Merge marina project in subdirectory marina/
authorAdam Megacz <adam@megacz.com>
Thu, 23 Jul 2009 23:07:38 +0000 (16:07 -0700)
committerAdam Megacz <adam@megacz.com>
Thu, 23 Jul 2009 23:07:38 +0000 (16:07 -0700)
486 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
bee2-selectmap/.svn/entries [new file with mode: 0644]
bee2-selectmap/.svn/format [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/Makefile.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/README.txt.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.edn.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/main.ucf.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/main.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/main.xst.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/main_counterexample_map0.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/main_counterexample_map1.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/makemaps.pl.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/remote_run.pl.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/prop-base/root.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/Makefile.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/Makefile_interchip0.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/Makefile_interchip1.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/Makefile_userfpga.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/README.txt.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/async_fifo_8_8_128.edn.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/async_fifo_8_8_128.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main.ucf.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main.ut.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main.xst.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main_counterexample_map0.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/main_counterexample_map1.v.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/makemaps.pl.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/remote_run.pl.svn-base [new file with mode: 0644]
bee2-selectmap/.svn/text-base/root.v.svn-base [new file with mode: 0644]
bee2-selectmap/Makefile [new file with mode: 0644]
bee2-selectmap/Makefile_interchip0 [new file with mode: 0644]
bee2-selectmap/Makefile_interchip1 [new file with mode: 0644]
bee2-selectmap/Makefile_userfpga [new file with mode: 0644]
bee2-selectmap/README.txt [new file with mode: 0644]
bee2-selectmap/async_fifo_8_8_128.edn [new file with mode: 0644]
bee2-selectmap/async_fifo_8_8_128.v [new file with mode: 0644]
bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc [new file with mode: 0644]
bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn [new file with mode: 0644]
bee2-selectmap/main.ucf [new file with mode: 0644]
bee2-selectmap/main.ut [new file with mode: 0644]
bee2-selectmap/main.v [new file with mode: 0644]
bee2-selectmap/main.xst [new file with mode: 0644]
bee2-selectmap/main_counterexample_map0.v [new file with mode: 0644]
bee2-selectmap/main_counterexample_map1.v [new file with mode: 0644]
bee2-selectmap/makemaps.pl [new file with mode: 0644]
bee2-selectmap/remote_run.pl [new file with mode: 0644]
bee2-selectmap/root.v [new file with mode: 0644]
campus.png [new file with mode: 0644]
contrib/bubblesort.fleet [new file with mode: 0644]
contrib/demo.f0 [new file with mode: 0644]
contrib/demo.fleet [new file with mode: 0644]
contrib/f0/Compile.lhs [new file with mode: 0644]
contrib/f0/Fleet.lhs [new file with mode: 0644]
contrib/f0/Main.lhs [new file with mode: 0644]
contrib/f0/Types.lhs [new file with mode: 0644]
contrib/f0/Util.lhs [new file with mode: 0644]
contrib/f0/f0.g [new file with mode: 0644]
contrib/flow-control-example.fleet [new file with mode: 0644]
contrib/fpga-demo.fa [new file with mode: 0644]
contrib/ps3-1b.fleet [new file with mode: 0644]
contrib/sort.fleet [new file with mode: 0644]
doc/archman.bib [new file with mode: 0644]
doc/archman.tex [new file with mode: 0644]
doc/bytefield.sty [new file with mode: 0644]
doc/javadoc.css [new file with mode: 0644]
doc/locations.svg [new file with mode: 0644]
doc/ports.svg [new file with mode: 0644]
doc/register.sty [new file with mode: 0644]
doc/toolchain.tex [new file with mode: 0644]
lib/HSbase.jar [new file with mode: 0644]
lib/HSrts.jar [new file with mode: 0644]
lib/HSstm.jar [new file with mode: 0644]
lib/RXTXcomm.jar [new file with mode: 0644]
lib/SBP.lhs [new file with mode: 0644]
lib/edu.berkeley.sbp.jar [new file with mode: 0644]
lib/ibex.jar [new file with mode: 0644]
lib/librxtxSerial.jnilib [new file with mode: 0644]
marina/blockDiagram.pdf [new file with mode: 0755]
marina/electric/aMarinaM.jelib [moved from electric/aMarinaM.jelib with 100% similarity]
marina/electric/arbiterM.jelib [moved from electric/arbiterM.jelib with 100% similarity]
marina/electric/basic.jelib [moved from electric/basic.jelib with 100% similarity]
marina/electric/calibre/tpdn90g18_3.spi [moved from electric/calibre/tpdn90g18_3.spi with 100% similarity]
marina/electric/centersJ.jelib [moved from electric/centersJ.jelib with 100% similarity]
marina/electric/compareM.jelib [moved from electric/compareM.jelib with 100% similarity]
marina/electric/countersL.jelib [moved from electric/countersL.jelib with 100% similarity]
marina/electric/coversM.jelib [moved from electric/coversM.jelib with 100% similarity]
marina/electric/crTest.jelib [moved from electric/crTest.jelib with 100% similarity]
marina/electric/dockM.jelib [moved from electric/dockM.jelib with 100% similarity]
marina/electric/dockPartsM.jelib [moved from electric/dockPartsM.jelib with 100% similarity]
marina/electric/driversM.jelib [moved from electric/driversM.jelib with 100% similarity]
marina/electric/dukeF.jelib [moved from electric/dukeF.jelib with 100% similarity]
marina/electric/edgesM.jelib [moved from electric/edgesM.jelib with 100% similarity]
marina/electric/esdTest.jelib [moved from electric/esdTest.jelib with 100% similarity]
marina/electric/fanPinsM.jelib [moved from electric/fanPinsM.jelib with 100% similarity]
marina/electric/fillM.jelib [moved from electric/fillM.jelib with 100% similarity]
marina/electric/gaspM.jelib [moved from electric/gaspM.jelib with 100% similarity]
marina/electric/gates1inM.jelib [moved from electric/gates1inM.jelib with 100% similarity]
marina/electric/gates2inM.jelib [moved from electric/gates2inM.jelib with 100% similarity]
marina/electric/gates3inM.jelib [moved from electric/gates3inM.jelib with 100% similarity]
marina/electric/jtagController.jelib [moved from electric/jtagController.jelib with 100% similarity]
marina/electric/jtagControllerAutoGenLib.jelib [moved from electric/jtagControllerAutoGenLib.jelib with 100% similarity]
marina/electric/jtagScan.jelib [moved from electric/jtagScan.jelib with 100% similarity]
marina/electric/kesselsCounter.jelib [moved from electric/kesselsCounter.jelib with 100% similarity]
marina/electric/latchGroupsK.jelib [moved from electric/latchGroupsK.jelib with 100% similarity]
marina/electric/latchPartsK.jelib [moved from electric/latchPartsK.jelib with 100% similarity]
marina/electric/latchesK.jelib [moved from electric/latchesK.jelib with 100% similarity]
marina/electric/loopCountM.jelib [moved from electric/loopCountM.jelib with 100% similarity]
marina/electric/marina_padframe.delib/PRS0816CDG_18.ic [moved from electric/marina_padframe.delib/PRS0816CDG_18.ic with 100% similarity]
marina/electric/marina_padframe.delib/PRS0816CDG_18.sch [moved from electric/marina_padframe.delib/PRS0816CDG_18.sch with 100% similarity]
marina/electric/marina_padframe.delib/PVDD1CDG_18.ic [moved from electric/marina_padframe.delib/PVDD1CDG_18.ic with 100% similarity]
marina/electric/marina_padframe.delib/PVDD1CDG_18.sch [moved from electric/marina_padframe.delib/PVDD1CDG_18.sch with 100% similarity]
marina/electric/marina_padframe.delib/PVDD2CDG_18.ic [moved from electric/marina_padframe.delib/PVDD2CDG_18.ic with 100% similarity]
marina/electric/marina_padframe.delib/PVDD2CDG_18.sch [moved from electric/marina_padframe.delib/PVDD2CDG_18.sch with 100% similarity]
marina/electric/marina_padframe.delib/PVDD2POC_18.ic [moved from electric/marina_padframe.delib/PVDD2POC_18.ic with 100% similarity]
marina/electric/marina_padframe.delib/PVDD2POC_18.sch [moved from electric/marina_padframe.delib/PVDD2POC_18.sch with 100% similarity]
marina/electric/marina_padframe.delib/PVSS3CDG_18.ic [moved from electric/marina_padframe.delib/PVSS3CDG_18.ic with 100% similarity]
marina/electric/marina_padframe.delib/PVSS3CDG_18.sch [moved from electric/marina_padframe.delib/PVSS3CDG_18.sch with 100% similarity]
marina/electric/marina_padframe.delib/TIEHI.ic [moved from electric/marina_padframe.delib/TIEHI.ic with 100% similarity]
marina/electric/marina_padframe.delib/TIEHI.lay [moved from electric/marina_padframe.delib/TIEHI.lay with 100% similarity]
marina/electric/marina_padframe.delib/TIEHI.sch [moved from electric/marina_padframe.delib/TIEHI.sch with 100% similarity]
marina/electric/marina_padframe.delib/TIELO.ic [moved from electric/marina_padframe.delib/TIELO.ic with 100% similarity]
marina/electric/marina_padframe.delib/TIELO.lay [moved from electric/marina_padframe.delib/TIELO.lay with 100% similarity]
marina/electric/marina_padframe.delib/TIELO.sch [moved from electric/marina_padframe.delib/TIELO.sch with 100% similarity]
marina/electric/marina_padframe.delib/config_input.ic [moved from electric/marina_padframe.delib/config_input.ic with 100% similarity]
marina/electric/marina_padframe.delib/config_input.lay [moved from electric/marina_padframe.delib/config_input.lay with 100% similarity]
marina/electric/marina_padframe.delib/config_input.sch [moved from electric/marina_padframe.delib/config_input.sch with 100% similarity]
marina/electric/marina_padframe.delib/config_output.ic [moved from electric/marina_padframe.delib/config_output.ic with 100% similarity]
marina/electric/marina_padframe.delib/config_output.lay [moved from electric/marina_padframe.delib/config_output.lay with 100% similarity]
marina/electric/marina_padframe.delib/config_output.sch [moved from electric/marina_padframe.delib/config_output.sch with 100% similarity]
marina/electric/marina_padframe.delib/core_dummy_excl.lay [moved from electric/marina_padframe.delib/core_dummy_excl.lay with 100% similarity]
marina/electric/marina_padframe.delib/fill_analog_gap_north.lay [moved from electric/marina_padframe.delib/fill_analog_gap_north.lay with 100% similarity]
marina/electric/marina_padframe.delib/header [moved from electric/marina_padframe.delib/header with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads.lay.deleted [moved from electric/marina_padframe.delib/infinity_pads.lay.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads.sch.deleted [moved from electric/marina_padframe.delib/infinity_pads.sch.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dmy_guts.lay [moved from electric/marina_padframe.delib/infinity_pads_dmy_guts.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dmy_guts.sch [moved from electric/marina_padframe.delib/infinity_pads_dmy_guts.sch with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dmy_guts_DM.lay [moved from electric/marina_padframe.delib/infinity_pads_dmy_guts_DM.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dmy_guts_DODPO.lay [moved from electric/marina_padframe.delib/infinity_pads_dmy_guts_DODPO.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts.lay [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts.lay.deleted [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts.lay.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts.sch [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts.sch with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts.sch.deleted [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts.sch.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts_DM.lay.deleted [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts_DM.lay.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts_DODPO.lay.deleted [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts_DODPO.lay.deleted with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts_with_power.lay [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts_with_power.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_dummy_guts_with_power.sch [moved from electric/marina_padframe.delib/infinity_pads_dummy_guts_with_power.sch with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_guts.lay [moved from electric/marina_padframe.delib/infinity_pads_guts.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_guts.sch [moved from electric/marina_padframe.delib/infinity_pads_guts.sch with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_guts_DM.lay [moved from electric/marina_padframe.delib/infinity_pads_guts_DM.lay with 100% similarity]
marina/electric/marina_padframe.delib/infinity_pads_guts_DODPO.lay [moved from electric/marina_padframe.delib/infinity_pads_guts_DODPO.lay with 100% similarity]
marina/electric/marina_padframe.delib/marinaPadframe.lay [moved from electric/marina_padframe.delib/marinaPadframe.lay with 100% similarity]
marina/electric/marina_padframe.delib/marinaPadframe.sch [moved from electric/marina_padframe.delib/marinaPadframe.sch with 100% similarity]
marina/electric/marina_padframe.delib/marinaPadframe_DM.lay [moved from electric/marina_padframe.delib/marinaPadframe_DM.lay with 100% similarity]
marina/electric/marina_padframe.delib/marinaPadframe_DODPO.lay [moved from electric/marina_padframe.delib/marinaPadframe_DODPO.lay with 100% similarity]
marina/electric/marina_padframe.delib/marina_pads_dmy_guts.lay [moved from electric/marina_padframe.delib/marina_pads_dmy_guts.lay with 100% similarity]
marina/electric/marina_padframe.delib/marina_pads_dmy_guts.sch [moved from electric/marina_padframe.delib/marina_pads_dmy_guts.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_east.ic [moved from electric/marina_padframe.delib/pads_east.ic with 100% similarity]
marina/electric/marina_padframe.delib/pads_east.lay [moved from electric/marina_padframe.delib/pads_east.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_east.sch [moved from electric/marina_padframe.delib/pads_east.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_looptest.ic [moved from electric/marina_padframe.delib/pads_looptest.ic with 100% similarity]
marina/electric/marina_padframe.delib/pads_looptest.lay [moved from electric/marina_padframe.delib/pads_looptest.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_looptest.sch [moved from electric/marina_padframe.delib/pads_looptest.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_north.ic [moved from electric/marina_padframe.delib/pads_north.ic with 100% similarity]
marina/electric/marina_padframe.delib/pads_north.lay [moved from electric/marina_padframe.delib/pads_north.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_north.sch [moved from electric/marina_padframe.delib/pads_north.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_south.ic [moved from electric/marina_padframe.delib/pads_south.ic with 100% similarity]
marina/electric/marina_padframe.delib/pads_south.lay [moved from electric/marina_padframe.delib/pads_south.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_south.sch [moved from electric/marina_padframe.delib/pads_south.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_southTEST.lay.deleted [moved from electric/marina_padframe.delib/pads_southTEST.lay.deleted with 100% similarity]
marina/electric/marina_padframe.delib/pads_test.lay [moved from electric/marina_padframe.delib/pads_test.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_test.sch [moved from electric/marina_padframe.delib/pads_test.sch with 100% similarity]
marina/electric/marina_padframe.delib/pads_west.ic [moved from electric/marina_padframe.delib/pads_west.ic with 100% similarity]
marina/electric/marina_padframe.delib/pads_west.lay [moved from electric/marina_padframe.delib/pads_west.lay with 100% similarity]
marina/electric/marina_padframe.delib/pads_west.sch [moved from electric/marina_padframe.delib/pads_west.sch with 100% similarity]
marina/electric/marina_padframe.delib/ring.lay [moved from electric/marina_padframe.delib/ring.lay with 100% similarity]
marina/electric/marina_padframe.delib/ring.lay.deleted [moved from electric/marina_padframe.delib/ring.lay.deleted with 100% similarity]
marina/electric/moveM.jelib [moved from electric/moveM.jelib with 100% similarity]
marina/electric/omegaCounter.jelib [moved from electric/omegaCounter.jelib with 100% similarity]
marina/electric/oneHotM.jelib [moved from electric/oneHotM.jelib with 100% similarity]
marina/electric/orangeTSMC090nm.jelib [moved from electric/orangeTSMC090nm.jelib with 100% similarity]
marina/electric/orangeTSMC090nm_pads.jelib [moved from electric/orangeTSMC090nm_pads.jelib with 100% similarity]
marina/electric/padframe_r3.jelib [moved from electric/padframe_r3.jelib with 100% similarity]
marina/electric/padframe_r3_gds.jelib [moved from electric/padframe_r3_gds.jelib with 100% similarity]
marina/electric/predicateM.jelib [moved from electric/predicateM.jelib with 100% similarity]
marina/electric/programPartsM.jelib [moved from electric/programPartsM.jelib with 100% similarity]
marina/electric/programsM.jelib [moved from electric/programsM.jelib with 100% similarity]
marina/electric/projsettings.xml [moved from electric/projsettings.xml with 100% similarity]
marina/electric/purpleFive.jelib [moved from electric/purpleFive.jelib with 100% similarity]
marina/electric/redFive.jelib [moved from electric/redFive.jelib with 100% similarity]
marina/electric/registersM.jelib [moved from electric/registersM.jelib with 100% similarity]
marina/electric/scanM.jelib [moved from electric/scanM.jelib with 100% similarity]
marina/electric/stageGroupsM.jelib [moved from electric/stageGroupsM.jelib with 100% similarity]
marina/electric/stagesM.jelib [moved from electric/stagesM.jelib with 100% similarity]
marina/electric/testsM.jelib [moved from electric/testsM.jelib with 100% similarity]
marina/electric/tinyCounter.jelib [moved from electric/tinyCounter.jelib with 100% similarity]
marina/electric/tpdn90g18.jelib [moved from electric/tpdn90g18.jelib with 100% similarity]
marina/electric/tpdn90g18_3.spi [moved from electric/tpdn90g18_3.spi with 100% similarity]
marina/electric/tsmc90Header.hsp [moved from electric/tsmc90Header.hsp with 100% similarity]
marina/electric/tsmcN90lo.jelib [moved from electric/tsmcN90lo.jelib with 100% similarity]
marina/electric/wiresL.jelib [moved from electric/wiresL.jelib with 100% similarity]
marina/lib/test.jar [moved from lib/test.jar with 100% similarity]
marina/logo/cal.logo.png [new file with mode: 0644]
marina/logo/marina-logo.png [new file with mode: 0644]
marina/logo/marina-logo.svg [new file with mode: 0644]
marina/logo/marina-logo.xcf [new file with mode: 0644]
marina/logo/metal9.png [new file with mode: 0644]
marina/logo/photo.jpeg [new file with mode: 0644]
marina/logo/sun.logo.pdf [new file with mode: 0644]
marina/logo/sun.logo.png [new file with mode: 0644]
marina/logo/title.png [new file with mode: 0644]
marina/logo/viram.logo.png [new file with mode: 0644]
marina/tapeout.jpeg [new file with mode: 0644]
marina/tapeout2.jpeg [new file with mode: 0644]
marina/testCode/am33-latest.pdf [moved from testCode/am33-latest.pdf with 100% similarity]
marina/testCode/cfg [moved from testCode/cfg with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/BitVectorGenerators.java [moved from testCode/com/sun/vlsi/chips/marina/test/BitVectorGenerators.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/ChainControls.java [moved from testCode/com/sun/vlsi/chips/marina/test/ChainControls.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/CmdArgs.java [moved from testCode/com/sun/vlsi/chips/marina/test/CmdArgs.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/Counter.java [moved from testCode/com/sun/vlsi/chips/marina/test/Counter.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/Design.java [moved from testCode/com/sun/vlsi/chips/marina/test/Design.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/Indenter.java [moved from testCode/com/sun/vlsi/chips/marina/test/Indenter.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/InstructionStopper.java [moved from testCode/com/sun/vlsi/chips/marina/test/InstructionStopper.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/Marina.java [moved from testCode/com/sun/vlsi/chips/marina/test/Marina.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/MarinaPacket.java [moved from testCode/com/sun/vlsi/chips/marina/test/MarinaPacket.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/MarinaTest.java [moved from testCode/com/sun/vlsi/chips/marina/test/MarinaTest.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/MarinaUtils.java [moved from testCode/com/sun/vlsi/chips/marina/test/MarinaUtils.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/ProperStopper.java [moved from testCode/com/sun/vlsi/chips/marina/test/ProperStopper.java with 100% similarity]
marina/testCode/com/sun/vlsi/chips/marina/test/Station.java [moved from testCode/com/sun/vlsi/chips/marina/test/Station.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/BitVector.java [moved from testCode/edu/berkeley/fleet/api/BitVector.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/DeferredBitVector.java [moved from testCode/edu/berkeley/fleet/api/DeferredBitVector.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Destination.java [moved from testCode/edu/berkeley/fleet/api/Destination.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Dock.java [moved from testCode/edu/berkeley/fleet/api/Dock.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Fleet.java [moved from testCode/edu/berkeley/fleet/api/Fleet.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/FleetProcess.java [moved from testCode/edu/berkeley/fleet/api/FleetProcess.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Instruction.java [moved from testCode/edu/berkeley/fleet/api/Instruction.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Path.java [moved from testCode/edu/berkeley/fleet/api/Path.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Predicate.java [moved from testCode/edu/berkeley/fleet/api/Predicate.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/Ship.java [moved from testCode/edu/berkeley/fleet/api/Ship.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/api/package.html [moved from testCode/edu/berkeley/fleet/api/package.html with 100% similarity]
marina/testCode/edu/berkeley/fleet/marina/MarinaDestination.java [moved from testCode/edu/berkeley/fleet/marina/MarinaDestination.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/marina/MarinaDock.java [moved from testCode/edu/berkeley/fleet/marina/MarinaDock.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/marina/MarinaFleet.java [moved from testCode/edu/berkeley/fleet/marina/MarinaFleet.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/marina/MarinaPath.java [moved from testCode/edu/berkeley/fleet/marina/MarinaPath.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/marina/MarinaShip.java [moved from testCode/edu/berkeley/fleet/marina/MarinaShip.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/DockDescription.java [moved from testCode/edu/berkeley/fleet/two/DockDescription.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/FleetTwoDock.java [moved from testCode/edu/berkeley/fleet/two/FleetTwoDock.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/FleetTwoFleet.java [moved from testCode/edu/berkeley/fleet/two/FleetTwoFleet.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/FleetTwoPath.java [moved from testCode/edu/berkeley/fleet/two/FleetTwoPath.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/FleetTwoShip.java [moved from testCode/edu/berkeley/fleet/two/FleetTwoShip.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/PercolatedPort.java [moved from testCode/edu/berkeley/fleet/two/PercolatedPort.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/two/ShipDescription.java [moved from testCode/edu/berkeley/fleet/two/ShipDescription.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/util/BitManipulations.java [moved from testCode/edu/berkeley/fleet/util/BitManipulations.java with 100% similarity]
marina/testCode/edu/berkeley/fleet/util/Mask.java [moved from testCode/edu/berkeley/fleet/util/Mask.java with 100% similarity]
marina/testCode/hardwareBugs.txt [moved from testCode/hardwareBugs.txt with 100% similarity]
marina/testCode/header.hsp [moved from testCode/header.hsp with 100% similarity]
marina/testCode/marina-netlist1.bsh [moved from testCode/marina-netlist1.bsh with 100% similarity]
marina/testCode/marina-netlist2.bsh [moved from testCode/marina-netlist2.bsh with 100% similarity]
marina/testCode/marina-xml1.bsh [moved from testCode/marina-xml1.bsh with 100% similarity]
marina/testCode/marina-xml2.bsh [moved from testCode/marina-xml2.bsh with 100% similarity]
marina/testCode/rebuild.sh [moved from testCode/rebuild.sh with 100% similarity]
marina/testCode/runOne.sh [moved from testCode/runOne.sh with 100% similarity]
marina/testCode/sml2008-am01.pdf [moved from testCode/sml2008-am01.pdf with 100% similarity]
marina/testCode/testDescriptions.txt [moved from testCode/testDescriptions.txt with 100% similarity]
misc/Makefile [new file with mode: 0644]
misc/README [new file with mode: 0644]
misc/config.c [new file with mode: 0644]
misc/config.h [new file with mode: 0644]
misc/index.html [new file with mode: 0644]
misc/jtagkey.c [new file with mode: 0644]
misc/jtagkey.h [new file with mode: 0644]
misc/jtagmon.c [new file with mode: 0644]
misc/jtagmon.h [new file with mode: 0644]
misc/libusb-driverrc [new file with mode: 0644]
misc/obsolete-ships/Alu1.ship [new file with mode: 0644]
misc/obsolete-ships/Alu3.ship [new file with mode: 0644]
misc/obsolete-ships/ArithmeticShip.java [new file with mode: 0644]
misc/obsolete-ships/Counter.java [new file with mode: 0644]
misc/obsolete-ships/DDR2.ship [new file with mode: 0644]
misc/obsolete-ships/DeMux.java [new file with mode: 0644]
misc/obsolete-ships/Dup.java [new file with mode: 0644]
misc/obsolete-ships/Dup3.java [new file with mode: 0644]
misc/obsolete-ships/DuplicatorShip.java [new file with mode: 0644]
misc/obsolete-ships/HomeworkCounter.java [new file with mode: 0644]
misc/obsolete-ships/MemoryReadShip.java [new file with mode: 0644]
misc/obsolete-ships/MemoryWriteShip.java [new file with mode: 0644]
misc/obsolete-ships/MultiplierShip.java [new file with mode: 0644]
misc/obsolete-ships/Mux.java [new file with mode: 0644]
misc/obsolete-ships/ScatterShip.java [new file with mode: 0644]
misc/obsolete-ships/Sort2.java [new file with mode: 0644]
misc/obsolete-ships/Stack.ship [new file with mode: 0644]
misc/parport.c [new file with mode: 0644]
misc/parport.h [new file with mode: 0644]
misc/program.sh [new file with mode: 0755]
misc/usb-driver.c [new file with mode: 0644]
misc/usb-driver.h [new file with mode: 0644]
ships/Alu.ship [new file with mode: 0644]
ships/Button.ship [new file with mode: 0644]
ships/CarrySaveAdder.ship [new file with mode: 0644]
ships/Counter.ship [new file with mode: 0644]
ships/DDR2.ship [new file with mode: 0644]
ships/DDR2.ship- [new file with mode: 0644]
ships/DRAM.ship [new file with mode: 0644]
ships/Debug.ship [new file with mode: 0644]
ships/Dvi.ship [new file with mode: 0644]
ships/Fifo.ship [new file with mode: 0644]
ships/Lut3.ship [new file with mode: 0644]
ships/Memory.ship [new file with mode: 0644]
ships/Null.ship [new file with mode: 0644]
ships/Random.ship [new file with mode: 0644]
ships/Rotator.ship [new file with mode: 0644]
ships/Timer.ship [new file with mode: 0644]
ships/Video.ship [new file with mode: 0644]
src/edu/berkeley/fleet/Main.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/BitVector.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/DeferredBitVector.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Destination.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Dock.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Fleet.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/FleetProcess.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Instruction.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Path.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Predicate.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/Ship.java [new file with mode: 0644]
src/edu/berkeley/fleet/api/package.html [new file with mode: 0644]
src/edu/berkeley/fleet/assembler/Main.java [new file with mode: 0644]
src/edu/berkeley/fleet/assembler/Parser.java [new file with mode: 0644]
src/edu/berkeley/fleet/assembler/fleet.g [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/AluNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DataFlowGraph.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DebugNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DiscardNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DoneNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DownCounterNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/DropNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/FifoNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/ForeverNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/Lut3Node.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/MemoryNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/MergeSort.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/Node.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/OnceNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/ParameterNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/PunctuatorNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/RandomNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/RepeatNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/SortedMergeNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/Client.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FabricElement.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FanoutModule.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FifoModule.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/Fpga.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FpgaDestination.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FpgaDock.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FpgaPath.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FpgaShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/FunnelModule.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/HornModule.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/Server.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/bram.inc [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_chipscope.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_ctrl.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_idelay_ctrl.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_infrastructure.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_mem_if_top.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_calib.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_ctl_io.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dm_iob.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dq_iob.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dqs_iob.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_init.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_io.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_top.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_write.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_sdram.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_top.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_addr_fifo.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_rd.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_top.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_wr.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/dvi/i2c_core.vhd [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/dvi/i2c_video_programmer.vhd [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/dvi/vga_timing_generator.vhd [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/async_fifo.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_clkgen.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_ctrl.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_include.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_init.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_pulse78.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_rpath.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/ddr_wpath.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/gray_counter.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/rotary.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/sasc_brg.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/sasc_fifo4.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/sasc_top.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/mem/wb_vga.v [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ramfifo.inc [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/verilog/Verilog.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/zbt/zbt_top.vhd [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/DebugDock.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/Interpreter.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/InterpreterDestination.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/InterpreterDock.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/InterpreterPath.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/InterpreterShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/Log.java [new file with mode: 0644]
src/edu/berkeley/fleet/interpreter/Packet.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/CleanupUtils.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/CodeBag.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/LoopFactory.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/MemoryUtils.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/Program.java [new file with mode: 0644]
src/edu/berkeley/fleet/loops/ShipPool.java [new file with mode: 0644]
src/edu/berkeley/fleet/marina/MarinaDestination.java [new file with mode: 0644]
src/edu/berkeley/fleet/marina/MarinaDock.java [new file with mode: 0644]
src/edu/berkeley/fleet/marina/MarinaFleet.java [new file with mode: 0644]
src/edu/berkeley/fleet/marina/MarinaPath.java [new file with mode: 0644]
src/edu/berkeley/fleet/marina/MarinaShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/DockDescription.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/FleetTwoDock.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/FleetTwoFleet.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/FleetTwoPath.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/FleetTwoShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/PercolatedPort.java [new file with mode: 0644]
src/edu/berkeley/fleet/two/ShipDescription.java [new file with mode: 0644]
src/edu/berkeley/fleet/util/BitManipulations.java [new file with mode: 0644]
src/edu/berkeley/fleet/util/BitMask.java [new file with mode: 0644]
src/edu/berkeley/fleet/util/Mask.java [new file with mode: 0644]
tests/codebags/fun-with-codebags.fleet [new file with mode: 0644]
tests/codebags/fun-with-codebags2.fleet [new file with mode: 0644]
tests/codebags/torpedoing-loops.fleet [new file with mode: 0644]
tests/colliding-tokens.test [new file with mode: 0644]
tests/dock/literal-at-pump.fleet [new file with mode: 0644]
tests/dock/one-instruction-loop.fleet [new file with mode: 0644]
tests/dock/predicate-olc-equals-zero.fleet [new file with mode: 0644]
tests/dock/pump+ [new file with mode: 0644]
tests/dock/send-without-destination.fleet- [new file with mode: 0644]
tests/dock/shift-outbox.test [new file with mode: 0644]
tests/dock/shift.test [new file with mode: 0644]
tests/dock/test-count.fleet [new file with mode: 0644]
tests/dock/test-repeat-counter-from-data-latch.fleet [new file with mode: 0644]
tests/dock/test-repeat-counter.fleet [new file with mode: 0644]
tests/dock/test-repeat-zero.fleet [new file with mode: 0644]
tests/dock/test-use-loop-counter.fleet [new file with mode: 0644]
tests/flags/basic.test [new file with mode: 0644]
tests/flags/c-flag-determined-by-dc.test [new file with mode: 0644]
tests/flags/flags-ab-1.test [new file with mode: 0644]
tests/flags/flags-ab-2.test [new file with mode: 0644]
tests/flags/flags-ab-3.test [new file with mode: 0644]
tests/flags/flags-ab-4.test [new file with mode: 0644]
tests/flags/flags-ab-5.test [new file with mode: 0644]
tests/flags/flags-ab-not-1.test [new file with mode: 0644]
tests/flags/flags-ab-not-2.test [new file with mode: 0644]
tests/flags/flags-ab-not-3.test [new file with mode: 0644]
tests/flags/flags-ab-not-4.test [new file with mode: 0644]
tests/flags/flags-ab-not-5.test [new file with mode: 0644]
tests/flags/flags-reset.test [new file with mode: 0644]
tests/flags/signal-0-from-inbox-to-inbox.test [new file with mode: 0644]
tests/flags/signal-0-from-inbox-to-outbox.test.test [new file with mode: 0644]
tests/flags/signal-0-from-outbox-to-inbox.test [new file with mode: 0644]
tests/flags/signal-0-from-outbox-to-outbox.test.test [new file with mode: 0644]
tests/flags/signal-1-from-inbox-to-inbox.test [new file with mode: 0644]
tests/flags/signal-1-from-inbox-to-outbox.test.test [new file with mode: 0644]
tests/flags/signal-1-from-outbox-to-inbox.test [new file with mode: 0644]
tests/flags/signal-1-from-outbox-to-outbox.test.test [new file with mode: 0644]
tests/flush/flush-alu.test [new file with mode: 0644]
tests/flush/flush-debug.test [new file with mode: 0644]
tests/flush/flush-fifo.test [new file with mode: 0644]
tests/literals/negative-absolute-literals.fleet [new file with mode: 0644]
tests/memory/memory-test.fleet [new file with mode: 0644]
tests/multiply.test- [new file with mode: 0644]
tests/ndp/p-plus.fleet- [new file with mode: 0644]
tests/requeue/requeueing-literal.fleet [new file with mode: 0644]
tests/requeue/test-for-common-requeue-timing-error.fleet [new file with mode: 0644]
tests/requeue/test-requeue.fleet [new file with mode: 0644]
tests/torpedo/basic-torpedo-inbox.test [new file with mode: 0644]
tests/torpedo/basic-torpedo-outbox.test [new file with mode: 0644]
tests/torpedo/epilogue-fifo.test [new file with mode: 0644]
tests/torpedo/infinite-nop-is-torpedoable.fleet [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..cc8f8d7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,378 @@
+
+## Fleeterpreter ##############################################################################
+
+cp                = -cp fleet.jar:lib/RXTXcomm.jar
+java              = java -Xmx500m
+
+run: fleet.jar; $(java) $(cp) $(interpreter_class)
+
+ifeq ($(shell uname -o 2>/dev/null),Cygwin)
+ps=\;
+else
+ps=:
+endif
+
+java_files = $(shell find src -name \*.java)
+ship_files = $(shell find ships -name \*.ship)
+fleet.jar: $(java_files) $(ship_files) src/edu/berkeley/fleet/assembler/fleet.g
+       mkdir -p build/class/edu/berkeley/fleet/assembler/
+       cp src/edu/berkeley/fleet/assembler/fleet.g build/class/edu/berkeley/fleet/assembler/
+       javac -classpath lib/ibex.jar:lib/RXTXcomm.jar:lib/edu.berkeley.sbp.jar -d build/class/ $(shell find src -name \*.java)
+       cd build/class/; jar xf ../../lib/edu.berkeley.sbp.jar
+       cd build/class/; jar xf ../../lib/ibex.jar
+       for A in `find ships -name \*.ship`;\
+         do java -cp fleet.jar:build/class edu.berkeley.fleet.Main expand $$A;\
+         done
+       javac -classpath lib/ibex.jar:lib/RXTXcomm.jar:build/class${ps}lib/edu.berkeley.sbp.jar -d build/class/ `find build/java -name \*.java`
+       echo 'Main-Class: edu.berkeley.fleet.Main' > build/class/manifest
+       jar cmf build/class/manifest $@ ships -C build/class .
+
+
+## Fpga ####################################################################################
+
+# 32Gb ram, 4-core.     small-config:1019s  large-config:2530s
+host = intel2950-5.eecs.berkeley.edu
+
+# 128Gb ram, 2x4-core.  small-config:1189s  large-config:3065s
+#host = amdr905-1.eecs.berkeley.edu
+
+#remote_ise = /tools/xilinx/10.1/ISE
+#remote_edk = /tools/xilinx/10.1/EDK
+
+#remote_ise = /tools/xilinx/ISE9.1i_lin
+#remote_edk = /tools/xilinx/EDK9.1i
+
+#remote_dir = /vol/hitz/home/megacz/fleet/
+#remote_dir = /tmp/megacz/fleet/
+
+remote_dir = /scratch/megacz/fleet/
+remote_ise = /scratch/megacz/xilinx/10.1/ISE
+remote_edk = /scratch/megacz/xilinx/10.1/EDK
+
+#host = mm2.millennium.berkeley.edu
+#remote_ise = /scratch/megacz/xilinx/ise/
+#remote_edk = /scratch/megacz/xilinx/edk/
+#remote_dir = /scratch/megacz/fleet/
+
+
+xilinx =  cd build/fpga;
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(remote_ise)/bin/lin:$(remote_edk)/bin/lin
+xilinx += PATH=$$PATH:$(remote_ise)/bin/lin:$(remote_edk)/bin/lin
+#xilinx += XST_VERSION=9.2i
+xilinx += XILINX=$(remote_ise)
+xilinx += XIL_XST_HIDEMESSAGES=hdl_and_low_levels
+xilinx += XIL_PAR_DESIGN_CHECK_VERBOSE=1
+xilinx += XILINX_EDK=$(remote_edk)
+
+xilinx_ise = $(xilinx) $(remote_ise)/bin/lin/
+xilinx_edk = $(xilinx) $(remote_edk)/bin/lin/
+
+# ML50X
+speed_grade = 1
+part = xc5vlx110t
+package = ff1136
+board = ml505   # ??
+
+# ML410
+#part = xc4vfx60
+#package = ff1152
+#speed_grade = 11
+#board = ml410
+
+# BEE2
+#part = xc2vp70
+#package = 7ff1704
+
+device = ${part}${package}-${speed_grade}
+
+upload: fleet.jar build/fpga/main.bit
+       mkdir -p build
+       chmod +x misc/program.sh
+       rsync -are ssh --progress --verbose ./ root@goliath:fleet/
+
+build/fpga/main.bit: $(java_files) $(ship_files)
+       make fleet.jar
+       mkdir -p build/fpga
+       $(java) $(cp) edu.berkeley.fleet.fpga.Fpga build/fpga/
+       cp src/edu/berkeley/fleet/fpga/* build/fpga || true
+       for A in `find ships -name \*.ship`;\
+         do java -cp build/class edu.berkeley.fleet.Main target=fpga expand $$A;\
+         done
+       ssh ${host} 'mkdir -p ${remote_dir}'
+       rsync -zare ssh --progress --delete --verbose ./ ${host}:${remote_dir}
+       time ssh ${host} 'make -C ${remote_dir} synth XILINX=${remote_ise} remote_ise=${remote_ise} remote_edk=${remote_edk}'
+       scp ${host}:${remote_dir}/build/fpga/main.bit build/fpga/
+       scp ${host}:${remote_dir}/build/fpga/main.ace build/fpga/
+
+pcore = ${remote_edk}/hw/XilinxProcessorIPLib/pcores
+intstyle = -intstyle xflow
+effort = std
+#effort = high
+opt_for = area
+#opt_for = speed
+synth:
+       cd build/fpga; ln -sf ../../src/edu/berkeley/fleet/fpga/* .
+       cd build/fpga; ln -sf ../../src/edu/berkeley/fleet/fpga/mem/* .
+       cd build/fpga; ln -sf ../../src/edu/berkeley/fleet/fpga/ddr2/* .
+       cd build/fpga; ln -sf ../../src/edu/berkeley/fleet/fpga/dvi/* .
+       cd build/fpga; ln -sf ../../src/edu/berkeley/fleet/fpga/zbt/* .
+       rm -f build/fpga/main.lso
+       echo work                        >> build/fpga/main.lso
+       rm -f build/fpga/main.prj
+       cd build/fpga; for A in *.v;   do echo verilog work \""$$A"\"; done >> main.prj
+       cd build/fpga; for A in *.vhd; do echo vhdl    work \""$$A"\"; done >> main.prj
+       cd build/fpga; touch main.ini
+       cd build/fpga; mkdir -p tmp
+       cd build/fpga; mkdir -p xst
+       rm -rf build/fpga/_ngo
+       skill xst_original
+
+       rm -f build/fpga/main.xst
+       echo "set -tmpdir ./tmp" >> build/fpga/main.xst
+       echo "set -xsthdpdir ./xst" >> build/fpga/main.xst
+       echo "set -xsthdpini main.ini" >> build/fpga/main.xst
+       echo -n "run" >> build/fpga/main.xst
+       echo -n " -ifn main.prj" >> build/fpga/main.xst
+       echo -n " -ifmt mixed" >> build/fpga/main.xst
+       echo -n " -ofn main" >> build/fpga/main.xst
+       echo -n " -ofmt NGC" >> build/fpga/main.xst
+       echo -n " -p ${device}" >> build/fpga/main.xst
+       echo -n " -top main" >> build/fpga/main.xst
+       echo -n " -opt_mode ${opt_for}" >> build/fpga/main.xst
+       echo -n " -opt_level 2" >> build/fpga/main.xst
+       echo -n " -iuc NO" >> build/fpga/main.xst
+       echo -n " -lso main.lso" >> build/fpga/main.xst
+       echo -n " -keep_hierarchy NO" >> build/fpga/main.xst
+       echo -n " -rtlview Yes" >> build/fpga/main.xst
+       echo -n " -glob_opt AllClockNets" >> build/fpga/main.xst
+       echo -n " -read_cores YES" >> build/fpga/main.xst
+       echo -n " -write_timing_constraints NO" >> build/fpga/main.xst
+       echo -n " -cross_clock_analysis YES" >> build/fpga/main.xst
+       echo -n " -hierarchy_separator /" >> build/fpga/main.xst
+       echo -n " -bus_delimiter <>" >> build/fpga/main.xst
+       echo -n " -case maintain" >> build/fpga/main.xst
+       echo -n " -slice_utilization_ratio 100" >> build/fpga/main.xst
+       echo -n " -verilog2001 YES" >> build/fpga/main.xst
+       echo -n " -fsm_extract Yes" >> build/fpga/main.xst
+       echo -n " -fsm_encoding Auto" >> build/fpga/main.xst
+       echo -n " -safe_implementation No" >> build/fpga/main.xst
+       echo -n " -fsm_style lut" >> build/fpga/main.xst
+       echo -n " -ram_extract Yes" >> build/fpga/main.xst
+       echo -n " -ram_style Auto" >> build/fpga/main.xst
+       echo -n " -rom_extract Yes" >> build/fpga/main.xst
+       echo -n " -mux_style Auto" >> build/fpga/main.xst
+       echo -n " -decoder_extract YES" >> build/fpga/main.xst
+       echo -n " -priority_extract YES" >> build/fpga/main.xst
+       echo -n " -shreg_extract YES" >> build/fpga/main.xst
+       echo -n " -shift_extract YES" >> build/fpga/main.xst
+       echo -n " -xor_collapse YES" >> build/fpga/main.xst
+       echo -n " -rom_style Auto" >> build/fpga/main.xst
+       echo -n " -mux_extract YES" >> build/fpga/main.xst
+       echo -n " -resource_sharing YES" >> build/fpga/main.xst
+       echo -n " -mult_style auto" >> build/fpga/main.xst
+       echo -n " -iobuf YES" >> build/fpga/main.xst
+       echo -n " -max_fanout 10000" >> build/fpga/main.xst
+       echo -n " -bufg 1" >> build/fpga/main.xst
+       echo -n " -register_duplication YES" >> build/fpga/main.xst
+       echo -n " -register_balancing Yes" >> build/fpga/main.xst
+       echo -n " -slice_packing Yes" >> build/fpga/main.xst
+       echo -n " -optimize_primitives Yes" >> build/fpga/main.xst
+       echo -n " -tristate2logic Yes" >> build/fpga/main.xst
+       echo -n " -use_clock_enable Yes" >> build/fpga/main.xst
+       echo -n " -use_sync_set Yes" >> build/fpga/main.xst
+       echo -n " -use_sync_reset Yes" >> build/fpga/main.xst
+       echo -n " -iob auto" >> build/fpga/main.xst
+       echo -n " -equivalent_register_removal YES" >> build/fpga/main.xst
+       echo -n " -slice_utilization_ratio_maxmargin 5" >> build/fpga/main.xst
+       echo >> build/fpga/main.xst
+
+       rm -f build/fpga/main.ut
+       echo '-w' >> build/fpga/main.ut
+       echo '-g CclkPin:PULLUP' >> build/fpga/main.ut
+       echo '-g TdoPin:PULLNONE' >> build/fpga/main.ut
+       echo '-g M1Pin:PULLDOWN' >> build/fpga/main.ut
+       echo '-g DonePin:PULLUP' >> build/fpga/main.ut
+       echo '-g DriveDone:No' >> build/fpga/main.ut
+       echo '-g StartUpClk:JTAGCLK' >> build/fpga/main.ut
+       echo '-g DONE_cycle:4' >> build/fpga/main.ut
+       echo '-g GTS_cycle:5' >> build/fpga/main.ut
+       echo '-g M0Pin:PULLUP' >> build/fpga/main.ut
+       echo '-g M2Pin:PULLUP' >> build/fpga/main.ut
+       echo '-g ProgPin:PULLUP' >> build/fpga/main.ut
+       echo '-g TckPin:PULLUP' >> build/fpga/main.ut
+       echo '-g TdiPin:PULLUP' >> build/fpga/main.ut
+       echo '-g TmsPin:PULLUP' >> build/fpga/main.ut
+       echo '-g DonePipe:No' >> build/fpga/main.ut
+       echo '-g GWE_cycle:6' >> build/fpga/main.ut
+       echo '-g LCK_cycle:NoWait' >> build/fpga/main.ut
+       echo '-g Security:NONE' >> build/fpga/main.ut
+       echo '-g Persist:No' >> build/fpga/main.ut
+
+       $(xilinx_ise)xst      ${intstyle} -ifn main.xst -ofn main.syr < main.xst \
+         | grep --line-buffered -v 'been backward balanced into' \
+         | grep --line-buffered -v 'IDDR has been replaced by IDDR_2CLK' \
+         | grep --line-buffered -v 'WARNING:Xst:616 - Invalid property'
+       cat build/fpga/*.ucf > build/fpga/main.ucf
+       $(xilinx_ise)ngdbuild ${intstyle} -aul -dd _ngo -nt timestamp -uc main.ucf -p $(device) main.ngc main.ngd
+       $(xilinx_ise)map      ${intstyle} -ol ${effort} -p $(device) -pr b -cm ${opt_for} -o main_map.ncd main.ngd main.pcf
+       $(xilinx_ise)par      ${intstyle} -pl ${effort} -ol ${effort} -w main_map.ncd main.ncd main.pcf
+       $(xilinx_ise)trce     ${intstyle} -e 3 -l 3 -s ${speed_grade} -xml main main.ncd -o main.twr main.pcf
+       $(xilinx_ise)bitgen   ${intstyle} -f main.ut main.ncd
+       $(xilinx) tcl $(remote_edk)/data/xmd/genace.tcl -jprog -hw main.bit -board ${board} -ace mainx.ace
+       mv build/fpga/mainx.ace build/fpga/main.ace   # genace throws a fit if the filename prefix is the same?
+
+
+runserver: fleet.jar
+       java -Djava.library.path=lib -cp fleet.jar:lib/RXTXcomm.jar edu.berkeley.fleet.fpga.Server
+
+test:     fleet.jar; $(java) -jar fleet.jar             test ships/*.ship tests
+testfpga: fleet.jar; $(java) -jar fleet.jar target=fpga test ships/*.ship tests
+
+## Manual ####################################################################################
+
+svgs    = $(shell find doc -name \*.svg)
+%.eps: %.svg
+       DISPLAY= /Applications/Inkscape.app/Contents//Resources/bin/inkscape  -z --export-area-drawing $^ --export-eps=$@
+
+%.pdf: %.eps
+       epstopdf $^ --outfile=$@
+
+manual: archmanual toolmanual
+
+archmanual: fleet.jar $(svgs:%.svg=%.pdf)
+       $(java) -jar fleet.jar doc
+       cd .tmp; ln -sf ../doc/*.bib .
+       cd .tmp; TEXINPUTS=$$TEXINPUTS:../src/edu/berkeley/fleet/assembler/:../doc/ pdflatex FleetTwo.Manual.tex
+       cd .tmp; for A in *.mp; do mpost --tex=latex $$A; done
+       cd .tmp; TEXINPUTS=$$TEXINPUTS:../src/edu/berkeley/fleet/assembler/:../doc/ pdflatex FleetTwo.Manual.tex
+       open .tmp/FleetTwo.Manual.pdf
+toolmanual: fleet.jar $(svgs:%.svg=%.pdf)
+       $(java) -jar fleet.jar doc
+       cd .tmp; ln -sf ../doc/*.bib .
+       cd .tmp; TEXINPUTS=$$TEXINPUTS:../src/edu/berkeley/fleet/assembler/:../doc/ pdflatex toolchain.tex
+       open .tmp/toolchain.pdf
+
+## API docs ####################################################################################
+
+javadoc:
+       javadoc \
+               -linksource \
+               -windowtitle "FleetCode API Documentation" \
+               -sourcepath src \
+               -header "<b>FleetCode API Documentation</b><br>" \
+               -public \
+               -notree \
+               -nonavbar \
+               -noqualifier all \
+               -stylesheetfile doc/javadoc.css \
+               -d /afs/research.cs.berkeley.edu/class/fleet/website/code/javadoc/ \
+               edu.berkeley.fleet.api
+       javadoc \
+               -linksource \
+               -windowtitle "FleetCode API Documentation" \
+               -sourcepath src \
+               -header "<b>FleetCode API Documentation</b><br>" \
+               -public \
+               -notree \
+               -nonavbar \
+               -noqualifier all \
+               -stylesheetfile doc/javadoc.css \
+               -d /afs/research.cs.berkeley.edu/class/fleet/website/code/javadoc-private/ \
+               `find src/edu/berkeley/fleet -name \*.java`
+       open http://fleet.cs.berkeley.edu/code/javadoc/
+       open http://fleet.cs.berkeley.edu/code/javadoc-private/
+
+## Misc ####################################################################################
+
+clean:
+       rm -rf fleet.jar build
+
+## Dist ####################################################################################
+
+#dist:
+#      darcs record
+#      darcs push /afs/research.cs.berkeley.edu/class/fleet/website/repos/fleet/
+#      darcs get . --repo-name=fleet-`date +%d.%h.%y`
+#      make -C fleet-`date +%d.%h.%y` fleet.jar
+#      rm -rf fleet-`date +%d.%h.%y`/build
+#      echo 'http://research.cs.berkeley.edu/class/fleet/repos/fleet/' > \
+#        fleet-`date +%d.%h.%y`/_darcs/prefs/defaultrepo
+#      tar cvzf fleet-`date +%d.%h.%y`.tgz fleet-`date +%d.%h.%y`
+#      rm -rf fleet-`date +%d.%h.%y`
+#      mv fleet-`date +%d.%h.%y`.tgz /afs/research.cs.berkeley.edu/class/fleet/website/files/
+#      @echo
+#      @echo
+#      @echo   http://research.cs.berkeley.edu/class/fleet/files/fleet-`date +%d.%h.%y`.tgz
+#      @echo
+#      @echo
+#
+
+dist: fleet.jar
+       darcs dist -d fleet
+       mv fleet.tar.gz /afs/research.cs.berkeley.edu/class/fleet/website/code/snapshots/fleet-`date +%Y.%m.%d`.tgz
+       mkdir -p .build
+       rm -f lib/suncvs.jar
+       cd .build; for A in ../fleet.jar ../lib/*.jar; do jar xvf $$A; done
+       cd .build; jar cvf /afs/research.cs.berkeley.edu/class/fleet/website/code/snapshots/fleet-`date +%Y.%m.%d`.jar .
+       rm -rf .build
+       echo
+       echo http://fleet.cs.berkeley.edu/code/snapshots/fleet-`date +%Y.%m.%d`.jar 
+       echo
+
+# you'll probably want to change this line
+ghc  = /usr/local/brian/ghc/compiler/ghc-inplace
+
+ghc += -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances -cpp 
+ghc += -i$(shell pwd)/build/hi/ -hidir $(shell pwd)/build/hi/ -odir $(shell pwd)/build/class/
+
+f0: fleet.jar
+       mkdir -p build/hi build/class
+       cd lib;                        $(ghc) -c -java SBP.lhs
+       cd src/edu/berkeley/fleet/f0/; $(ghc) -fglasgow-exts -cpp $(hflags)    -java Util.lhs
+       cd src/edu/berkeley/fleet/f0/; $(ghc) -fglasgow-exts -cpp $(hflags)    -java Fleet.lhs
+       cd src/edu/berkeley/fleet/f0/; $(ghc) -fglasgow-exts -cpp $(hflags)    -java Types.lhs
+       cd src/edu/berkeley/fleet/f0/; $(ghc) -fglasgow-exts -cpp $(hflags)    -java Compile.lhs
+       cd src/edu/berkeley/fleet/f0/; $(ghc) -fglasgow-exts -cpp $(hflags)    -java Main.lhs
+       $(java) -cp build/class:lib/HSbase.jar:lib/HSrts.jar:lib/HSstm.jar:fleet.jar Main
+
+
+## Targets below are for integration with Sun-Proprietary Marina Test Chip ##############################
+
+cleansuncvs:
+       rm -rf lib/suncvs.jar suncvs
+
+lib/suncvs.jar: fleet.jar suncvs/marina suncvs/test
+       rm -rf suncvs/test/manuals
+       mkdir -p suncvs/build
+       for A in api marina two util; do rsync -a src/edu/berkeley/fleet/$$A/ suncvs/marina/testCode/edu/berkeley/fleet/$$A/; done
+       cd suncvs; javac -cp test/javamake.jar:test/jcommon.jar:test/jfreechart.jar -d build `find . -name \*.java`
+       cd suncvs/build; jar cvf ../../lib/suncvs.jar .
+       cd suncvs/test; jar uvf ../../lib/suncvs.jar .
+
+sun_server = frehley
+#sun_server = simmons
+
+runtest: fleet.jar
+       rm lib/suncvs.jar; make lib/suncvs.jar
+       cp lib/suncvs.jar suncvs/marina/testCode/MarinaTest.jar
+       ssh ${sun_server} 'skill nanosim'
+       rsync -are ssh --delete --progress --verbose ./ ${sun_server}:~/fleet/
+       ssh -Y ${sun_server} 'export PATH=/proj/async/cad/linux/bin/:$$PATH; cd ~/fleet/suncvs/marina/testCode; /proj/async/cad/linux/lib/jdk1.5.0_05-linux-i586/bin/java -cp $$HOME/fleet/lib/suncvs.jar com.sun.vlsi.chips.marina.test.MarinaTest -testNum 3'
+
+electric:
+       rsync -are ssh --progress --verbose ${sun_server}:fleet/suncvs/marina/testSims/marina.spi.out ~/marina.spi.out
+       java -Xmx900m -jar /Applications/electric.jar suncvs/marina/electric/aMarinaM.jelib
+
+suncvs/test:
+       mkdir -p suncvs
+       cd suncvs; cvs -d ${sun_server}:/import/async/cad/cvs co test
+
+suncvs/marina:
+       mkdir -p suncvs
+       cd suncvs; cvs -d ${sun_server}:/import/async/cad/cvs co marina
+
+chaing: lib/suncvs.jar
+       java -cp lib/suncvs.jar com.sun.async.test.ChainG suncvs/marina/testCode/marina.xml
+
+syncspi:
+       rsync -are ssh --progress --verbose frehley:fleet/suncvs/marina/testCode/marina.spi.out ~/marina.spi.out
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..4a041ba
--- /dev/null
+++ b/README
@@ -0,0 +1,18 @@
+== Fleet Code Distribution  =======================================================================
+
+Directories
+
+   Makefile
+   README                                    -- this file
+   doc/
+       api/                                  -- javadoc goes here
+   src/
+       edu/berkeley/fleet/
+                          api/               -- api classes
+                          interpreter/       -- fleet interpreter
+                          assembler/         -- assembler code
+                                    fleet.g  -- fleet grammar
+                          slipway/           -- code for Fleet-on-RAMP simulator
+   contrib/                                  -- sample code
+   lib/                                      -- jar libraries
+                                 
diff --git a/bee2-selectmap/.svn/entries b/bee2-selectmap/.svn/entries
new file mode 100644 (file)
index 0000000..6045a66
--- /dev/null
@@ -0,0 +1,260 @@
+8
+
+dir
+21519
+svn+ssh://repositorypub@repository.eecs.berkeley.edu/public/Projects/BEE/trunk/2/applications/selectmap
+svn+ssh://repositorypub@repository.eecs.berkeley.edu/public
+
+
+
+2008-03-10T21:26:36.416102Z
+5287
+gdgib
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+d478818c-914a-0410-a11c-fe9a00987c8c
+\f
+main_counterexample_map0.v
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+f3ae61405a249a98c87c62f5e20f82ef
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+has-props
+\f
+async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+7481fa6d30857930833924d3e6a7c89e
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+main_counterexample_map1.v
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+40d3bfdfcd9b7d4d388862e4bfdf3be2
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+has-props
+\f
+root.v
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+98fab79ebb3d036f4ec12452d86ed88d
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+main.v
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+f01cdb4fe9ffd56cb1a9a751b4de6669
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+remote_run.pl
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+b6f32853cd6525f227ab790d31eaf3e8
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+has-props
+\f
+async_fifo_8_8_128.v
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+a04fa924e54120de014641e535a32009
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+async_fifo_8_8_128.edn
+file
+
+
+
+
+2009-05-19T01:22:20.000000Z
+556d4b4725fa6abd34cd3b74493d55db
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+main.ucf
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+1e14a7495a24f74975ccaecbd497e20b
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+main.xst
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+87cda4d50a058462d22cef94ef8daa10
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
+Makefile_interchip0
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+2969fe71120b1958efe06fee573fe365
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+\f
+Makefile_interchip1
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+a7d06ff0081e24168fbee3d4eddc43ff
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+\f
+makemaps.pl
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+006ed915f2c77962c51c3664e9c44b3d
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+has-props
+\f
+Makefile_userfpga
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+d73d4c40db73a17c5bc017e2b1aa1380
+2007-10-24T05:14:46.000000Z
+1102
+tracyx
+\f
+main.ut
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+5e612967fe3c34aa0c618f0945aeae83
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+\f
+README.txt
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+a978e712d9d32880d33887b29a005500
+2008-02-05T23:50:57.000000Z
+1160
+tracyx
+has-props
+\f
+control_fpga
+dir
+\f
+async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+2d8f5db3059d314cd50378256896ec1c
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+\f
+Makefile
+file
+
+
+
+
+2009-05-19T01:22:21.000000Z
+375b6e3f3eb4ecc24ef8fbc23d1c009b
+2007-09-14T22:27:52.000000Z
+1095
+gdgib
+has-props
+\f
diff --git a/bee2-selectmap/.svn/format b/bee2-selectmap/.svn/format
new file mode 100644 (file)
index 0000000..45a4fb7
--- /dev/null
@@ -0,0 +1 @@
+8
diff --git a/bee2-selectmap/.svn/prop-base/Makefile.svn-base b/bee2-selectmap/.svn/prop-base/Makefile.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/README.txt.svn-base b/bee2-selectmap/.svn/prop-base/README.txt.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.edn.svn-base b/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.edn.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.v.svn-base b/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128.v.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base b/bee2-selectmap/.svn/prop-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/main.ucf.svn-base b/bee2-selectmap/.svn/prop-base/main.ucf.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/main.v.svn-base b/bee2-selectmap/.svn/prop-base/main.v.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/main.xst.svn-base b/bee2-selectmap/.svn/prop-base/main.xst.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/main_counterexample_map0.v.svn-base b/bee2-selectmap/.svn/prop-base/main_counterexample_map0.v.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/main_counterexample_map1.v.svn-base b/bee2-selectmap/.svn/prop-base/main_counterexample_map1.v.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/makemaps.pl.svn-base b/bee2-selectmap/.svn/prop-base/makemaps.pl.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/remote_run.pl.svn-base b/bee2-selectmap/.svn/prop-base/remote_run.pl.svn-base
new file mode 100644 (file)
index 0000000..4a83b70
--- /dev/null
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/prop-base/root.v.svn-base b/bee2-selectmap/.svn/prop-base/root.v.svn-base
new file mode 100644 (file)
index 0000000..f417888
--- /dev/null
@@ -0,0 +1,13 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+K 13
+svn:mime-type
+V 10
+text/plain
+END
diff --git a/bee2-selectmap/.svn/text-base/Makefile.svn-base b/bee2-selectmap/.svn/text-base/Makefile.svn-base
new file mode 100644 (file)
index 0000000..a6e1717
--- /dev/null
@@ -0,0 +1,52 @@
+
+projectname = bee2-control-user-fifo
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = bee441.megacz.com
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = bee2-control-user-fifo.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+remote_run += echo "Gdkkn+vnqkc " > /dev/selectmap1;
+remote_run += head -c12 /dev/selectmap1; echo
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       rsync -zare ssh --progress --verbose build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare ssh --progress --delete --verbose ./ ${build_machine}:${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} synth XILINX=${build_machine_xilinx_path}'
+       scp ${build_machine}:${build_machine_work_dir}/main.bit build/fpga/$(bitfile)
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/.svn/text-base/Makefile_interchip0.svn-base b/bee2-selectmap/.svn/text-base/Makefile_interchip0.svn-base
new file mode 100644 (file)
index 0000000..042c5a2
--- /dev/null
@@ -0,0 +1,50 @@
+
+projectname = working-bee2
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = map0.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} -f Makefile0 synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/.svn/text-base/Makefile_interchip1.svn-base b/bee2-selectmap/.svn/text-base/Makefile_interchip1.svn-base
new file mode 100644 (file)
index 0000000..2d02793
--- /dev/null
@@ -0,0 +1,53 @@
+
+projectname = working-bee2
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = map1.bit
+
+remote_run  = user_unprogram 2;
+remote_run += user_program 2 $(bitfile);
+remote_run += ./remote_run.pl;
+remote_run += cat transcript;
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} -f Makefile1 synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+       scp remote_run.pl root@$(bee2_machine):
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/.svn/text-base/Makefile_userfpga.svn-base b/bee2-selectmap/.svn/text-base/Makefile_userfpga.svn-base
new file mode 100644 (file)
index 0000000..09dda50
--- /dev/null
@@ -0,0 +1,53 @@
+
+projectname = bee2-control-user-fifo
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = bee2-control-user-fifo.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+remote_run += ./remote_run.pl;
+remote_run += cat transcript;
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+       scp remote_run.pl root@$(bee2_machine):
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/.svn/text-base/README.txt.svn-base b/bee2-selectmap/.svn/text-base/README.txt.svn-base
new file mode 100644 (file)
index 0000000..9d081a5
--- /dev/null
@@ -0,0 +1,67 @@
+Author: Tracy Wang
+
+Everything in this folder is the framework that I used to test the interchip on the Bee2. 
+
+Here's a short list of important files and their description.
+
+============
+main.v
+
+This is the *generic* top level verilog file which hooks up the selectmap FIFOs (async_fifo_* files). Then it hooks the FIFOs to the testing file, in this case in root.v. Actual test resides in root.v. 
+
+============
+main_counterexample_map0
+
+This is the main file which hooks up the counterexample Map0. So it hooks up the selectmap to BTN and SW. It also connects the interchip terminal to the right pins on Bee2.
+
+============
+main_counterexample_map1
+
+This is the main file which hooks up the counterexample Map1. It connects the counter outputs to the selectmap FIFO. 
+
+============
+
+Makefile_userfpga
+
+This is the *generic* makefile which can be invoked from the control fpga to program the testing harness automatically onto one of the user fpgas. However, it will prompt for password in several locations, which I wasn't able to bypass.
+
+===========
+
+makemaps.pl
+
+This is the perl file which I used to invoke Makefile_interchip0 and Makefile interchip1 to build the two interchip maps. This file requires customization of the Makefile file names.
+Both Makefile_interchip0 and Makefile_interchip1 will program the bit files onto the boards. Makefile_interchip1 will actually run a remote_run.pl file after everything is programmed to automatically test the unit and retrieve the results.
+
+===========
+
+How to use selectmap
+
+To input characters into selectmap:
+
+echo "<characters here>" > /dev/selectmap[1-4];
+
+To read from selectmap
+
+head -c<number of characters> /dev/selectmap[1-4];
+
+i.e. if I'm on board 2, and I program a single unit which counts every time I receive a character from the selectmap, I would do the following
+
+echo "12345" > /dev/selectmap2;
+head -c5 /dev/selectmap2;
+
+i.e. if I'm on board1, and the interchip connects to board2, I would do something like 
+
+echo "12345" > /dev/selectmap1;
+head -c5 /dev/selectmap2;
+
+===========
+
+Finally, step by step instructions on how to go from a verilog project to programming it and running it on the Bee2.
+
+1. Use RDLC to generate files from the RDL
+2. Copy all verilog files into a single flat directory on a server connected to a bee2 board (like sting)
+3. Make sure the selectmap FIFO, main*.v and Makefile* are also in that same directory.
+4. Customize the main*.v files to connect the right ports to selectmap FIFOs, and your Maps. If you have multiple Maps, make two separate main files
+5. Customize the Makefile to point to the right chip. If you are making two maps, make two Makefiles.
+6. Run Makefile. The original Makefiles will program the chips automatically.
+7. Use the above instructions to start running the tests by echoing characters into the selectmap.
diff --git a/bee2-selectmap/.svn/text-base/async_fifo_8_8_128.edn.svn-base b/bee2-selectmap/.svn/text-base/async_fifo_8_8_128.edn.svn-base
new file mode 100644 (file)
index 0000000..5562d7c
--- /dev/null
@@ -0,0 +1,402 @@
+(edif test (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0))
+(status (written (timeStamp 2006 2 18 19 6 14)
+   (author "Xilinx, Inc.")
+   (program "Xilinx CORE Generator" (version "Xilinx CORE Generator 7.1.04i; Cores Update # 3"))))
+   (comment "                                                                                
+      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-2005 Xilinx, Inc.                                      
+      All rights reserved.                                                      
+                                                                                
+   ")
+   (comment "Core parameters: ")
+       (comment "c_wr_response_latency = 1 ")
+       (comment "c_has_rd_data_count = 1 ")
+       (comment "c_din_width = 8 ")
+       (comment "c_has_wr_data_count = 1 ")
+       (comment "InstanceName = async_fifo_8_8_128 ")
+       (comment "c_implementation_type = 2 ")
+       (comment "c_family = virtex2p ")
+       (comment "c_has_wr_rst = 0 ")
+       (comment "c_underflow_low = 0 ")
+       (comment "c_has_meminit_file = 0 ")
+       (comment "c_has_overflow = 0 ")
+       (comment "c_preload_latency = 0 ")
+       (comment "c_dout_width = 8 ")
+       (comment "c_rd_depth = 128 ")
+       (comment "c_default_value = BlankString ")
+       (comment "c_mif_file_name = BlankString ")
+       (comment "c_has_underflow = 0 ")
+       (comment "c_has_rd_rst = 0 ")
+       (comment "c_has_almost_full = 0 ")
+       (comment "c_has_rst = 1 ")
+       (comment "c_data_count_width = 2 ")
+       (comment "c_has_wr_ack = 0 ")
+       (comment "c_wr_ack_low = 0 ")
+       (comment "c_common_clock = 0 ")
+       (comment "c_rd_pntr_width = 7 ")
+       (comment "c_has_almost_empty = 0 ")
+       (comment "c_rd_data_count_width = 8 ")
+       (comment "c_enable_rlocs = 0 ")
+       (comment "c_wr_pntr_width = 7 ")
+       (comment "c_overflow_low = 0 ")
+       (comment "c_prog_empty_type = 0 ")
+       (comment "c_optimization_mode = 0 ")
+       (comment "c_wr_data_count_width = 8 ")
+       (comment "c_preload_regs = 1 ")
+       (comment "c_dout_rst_val = 0 ")
+       (comment "c_has_data_count = 0 ")
+       (comment "c_prog_full_thresh_negate_val = 96 ")
+       (comment "c_wr_depth = 128 ")
+       (comment "c_prog_empty_thresh_negate_val = 32 ")
+       (comment "c_prog_empty_thresh_assert_val = 32 ")
+       (comment "c_has_valid = 0 ")
+       (comment "c_init_wr_pntr_val = 0 ")
+       (comment "c_prog_full_thresh_assert_val = 96 ")
+       (comment "c_use_fifo16_flags = 0 ")
+       (comment "c_has_backup = 0 ")
+       (comment "c_valid_low = 0 ")
+       (comment "c_prim_fifo_type = 512 ")
+       (comment "c_count_type = 0 ")
+       (comment "c_prog_full_type = 0 ")
+       (comment "c_memory_type = 1 ")
+   (external xilinxun (edifLevel 0)
+      (technology (numberDefinition))
+       (cell VCC (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port P (direction OUTPUT))
+               )
+           )
+       )
+       (cell GND (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port G (direction OUTPUT))
+               )
+           )
+       )
+   )
+   (external async_fifo_8_8_128_fifo_generator_v2_2_xst_1_lib (edifLevel 0)
+       (technology (numberDefinition))
+       (cell async_fifo_8_8_128_fifo_generator_v2_2_xst_1 (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port clk (direction INPUT))
+                   (port backup (direction INPUT))
+                   (port backup_marker (direction INPUT))
+                   (port ( array ( rename din "din<7:0>") 8 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh "prog_empty_thresh<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh_assert "prog_empty_thresh_assert<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh_negate "prog_empty_thresh_negate<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh "prog_full_thresh<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh_assert "prog_full_thresh_assert<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh_negate "prog_full_thresh_negate<6:0>") 7 ) (direction INPUT))
+                   (port rd_clk (direction INPUT))
+                   (port rd_en (direction INPUT))
+                   (port rd_rst (direction INPUT))
+                   (port rst (direction INPUT))
+                   (port wr_clk (direction INPUT))
+                   (port wr_en (direction INPUT))
+                   (port wr_rst (direction INPUT))
+                   (port almost_empty (direction OUTPUT))
+                   (port almost_full (direction OUTPUT))
+                   (port ( array ( rename data_count "data_count<1:0>") 2 ) (direction OUTPUT))
+                   (port ( array ( rename dout "dout<7:0>") 8 ) (direction OUTPUT))
+                   (port empty (direction OUTPUT))
+                   (port full (direction OUTPUT))
+                   (port overflow (direction OUTPUT))
+                   (port prog_empty (direction OUTPUT))
+                   (port prog_full (direction OUTPUT))
+                   (port valid (direction OUTPUT))
+                   (port ( array ( rename rd_data_count "rd_data_count<7:0>") 8 ) (direction OUTPUT))
+                   (port underflow (direction OUTPUT))
+                   (port wr_ack (direction OUTPUT))
+                   (port ( array ( rename wr_data_count "wr_data_count<7:0>") 8 ) (direction OUTPUT))
+               )
+           )
+       )
+   )
+(library test_lib (edifLevel 0) (technology (numberDefinition (scale 1 (E 1 -12) (unit Time))))
+(cell async_fifo_8_8_128
+ (cellType GENERIC) (view view_1 (viewType NETLIST)
+  (interface
+   (port ( array ( rename din "din<7:0>") 8 ) (direction INPUT))
+   (port ( rename rd_clk "rd_clk") (direction INPUT))
+   (port ( rename rd_en "rd_en") (direction INPUT))
+   (port ( rename rst "rst") (direction INPUT))
+   (port ( rename wr_clk "wr_clk") (direction INPUT))
+   (port ( rename wr_en "wr_en") (direction INPUT))
+   (port ( array ( rename dout "dout<7:0>") 8 ) (direction OUTPUT))
+   (port ( rename empty "empty") (direction OUTPUT))
+   (port ( rename full "full") (direction OUTPUT))
+   (port ( array ( rename rd_data_count "rd_data_count<7:0>") 8 ) (direction OUTPUT))
+   (port ( array ( rename wr_data_count "wr_data_count<7:0>") 8 ) (direction OUTPUT))
+   )
+  (contents
+   (instance VCC (viewRef view_1 (cellRef VCC  (libraryRef xilinxun))))
+   (instance GND (viewRef view_1 (cellRef GND  (libraryRef xilinxun))))
+   (instance BU2
+      (viewRef view_1 (cellRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1 (libraryRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_lib)))
+   )
+   (net (rename N5 "din<7>")
+    (joined
+      (portRef (member din 0))
+      (portRef (member din 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N6 "din<6>")
+    (joined
+      (portRef (member din 1))
+      (portRef (member din 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N7 "din<5>")
+    (joined
+      (portRef (member din 2))
+      (portRef (member din 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N8 "din<4>")
+    (joined
+      (portRef (member din 3))
+      (portRef (member din 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N9 "din<3>")
+    (joined
+      (portRef (member din 4))
+      (portRef (member din 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N10 "din<2>")
+    (joined
+      (portRef (member din 5))
+      (portRef (member din 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N11 "din<1>")
+    (joined
+      (portRef (member din 6))
+      (portRef (member din 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N12 "din<0>")
+    (joined
+      (portRef (member din 7))
+      (portRef (member din 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N55 "rd_clk")
+    (joined
+      (portRef rd_clk)
+      (portRef rd_clk (instanceRef BU2))
+    )
+   )
+   (net (rename N56 "rd_en")
+    (joined
+      (portRef rd_en)
+      (portRef rd_en (instanceRef BU2))
+    )
+   )
+   (net (rename N58 "rst")
+    (joined
+      (portRef rst)
+      (portRef rst (instanceRef BU2))
+    )
+   )
+   (net (rename N59 "wr_clk")
+    (joined
+      (portRef wr_clk)
+      (portRef wr_clk (instanceRef BU2))
+    )
+   )
+   (net (rename N60 "wr_en")
+    (joined
+      (portRef wr_en)
+      (portRef wr_en (instanceRef BU2))
+    )
+   )
+   (net (rename N66 "dout<7>")
+    (joined
+      (portRef (member dout 0))
+      (portRef (member dout 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N67 "dout<6>")
+    (joined
+      (portRef (member dout 1))
+      (portRef (member dout 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N68 "dout<5>")
+    (joined
+      (portRef (member dout 2))
+      (portRef (member dout 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N69 "dout<4>")
+    (joined
+      (portRef (member dout 3))
+      (portRef (member dout 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N70 "dout<3>")
+    (joined
+      (portRef (member dout 4))
+      (portRef (member dout 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N71 "dout<2>")
+    (joined
+      (portRef (member dout 5))
+      (portRef (member dout 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N72 "dout<1>")
+    (joined
+      (portRef (member dout 6))
+      (portRef (member dout 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N73 "dout<0>")
+    (joined
+      (portRef (member dout 7))
+      (portRef (member dout 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N74 "empty")
+    (joined
+      (portRef empty)
+      (portRef empty (instanceRef BU2))
+    )
+   )
+   (net (rename N75 "full")
+    (joined
+      (portRef full)
+      (portRef full (instanceRef BU2))
+    )
+   )
+   (net (rename N80 "rd_data_count<7>")
+    (joined
+      (portRef (member rd_data_count 0))
+      (portRef (member rd_data_count 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N81 "rd_data_count<6>")
+    (joined
+      (portRef (member rd_data_count 1))
+      (portRef (member rd_data_count 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N82 "rd_data_count<5>")
+    (joined
+      (portRef (member rd_data_count 2))
+      (portRef (member rd_data_count 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N83 "rd_data_count<4>")
+    (joined
+      (portRef (member rd_data_count 3))
+      (portRef (member rd_data_count 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N84 "rd_data_count<3>")
+    (joined
+      (portRef (member rd_data_count 4))
+      (portRef (member rd_data_count 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N85 "rd_data_count<2>")
+    (joined
+      (portRef (member rd_data_count 5))
+      (portRef (member rd_data_count 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N86 "rd_data_count<1>")
+    (joined
+      (portRef (member rd_data_count 6))
+      (portRef (member rd_data_count 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N87 "rd_data_count<0>")
+    (joined
+      (portRef (member rd_data_count 7))
+      (portRef (member rd_data_count 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N90 "wr_data_count<7>")
+    (joined
+      (portRef (member wr_data_count 0))
+      (portRef (member wr_data_count 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N91 "wr_data_count<6>")
+    (joined
+      (portRef (member wr_data_count 1))
+      (portRef (member wr_data_count 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N92 "wr_data_count<5>")
+    (joined
+      (portRef (member wr_data_count 2))
+      (portRef (member wr_data_count 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N93 "wr_data_count<4>")
+    (joined
+      (portRef (member wr_data_count 3))
+      (portRef (member wr_data_count 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N94 "wr_data_count<3>")
+    (joined
+      (portRef (member wr_data_count 4))
+      (portRef (member wr_data_count 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N95 "wr_data_count<2>")
+    (joined
+      (portRef (member wr_data_count 5))
+      (portRef (member wr_data_count 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N96 "wr_data_count<1>")
+    (joined
+      (portRef (member wr_data_count 6))
+      (portRef (member wr_data_count 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N97 "wr_data_count<0>")
+    (joined
+      (portRef (member wr_data_count 7))
+      (portRef (member wr_data_count 7) (instanceRef BU2))
+    )
+   )
+))))
+(design async_fifo_8_8_128 (cellRef async_fifo_8_8_128 (libraryRef test_lib))
+  (property X_CORE_INFO (string "fifo_generator_v2_2, Coregen 7.1.04i_ip3"))
+  (property PART (string "xc2vp70-ff1704-7") (owner "Xilinx")))
+)
diff --git a/bee2-selectmap/.svn/text-base/async_fifo_8_8_128.v.svn-base b/bee2-selectmap/.svn/text-base/async_fifo_8_8_128.v.svn-base
new file mode 100644 (file)
index 0000000..ce27aa2
--- /dev/null
@@ -0,0 +1,155 @@
+/*******************************************************************************
+*     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-2005 Xilinx, Inc.                                     *
+*     All rights reserved.                                                     *
+*******************************************************************************/
+// The synopsys directives "translate_off/translate_on" specified below are
+// supported by XST, FPGA Compiler II, Mentor Graphics and Synplicity synthesis
+// tools. Ensure they are correct for your synthesis tool(s).
+
+// You must compile the wrapper file async_fifo_8_8_128.v when simulating
+// the core, async_fifo_8_8_128. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
+`timescale 1ns/1ps
+
+module async_fifo_8_8_128(
+       din,
+       rd_clk,
+       rd_en,
+       rst,
+       wr_clk,
+       wr_en,
+       dout,
+       empty,
+       full,
+       rd_data_count,
+       wr_data_count);
+
+
+input [7 : 0] din;
+input rd_clk;
+input rd_en;
+input rst;
+input wr_clk;
+input wr_en;
+output [7 : 0] dout;
+output empty;
+output full;
+output [7 : 0] rd_data_count;
+output [7 : 0] wr_data_count;
+
+// synopsys translate_off
+
+      FIFO_GENERATOR_V2_2 #(
+               0,      // c_common_clock
+               0,      // c_count_type
+               2,      // c_data_count_width
+               "BlankString",  // c_default_value
+               8,      // c_din_width
+               "0",    // c_dout_rst_val
+               8,      // c_dout_width
+               0,      // c_enable_rlocs
+               "virtex2p",     // c_family
+               0,      // c_has_almost_empty
+               0,      // c_has_almost_full
+               0,      // c_has_backup
+               0,      // c_has_data_count
+               0,      // c_has_meminit_file
+               0,      // c_has_overflow
+               1,      // c_has_rd_data_count
+               0,      // c_has_rd_rst
+               1,      // c_has_rst
+               0,      // c_has_underflow
+               0,      // c_has_valid
+               0,      // c_has_wr_ack
+               1,      // c_has_wr_data_count
+               0,      // c_has_wr_rst
+               2,      // c_implementation_type
+               0,      // c_init_wr_pntr_val
+               1,      // c_memory_type
+               "BlankString",  // c_mif_file_name
+               0,      // c_optimization_mode
+               0,      // c_overflow_low
+               0,      // c_preload_latency
+               1,      // c_preload_regs
+               512,    // c_prim_fifo_type
+               32,     // c_prog_empty_thresh_assert_val
+               32,     // c_prog_empty_thresh_negate_val
+               0,      // c_prog_empty_type
+               96,     // c_prog_full_thresh_assert_val
+               96,     // c_prog_full_thresh_negate_val
+               0,      // c_prog_full_type
+               8,      // c_rd_data_count_width
+               128,    // c_rd_depth
+               7,      // c_rd_pntr_width
+               0,      // c_underflow_low
+               0,      // c_use_fifo16_flags
+               0,      // c_valid_low
+               0,      // c_wr_ack_low
+               8,      // c_wr_data_count_width
+               128,    // c_wr_depth
+               7,      // c_wr_pntr_width
+               1)      // c_wr_response_latency
+       inst (
+               .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),
+               .RD_DATA_COUNT(rd_data_count),
+               .WR_DATA_COUNT(wr_data_count),
+               .CLK(),
+               .BACKUP(),
+               .BACKUP_MARKER(),
+               .PROG_EMPTY_THRESH(),
+               .PROG_EMPTY_THRESH_ASSERT(),
+               .PROG_EMPTY_THRESH_NEGATE(),
+               .PROG_FULL_THRESH(),
+               .PROG_FULL_THRESH_ASSERT(),
+               .PROG_FULL_THRESH_NEGATE(),
+               .RD_RST(),
+               .WR_RST(),
+               .ALMOST_EMPTY(),
+               .ALMOST_FULL(),
+               .DATA_COUNT(),
+               .OVERFLOW(),
+               .PROG_EMPTY(),
+               .PROG_FULL(),
+               .VALID(),
+               .UNDERFLOW(),
+               .WR_ACK());
+
+
+// synopsys translate_on
+
+endmodule
+
diff --git a/bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc.svn-base b/bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc.svn-base
new file mode 100644 (file)
index 0000000..dc18c6b
--- /dev/null
@@ -0,0 +1,3 @@
+XILINX-XDB 0.1 STUB 0.1 ASCII
+XILINX-XDM V1.4e
+$52f\7f4=7:2:3=6?>;33;?7<H]]Z^X7jnt`]`kphs480;2<5;4:66104<=8;0:95998426>1=AGZ^X7OKDSC?2?699;1<6D@_UU8B@ATE4?0;2<k47;KMTPR=X[ELSHC_TX]WLWCT@5<1<3<:;68JJUSS2YXDKRKBPU[\PMTB[AUJ_^K]T=494;423>0BB][[:QPLCZCJX]STXE\JSI]MABGSM5<1<3?k;68JJUSS2YXDKRHZLM]WLWCT@5<1<3<;;68JJUSS2YXDKRHZLM]WLWCT@VKX_H\[<783:72<?3CE\XZ5PSMD[CSKDV^C^H]G_OGDEQC;>3:5=h58:HLSQQ<wzfmTi`~{y^vkv`uo4?0;2?;47;KMTPR=x{elShc\7ftx]wlwct`Vkx\7fh|{<783:73<?3CE\XZ5psmd[`kw|pU\7fd\7fk|h^lfcdrb4?0;2<j47;KMTPR=x{elSk{cl^vkv`uo4?0;2?:47;KMTPR=x{elSk{cl^vkv`uoWhyxi\7fz36;2=61=02@D[YY4\7frne\bpjkW}byi~fPndebp`:1294:n695OTVSQQ<CMK_LS_JPPOVQ83<768h0;7AZTQWW>ACE]NU\^R^ATS>5>585;2=1CXZ_UU8gags`W{nT|cz}_qnvw4Yu4?0;2<j47;MVPUSS2moiyjQ}d^rmpwYu4?0;2<j47;MVPUSS2moiyjQ}d^rmpwYp4?0;2?=47;MVPUSS2moiyjQxr^rmpwYwd|y:Sz29:1<17>1=G\^[YY4kecwd[rtXxg~yS}bzs3]t83<768n0;7AZTQWW>ace}nU|~R~ats]q83<768n0;7AZTQWW>ace}nU|~R~ats]t83<76;13<95701224>>=AGZ^X7JFN=594;76310BB][[:EKME91=87;:754FNQWW>AOIJ5=1<3??;98JJUSS2mce0:4?>008<?IR\Y__6IAZT=594;74310DYY^ZT;FLQQG;?3:5=>57:NWWTPR=LF__N1950?3a?=<H]]Z^X7\K_ECWEZEH]G^7;7>11c9;>JSSX\^1[_QKAUC\GJSI\5=1<3?=;98LQQVR\3ndyy28:1<2f>>=G\^[YY4}d^fbpdYdg|d\7f0:4?>0`8<?IR\Y__6z|Pd`vb[firf}6<6=0>;868=56>:23=46OKDSC?4;><IMNYM1?18:CG@WG;:720MIJ]A=1=<>GCL[K78364AEFQE939i2KOH_O36;2=<>GCL[K7:364AEFQF96902KOH_L31?:8EABUJ58546OKDS@?7;><IMNYN1:18:CG@WD;=7k0MIJ]B=494;><IMNYN1814:CE62e<IEGD_YQJMQVZf>GKEFY_SK[CL89BW\HDW[OL86LNA@:8FPUXAGLD=6M=;B61?FC>3JBDENK>08;8GMINKL;9<45LHNK@A44012ICCDMJ12::?FNHAJO:9=74CIMJG@71901HDBGLE04;=>EOG@IN=:76;BJLMFC61830OEAFCD036==D@FCHI9;7;BJLMFC2>11HDBGLE7:;?FNHAJO<555LHNK@A=0?3JBDENK6739@M1=DDBK?7NBDB29@HW?<KFGFEYZJD69@V@GSMM;0Hk5KECWD[WGJWLG[XTk4DD@VCZTFEVL^@Ah4DD@VCZTFEVXOSH@i;EGAQBYUIDU\^RKA119GAGS@W[NT\CZ]<1<24>BBJ\MT^IQ_NUP?5;773MOIYJQ]D^RMPW:568:0HHLZG^PG[UHSZ595==5KECWD[WBXXG^Y090>0:FFFPAXZMU[BY\35?31?ACE]NUYHR^ATS>5>58682NNNXIPRE]SJQT;>7;;7IKMUF]TVZVI\[6;2<>4DD@VCZQUWYD_^1?1119GAGS@W^XT\CZ]<3<24>BBJ\MT[_Q_NUP?7;773MOIYJQXR^RMPW:368:0HHLZG^UQ[UHSZ5?5=?5KECWD[RTXXG^Y0;4?>028@@DROV]YS]@[R=4=6>BN>2NBB1>16:FJJ979>2NBB1<16:FJJ959>2NBB1:16:FJJ939>2NBB1818:FJJ91=87<0HD@37?58@LHF494<7IGAA=3=3>BNFH692:5KIOC?7;1<L@DJ0908;EKME939?2NBBL29>89GMKG;?3:5;6JFN@>4:2=CAGH7<394DHLA84803MCEN1<17:FJJG:46>1OECL34?58@LHE4<4<7IGAB=4==>BNFK6<6=08;EKMF919?2NDYY2?>69GKPR;97=0HB[[<3<4?AIR\595;6J@UU>7:2=CG\^79394DNWW838>3ME^X1950?58@JSS4>437IAZT@>3:==CG\^J0<07;EMVPD:5611OCXZN<2<;?AIR\H6?255KOTVB808?3ME^XL29>`9GKPRF4>0;255KOTVB828?3ME^XO2?>99GKPRE48437IAZTC>1:==CG\^I0>07;EMVPG:3611OCXZM<4<;?AIR\K6=2l5KOTVA82<7611OCXZM<6<2?@3<MDZ_U>5JN@18AKD53O>97K6<;GF@0>@CKL90JI^;;GFSA1=A]EF:7J=4GOF7?M(3:;1B<?5F139J67=N;01BBDZ\T@VF6>JN:2FD;6B@GHABH1=K]];=7A[[1^N7?ISS:?1GYY<PL59OQQ513E__?RB;;MWW00=J]QIR>6@?4:L03<5<FMK87CJM7:LFPRIUC>1EC@K]GD38K==H^LXM@BY>;Q68TDTSi2ZBBRLZSHF[f>VNFVH^_COBE29SV@g<X[ELSHC_TX37?UTHOVOF\YWPTIPFWM:768>0\_AH_DOSP\YS@[OXD1?1159SVJAXMDZ_URZGRDQK8786<2ZYCJQJMQVZ[QNUMZB7?3?;;QPLCZCJX]STXE\JSI>7:42<X[ELSHC_TX]WLWCT@5?5=;5_RNE\AHVSQV^C^H]G<783:42<X[ELSHC_TX]WLWCT@5<5=o5_RNE\AHVSQV^C^H]G_@QPAWR;87;i7]\@G^GNTQ_X\AXN_EQNSRGQP9799k1[^BIPELRW]ZROZLYCSL]\ESV?6;7e3YXDKRKBPU[\PMTB[AUJ_^K]T=1=5g=WZFMTI@^[Y^VKV@UOWHYXI_Z34?3a?UTHOVOF\YWPTIPFWMYF[ZOYX1;11e9SVJAXMDZ_URZGRDQK[DUTM[^7:7>11c9SVJAXMDZ_URZGRDQK[DUTM[^7:3?m;QPLCZCJX]STXE\JSI]MABGSM5:5=o5_RNE\AHVSQV^C^H]G_OGDEQC;97;i7]\@G^GNTQ_X\AXN_EQAEFCWA9499k1[^BIPELRW]ZROZLYCSCKHAUG?7;7e3YXDKRKBPU[\PMTB[AUEIJO[E=6=5g=WZFMTI@^[Y^VKV@UOWGOLMYK35?3g?UTHOVOF\YWPTIPFWMYIMNK_I1850?3a?UTHOVOF\YWPTIPFWMYIMNK_I1819:RQKBYA]EF:?6^]OF]EQIJX\AXN_E2?>018TWI@WO_G@RZGRDQK8486;2ZYCJQIUMN\PMTB[A692<=4PSMD[CSKDV^C^H]G<2<27>VUGNUMYABPTIPFWM:36890\_AH_GWOHZROZLYC080>5:RQKBYA]EFTXE\JSI>5>586;2ZYCJQIUMN\PMTB[A6=2<o4PSMD[CSKDV^C^H]G_@QPAWR;87;j7]\@G^DVHIYS@[OXDRO\SDPW8486i2ZYCJQIUMN\PMTB[AUJ_^K]T=0=5d=WZFMTJXBC_UJQAVNXIZYN^Y2<>0c8TWI@WO_G@RZGRDQK[DUTM[^783?n;QPLCZ@RDEU_D_K\H^CPW@TS4<4:o6^]OF]EQIJX\AXN_EQNSRGQP90=87;j7]\@G^DVHIYS@[OXDRO\SDPW8386i2ZYCJQIUMN\PMTB[AUEIJO[E=2=5d=WZFMTJXBC_UJQAVNXFLMJXH2>>0c8TWI@WO_G@RZGRDQK[KC@I]O7>3?n;QPLCZ@RDEU_D_K\H^LFCDRB4:4:m6^]OF]EQIJX\AXN_EQAEFCWA9299h1[^BIPFTNO[QNUMZBTBHINTD>6:4e<X[ELSK[CL^VKV@UOWGOLMYK36;2=5d=WZFMTJXBC_UJQAVNXFLMJXH29>09R0>TCQH>0^IWM6:PG[FJL991YHRJNT@]@KPHS494:<6\K_ECWEZEH]G^7=3??;SF\@DRFWJE^BY2=>028VAYCI]KTOB[AT=1=55=ULVNJXLQLOTLW818682XOSIO[A^ALQKR;=7;;7_JPD@VB[FIRF]6=2<<4RE]GEQGXKF_EX1950?33?WBXLH^JSNAZNU>4:0=ULVOE86\ID@68VCBE;2XXX<5\6:QJJLRF>2YBBDZM6:QLQWEB<2^R\H94U1-ecdu>3\DOI_HCOVa8QVCUW_CXEOBJ5:TBHLB43_IH56XFEV]W]UC43^OJ?6YJB79TVZGDC?1\^RMCK028SWYCI]KTOB[AT=2=55=PZVNJXLQLOTLW848682]YSIO[A^ALQKR;:7;;7Z\PD@VB[FIRF]682<>4WS]GEQGXKF_EX1:1119TVZBF\HUHCX@[<4<24>QUWMK_MRM@UOV?2;753^XTHLZN_BMVJQ:0294:<6Y]_ECWEZEH]G^7;3;4WS]FJ4b<P@FBBU#WDC"3*4&T\\H+<#?/ARAJM0=_G[IR:6V\TMKA3>^T\VMEH:5WSU]UGFd<PVID^HQFNGM5?]beW@n:<6Vkm^ObnjtQm{ybcc??;Yfn[Hoig{\n~~g`n29[wqe<iegd\7fyQjmqvzf>gkefy\7fSk{cl3a8ev\7fikVlbjbQ7_9]26=YaaoeTkh`jr`vlvZp5W;Us\7fyQ>3d9bw|hdWocmcR6P8^31<Z`nnfUlick}aumq[s4X:VrxxR?PbminahbwW\7f<T>Rv|t79aefmrxm1imnezp^obvncu;2igg?j4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%E?9o4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqYdg|d\7fSR`?012?4;Ydqf>37n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<1<`}1?<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:7<3bzt5c8gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;97Uhub:n;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrXkf\7fexRQa0123848Xpfx?46matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=3=g|2f3jd\7fnae gdl\vaYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;0?0Pcxm7e>ei|kf`#jka_sf\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j5678585Sua}499`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:56js?m6matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=1=[f\7fh<h1hbylck.efjZtcWjd\7f~"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^alqkrXWg:;<=2<>^zlv1><kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:7?3mv4`9`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:36Virc9o4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqYdg|d\7fSR`?012?0;Y\7fg{>37n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<5<`}1g<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:793Qlyn6b?fhsjea$kh`Pre]`jqt(j`dToczPtnr,fibXj`dTocz bra\flhXkg~Tob{at^]m45674<4Ttb|;8:ampgjl'noeS\7fjPcovq+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsWje~byQPn1234939kp>j7n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<7<\|jt4:2iexobd/fgm[wbXkg~y#oga_blw[qiw'kfoSoga_blw+firf}U;??5lnu`oo*abfVxoSn`{r.`jjZei|V~d|"lcd^`jjZei|&idyczP1278gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[4Yu|:80oczmlj-dakYulViex\7f!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS?=:;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^0\vq553jd\7fnae gdl\vaYdf}x$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V9896matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQ<_sv06>ei|kf`#jka_sf\gkru'kceSn`{_ums+gjcWkceSn`{/bmvjqY3;<1hbylck.efjZtcWjd\7f~"lfn^ampZrhx&hghRlfn^amp*eh}g~T8R|{339`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"m`uov\163<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-`kphsW<Uyx><4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_716?fhsjea$kh`Pre]`jqt(j`dToczPtnr,fibXj`dTocz cnwmpZ0Xz}9j7n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa01238484i2iexobd/fgm[wbXkg~y#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=0=7d=df}hgg"ijn^pg[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2<>2c8gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:783=n;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^]m45674<48m6matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQPn1234909;:1hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$B>;=;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;0=0Pcxm64>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]3[firf}UTb=>?0=2=g|363jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZ6Xkf\7fexRQa0123858k}}?97n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m4567484Tota:2:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ?_bmvjqYXf9:;<1?1_ymq15=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>2:f\7f2:2iexobd/fgm[wbXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234949Wjsd9?5lnu`oo*abfVxoSn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k6789692Rv`r428gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>32?az17=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>0:Ze~g<80oczmlj-dakYulViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;;7Usc\7f;?;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;0>0ly408gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>34?]`}j353jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZ6Xkf\7fexRQa0123818Xpfx><6matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U;Snaznu]\j56785>5ot;=;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;080Pcxm66>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]3[firf}UTb=>?0=7=[}iu=91hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrX8VidyczP_o2345:26js>>6matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U;Snaznu]\j56785<5Sua}399`jqdkc&mnbR|k_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V:846matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!lotlw[45e3jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP1^pw7==df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(kf\7fexR<<b:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-`kphsW;Uyx>64covahn)`mgUyhRmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqY4;k1hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$ob{at^1\vq5?3jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP42`8gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}U?S\7fz<8:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-`kphsW<9i7n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\1Zts;11hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$ob{at^40f>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS;Q}t528gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=3=05=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa0123878382iexobd/fgm[wbXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;;7>;7n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896?29>4covahn)`mgUyhRmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqYXf9:;<1;1419`jqdkc&mnbR|k_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|VUe<=>?<7<1`>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/O17e>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j56785:5Snw`499`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:76js?56matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=2=hpr3i2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_bmvjqYXf9:;<1?1_b{l0d=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexRm`uov\[k67896:2Rv`r5:8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;97ir8l5lnu`oo*abfV}ySn`{r.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZeh}g~TSc>?01>1:Ze~g=k0oczmlj-dakYpzViex\7f!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]`kphsWVd;<=>32?]{kw2?3jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;0?0ly5c8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;;7Uhub:n;blwfim(oldT{\7fQlnup,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrXkf\7fexRQa0123868Xpfx?46matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=1=g|2f3jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;090Pcxm7e>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j56785>5Sua}499`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:36js?m6matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=7=[f\7fh<h1hbylck.efjZquWjd\7f~"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^alqkrXWg:;<=2:>^zlv1><kg~i`f!heo]tvZei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:793mv4`9`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:16Vrd~><4covahn)`mgU|~Rmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_111?fhsjea$kh`Pws]`jqt(j`dToczPtnr,fibXj`dTocz cnwmpZ74=2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+firf}U:S\7fz<2:ampgjl'noeSz|Pcovq+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]170=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrX:Vx\7f??5lnu`oo*abfV}ySn`{r.`jjZei|V~d|"lcd^`jjZei|&idyczP3278gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[6Yu|:80oczmlj-dakYpzViex\7f!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS9=:;blwfim(oldT{\7fQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^6\vq553jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?896matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQ:_sv06>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/bmvjqY1;<1hbylck.efjZquWjd\7f~"lfn^ampZrhx&hghRlfn^amp*eh}g~T:R|{3`9`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896:2>o4covahn)`mgU|~Rmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;:79j7n`{bmi,c`hX\7f{Uhby| bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa01238684i2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=6=7d=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2:>2c8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:7:3=<;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.L017=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>3:Ze~g<:0oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;87ir9<5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k67896;2a{{539`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczP0^alqkrXWg:;<=2>>^azk04<kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[5Ydg|d\7fSR`?012?5;Y\7fg{?;7n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m4567484hu8<4covahn)`mgU|~Rmats]shpu6'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fS=Qlotlw[Zh789:7>3Qlyn71?fhsjea$kh`Pws]`jqtXxe\7fx="lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^2\gjsi|VUe<=>?<3<\|jt282iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234949kp?97n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m45674:4Tota:2:ampgjl'noeSz|Pcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ?_bmvjqYXf9:;<1=1_ymq15=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>0:f\7f2:2iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234929Wjsd9?5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k67896?2Rv`r428gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>34?az17=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>6:Ze~g<80oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;=7Usc\7f;?;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;080ly408gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>36?]{kw5?3jd\7fnae gdl\swYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP02:8gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}U:?o5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz cnwmpZ7Xz}937n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\66d<kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'je~byQ=_sv0<>ei|kf`#jka_vp\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS>=m;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.alqkrX;Vx\7f?55lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz cnwmpZ24j2iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_5]qp6><kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'je~byQ:3c9`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?T~y=7;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.alqkrX>:h0oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]5[wr382iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;97>;7n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896929>4covahn)`mgU|~Rmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqYXf9:;<1=1419`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|VUe<=>?<5<74>ei|kf`#jka_vp\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fSR`?012?1;273jd\7fnae gdl\swYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP_o2345:16:90oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#C=:2:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1>1_b{l15=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\5Zeh}g~TSc>?01>3:f\7f292iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY6Wje~byQPn1234969d|~>>6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U:Snaznu]\j56785;5Snw`539`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczP1^alqkrXWg:;<=2>>^zlv06<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[4Ydg|d\7fSR`?012?5;e~=;1hbylck.efjZquWjd\7f~R~cur0,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrX9VidyczP_o2345:56Virc8<4covahn)`mgU|~Rmats]shpu5'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fS<Qlotlw[Zh789:7>3Qwos73?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^3\gjsi|VUe<=>?<3<`}04<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[4Ydg|d\7fSR`?012?7;Ydqf?97n`{bmi,c`hX\7f{Uhby|Ppmwp6*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V;Tob{at^]m45674:4Ttb|:0:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1=1cx71?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^3\gjsi|VUe<=>?<5<\g|i2:2iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY6Wje~byQPn1234929Wqey9=5lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T=Rm`uov\[k67896?2nw:2:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1;1_b{l17=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\5Zeh}g~TSc>?01>6:Z~hz<:0oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW8Uhcx`{_^l3456;=7ir9?5lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T=Rm`uov\[k67896=2Rv`r2:8gkredb%licQxr^ampwYwd|y9#oga_blw[qiw'kfoSoga_blw+firf}U;?55lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz cnwmpZ74j2iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_0]qp6><kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'je~byQ=3c9`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V8T~y=7;blwfim(oldT{\7fQlnup\tist:&hbbRmat^vlt*dklVhbbRmat.alqkrX;:h0oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]0[wr402iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_51a?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*eh}g~T8R|{399`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?8n6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!lotlw[0Yu|:20oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]57g=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(kf\7fexR8Pru63?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*eh}g~TSc>?01>2:16<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'je~byQPn1234949<91hbylck.efjZquWjd\7f~R~cur0,flhXkg~Txb~ bmf\flhXkg~$ob{at^]m45674:4?<6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:783:?;blwfim(oldT{\7fQlnup\tist:&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2:>528gkredb%licQxr^ampwYwd|y9#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=4=`>bf|hUhcx`{<1<e?agsiVidycz31;2=`>bf|hUhcx`{<0<2<>bbj|mT~iQ\7fnup\tist9Vx7<3?7;egaqbYulVzex\7fQ\7fltq2[w:66820hhlzg^pg[uhszVzgy~?Pr=0=5==cmk\7flS\7fjPpovq[ujr{8Uy0>0>8:fffpaXzmU{by|Ppmwp5Zt;<7;37ikmuf]q`Zvi|{U{`x}>_s>6:4g<llh~kR|k_qlwvZvk}z;T~1850?3;?ace}nUyhR~ats]shpu6W{6=2<<4dd`vcZtcWyd\7f~R|30?31?ace}nUyhR~ats]q8486:2nnnxiPre]sjqtXz585=?5kecwd[wbXxg~yS\7f2<>008``droVxoS}`{r^p?0;753moiyjQ}d^rmpwYu4<4:86jjbte\vaYwf}xT~1850?31?ace}nUyhR~ats]q8386:2nnnxiPre]sjqtX\7f5:5=?5kecwd[wbXxg~ySz2>>008``droVxoS}`{r^u?6;753moiyjQ}d^rmpwYp4:4:>6jjbte\vaYwf}xT{1:1139gags`W{nT|cz}_v>6:42<llh~kR|k_qlwvZq;>3:5=?5kecwd[wbXxg~ySz29>0:8``droV}yS}`{r^roqv7X\7f5:5=55kecwd[rtXxg~yS}bzs0]t848602nnnxiPws]sjqtXxe\7fx=Ry32?3;?ace}nU|~R~ats]shpu6W~682<64dd`vcZquWyd\7f~R~cur3\s929911oio{h_vp\tkruWyf~\7f<Qx<4<2e>bbj|mT{\7fQ\7fnup\tist9V}7:7>1199gags`W~xT|cz}_qnvw4Yp4?4:46jjbte\swYwf}xT|a{|2^u?4;7?3moiyjQxr^rmpwYwd|y9Sz2>>0:8``droV}yS}`{r^roqv4X\7f585=55kecwd[rtXxg~yS}bzs3]t868602nnnxiPws]sjqtXxe\7fx>Ry34?3;?ace}nU|~R~ats]shpu5W~6>2<o4dd`vcZquWyd\7f~R~cur0\s90=87;37ikmuf]tvZvi|{U{`x}=_v>5:44<llh~kRy}_qlwvZt;87;97ikmuf]tvZvi|{Uy0<0>2:fffpaX\7f{U{by|Pr=0=57=cmk\7flSz|Ppovq[w:46880hhlzg^uq[uhszVx783?=;egaqbYpzVzex\7fQ}<4<20>bbj|mT{\7fQ\7fnup\v90=87;97ikmuf]tvZvi|{Uy0;0>2:fffpaX\7f{U{by|Pw=2=57=cmk\7flSz|Ppovq[r:66880hhlzg^uq[uhszV}7>3?=;egaqbYpzVzex\7fQx<2<26>bbj|mT{\7fQ\7fnup\s9299;1oio{h_vp\tkruW~6>2<:4dd`vcZquWyd\7f~Ry36;2=57=cmk\7flSz|Ppovq[r:16?1oec2?>79gmk:66?1oec2=>79gmk:46?1oec2;>79gmk:26?1oec29>99gmk:0294=7iga<6<4?air|5:5;6j`uu>2:2=cg|~7>394dnww86803me~x1:17:flqq:26>1ocxz36?;8`jss4>0;2:5kotv?3;3<mdz\7fu?64fhdl[bcim{k\7fc\7fQy2^0/$Fiumnoe,: >.16j[lv49?1mekaPgdlfvdrhzV|9S?Qns0;8bidkc&KGXR\K_ECWEZEH]G^T<<74fm`oo*GK\VXOSIO[A^ALQKRX9830jalck.COPZTCWMK_MRM@UOV\64?<nehgg"OCT^PG[AGSIVIDYCZP30;8bidkc&KGXR\K_ECWEZEH]G^T8<74fm`oo*GK\VXOSIO[A^ALQKRX=830jalck.COPZTCWMK_MRM@UOV\24?<nehgg"OCT^PG[AGSIVIDYCZP70;8bidkc&KGXRY]_ECWEZEH]G^T=<74fm`oo*GK\V]YSIO[A^ALQKRX:830jalck.COPZQUWMK_MRM@UOV\74?<nehgg"OCT^UQ[AGSIVIDYCZP40;8bidkc&KGXRY]_ECWEZEH]G^T9<74fm`oo*GK\V]YSIO[A^ALQKRX>830jalck.COPZQUWMK_MRM@UOV\3<=adkf`#C??9:dofim(F8;27kbmlj-M57?<nehgg"@>389ehgjl'G;?56hcbmi,J43>3ofi`f!A17;8bidkc&D:;45ilcnh+K7?12lgnae N0;:?cjedb%E>=74fm`oo*H5911m`obd/O4;?cjedb%E;55ilcnh+K>6=2lgnae WS]GEQGXKF_EXR>i;gnahn)Xf9:;>1>1119ehgjl'Vd;<=<30?3e?cjedb%Tb=>?2=3=55=adkf`#R`?010?5;7a3ofi`f!Pn1236949991m`obd/^l3454;:7;m7kbmlj-\j567:595==5ilcnh+Zh78987?3?i;gnahn)Xf9:;>1:1119ehgjl'Vd;<=<34?3e?cjedb%Tb=>?2=7=55=adkf`#R`?010?1;7a3ofi`f!Pn1236909991m`obd/^l3454;>7;m7kbmlj-\j567:5=5==5ilcnh+Zh78987;3?i;gnahn)Xf9:;?1<1f:dofim(Wg:;<>2<>g9ehgjl'Vd;<==34?d8bidkc&Ue<=><<4<e?cjedb%Tb=>?3=4=b>`kjea$Sc>?06>1:c=adkf`#R`?015?7;`<nehgg"Qa0124818a3ofi`f!Pn1233939n2lgnae _o2342:16;>0jalck.aoohic'{ns#@v`r^]m4567W[oxyaz>259ehgjl'jf`abj rez,I}iuWVd;<=?PRdqvhq75<2lgnae cminka)ulq%Ftb|P_o2347YUmz\7fgx<<;;gnahn)ddbgdh"|kx.O{kwYXf9:;?R\jstnw572<nehgg"mcklmg+wb\7f'Drd~RQa0127[Wct}e~:>95ilcnh+fjlefn$~iv Mymq[Zh789?T^h}zlu310>`kjea$oaeboe-q`})JpfxTSc>?06]Qavsk|88?7kbmlj-`hnkhl&xot"Cwos]\j5670VXn\7fxb{1308bidkc&igg`ak/sf{+H~hzVUe<=??_Ym?4;443ofi`f!lljol`*tcp&Gsc\7fQPn1224Z^h484:>95ilcnh+fjlefn$~iv Mymq[Zh788;T^h}zlu310>`kjea$oaeboe-q`})JpfxTSc>?13]Qavsk|88?7kbmlj-`hnkhl&xot"Cwos]\j566:VXn\7fxb{20;8bidkc&igg`ak/sf{+UHSZVHT<<74fm`oo*ekcdeo#\7fjw/QLWVZDX9830jalck.aoohic'{ns#]@[R^@\64?<nehgg"mcklmg+wb\7f'YD_^RLP30;8bidkc&igg`ak/sf{+UHSZVHT8<74fm`oo*ekcdeo#\7fjw/QLWVZDX=830jalck.aoohic'{ns#]@[R^@\24g<nehgg"mcklmg+wb\7f'Vd;<<;30?3b?cjedb%h`fc`d.pg|*Yi89;>0<0>a:dofim(keafci!}dy-\j566=585=l5ilcnh+fjlefn$~iv _o2350:468k0jalck.aoohic'{ns#R`?007?0;7f3ofi`f!lljol`*tcp&Ue<=?:<4<2e>`kjea$oaeboe-q`})Xf9:::1>11`9ehgjl'jf`abj rez,[k679?6?2<o4fm`oo*ekcdeo#\7fjw/^l3472;87;j7kbmlj-`hnkhl&xot"Qa01068586i2lgnae cminka)ulq%Tb=>=8=2=5f=adkf`#nbdmnf,va~(xg~ySyc\7f<1<2g>`kjea$oaeboe-q`})wf}xTx`~31?3`?cjedb%h`fc`d.pg|*vi|{U\7fa}2=>0a8bidkc&igg`ak/sf{+uhszV~f|1=11b9ehgjl'jf`abj rez,tkruW}g{090>c:dofim(keafci!}dy-sjqtX|dz793?l;gnahn)ddbgdh"|kx.rmpwYsey6=2<l4fm`oo*ekcdeo#\7fjw/qlwvZrjxV::n6hcbmi,gimjgm%yhu!\7fnup\phvX98h0jalck.aoohic'{ns#}`{r^vntZ46j2lgnae cminka)ulq%{by|Ptlr\74d<nehgg"mcklmg+wb\7f'yd\7f~Rzbp^62f>`kjea$oaeboe-q`})wf}xTx`~P50`8bidkc&igg`ak/sf{+uhszV~f|R8>d:dofim(keafci!}dy-sjqtX|dzs0=0>d:dofim(keafci!}dy-sjqtX|dzs0<0>d:dofim(keafci!}dy-sjqtX|dzs0?0>d:dofim(keafci!}dy-sjqtX|dzs0>0>d:dofim(keafci!}dy-sjqtX|dzs090>d:dofim(keafci!}dy-sjqtX|dzs080>d:dofim(keafci!}dy-sjqtX|dzs0;0>c:dofim(keafci!}dy-sjqtX|dzsS=?l;gnahn)ddbgdh"|kx.rmpwYseyrT=<m4fm`oo*ekcdeo#\7fjw/qlwvZrjxqU9=n5ilcnh+fjlefn$~iv povq[qkwpV9:o6hcbmi,gimjgm%yhu!\7fnup\phv\7fW=;h7kbmlj-`hnkhl&xot"~ats]wiu~X=8i0jalck.aoohic'{ns#}`{r^vnt}Y1:=1m`obd/bnhijb(\7f{r$Aua}_^l3456XZly~`y?=4:dofim(keafci!xry-N|jtXWg:;<<Q]erwop4433ofi`f!lljol`*qup&Gsc\7fQPn1236ZTb{|f\7f=?:4fm`oo*ekcdeo#z|w/LzlvZYi89:8S_k|umv261=adkf`#nbdmnf,sw~(EqeySR`?016\V`urd};986hcbmi,gimjgm%|~u!Bxnp\[k678<UYi~{ct007?cjedb%h`fc`d.uq|*K\7fg{UTb=>?7^Pfwpjs9;>0jalck.aoohic'~xs#@v`r^]m456?W[oxyaz>239ehgjl'jf`abj wsz,I}iuWVd;<<>PXn>3:75<nehgg"mcklmg+rt\7f'Drd~RQa0133[]i;97;986hcbmi,gimjgm%|~u!Bxnp\[k6798UYi~{ct007?cjedb%h`fc`d.uq|*K\7fg{UTb=>>2^Pfwpjs9;>0jalck.aoohic'~xs#@v`r^]m4575W[oxyaz=189ehgjl'jf`abj wsz,TKRUWKU;=45ilcnh+fjlefn${\7fv POVQ[GY6901m`obd/bnhijb(\7f{r$\CZ]_C]15<=adkf`#nbdmnf,sw~(XG^YSOQ<189ehgjl'jf`abj wsz,TKRUWKU?=45ilcnh+fjlefn${\7fv POVQ[GY2901m`obd/bnhijb(\7f{r$\CZ]_C]55d=adkf`#nbdmnf,sw~(Wg:;=82?>0c8bidkc&igg`ak/vp{+Zh788?7=3?n;gnahn)ddbgdh"y}x.]m45724;4:m6hcbmi,gimjgm%|~u!Pn12219599h1m`obd/bnhijb(\7f{r$Sc>?14>7:4g<nehgg"mcklmg+rt\7f'Vd;<<;35?3b?cjedb%h`fc`d.uq|*Yi89;=0=0>a:dofim(keafci!xry-\j566>5>5=l5ilcnh+fjlefn${\7fv _o2361:768k0jalck.aoohic'~xs#R`?037?4;7f3ofi`f!lljol`*qup&Ue<=<7<1<2g>`kjea$oaeboe-tv})wf}xTx`~30?3`?cjedb%h`fc`d.uq|*vi|{U\7fa}2>>0a8bidkc&igg`ak/vp{+uhszV~f|1<11b9ehgjl'jf`abj wsz,tkruW}g{0>0>c:dofim(keafci!xry-sjqtX|dz783?l;gnahn)ddbgdh"y}x.rmpwYsey6>2<m4fm`oo*ekcdeo#z|w/qlwvZrjx5<5=o5ilcnh+fjlefn${\7fv povq[qkwW9;i7kbmlj-`hnkhl&}yt"~ats]wiuY69k1m`obd/bnhijb(\7f{r$|cz}_uos[77e3ofi`f!lljol`*qup&zex\7fQ{mq]05g=adkf`#nbdmnf,sw~(xg~ySyc\7f_53a?cjedb%h`fc`d.uq|*vi|{U\7fa}Q:1c9ehgjl'jf`abj wsz,tkruW}g{S;?k;gnahn)ddbgdh"y}x.rmpwYseyr7<3?k;gnahn)ddbgdh"y}x.rmpwYseyr7=3?k;gnahn)ddbgdh"y}x.rmpwYseyr7>3?k;gnahn)ddbgdh"y}x.rmpwYseyr7?3?k;gnahn)ddbgdh"y}x.rmpwYseyr783?k;gnahn)ddbgdh"y}x.rmpwYseyr793?k;gnahn)ddbgdh"y}x.rmpwYseyr7:3?l;gnahn)ddbgdh"y}x.rmpwYseyrT<<m4fm`oo*ekcdeo#z|w/qlwvZrjxqU:=n5ilcnh+fjlefn${\7fv povq[qkwpV8:o6hcbmi,gimjgm%|~u!\7fnup\phv\7fW:;h7kbmlj-`hnkhl&}yt"~ats]wiu~X<8i0jalck.aoohic'~xs#}`{r^vnt}Y29j1m`obd/bnhijb(\7f{r$|cz}_uos|Z06k2lgnae lnejgZgtWVd;<==31?]`}j7f3ofi`f!cofk`[duXWg:;<>2>>b{2f>`kjea$`bifc^cp[Zh78997=3bzt0a8bidkc&fdkdmPar]\j567;585Snw`1b9ehgjl'eelenQns^]m45644;4Ttb|>a:dofim(dfmboRo|_^l3455;:7ir=n5ilcnh+ii`ajUj\7fRQa0120868Xkpe:o6hcbmi,hjankVkxSR`?011?7;Y\7fg{;j7kbmlj-okbodWhyTSc>?02>0:f\7f6k2lgnae lnejgZgtWVd;<==34?]`}j7d3ofi`f!cofk`[duXWg:;<>2;>^zlv4g<nehgg"b`gha\evYXf9:;?1:1cx3`?cjedb%gcjgl_`q\[k678:6>2Rmvo0a8bidkc&fdkdmPar]\j567;5?5Sua}1`9ehgjl'eelenQns^]m45644<4hu<m4fm`oo*jho`iTm~QPn1237909Wjsd=n5ilcnh+ii`ajUj\7fRQa0120838Xpfx:m6hcbmi,hjankVkxSR`?011?2;e~9j1m`obd/mmdmfYf{VUe<=>8<0<\g|i6i2lgnae lnejgZgtWVd;<=931?az5g=adkf`#aahib]bwZYi89:<0<0cuu3`?cjedb%gcjgl_`q\[k678>692Rmvo0a8bidkc&fdkdmPar]\j567?585Sua}1`9ehgjl'eelenQns^]m45604;4hu<m4fm`oo*jho`iTm~QPn1233959Wjsd=n5ilcnh+ii`ajUj\7fRQa0124868Xpfx:m6hcbmi,hjankVkxSR`?015?7;e~9j1m`obd/mmdmfYf{VUe<=>8<5<\g|i6k2lgnae lnejgZgtWVd;<=934?]{kw7f3ofi`f!cofk`[duXWg:;<:2;>b{2g>`kjea$`bifc^cp[Zh789=793Qlyn3`?cjedb%gcjgl_`q\[k678>6>2Rv`r0c8bidkc&fdkdmPar]\j567?5?5ot?l;gnahn)kgnchSl}P_o2342:16Virc<m4fm`oo*jho`iTm~QPn1233909Wqey=l5ilcnh+ii`ajUj\7fRQa0124838dq;30jalck.nlcleXizU\7fa}Q\7fnup\vZbnnoU{mi2?>^azk7?<nehgg"b`gha\evYseyU{by|Pr^fjbcYwim6;2Rv`r358bidkc&fdkdmPar]wiuYwf}xT~Rjffg]sea:76js946hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<1<oqq4>3ofi`f!cofk`[duX|dzT|cz}_s]gmc`Xxhn7=3Qlyn0:?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;97Usc\7f<8;gnahn)kgnchSl}Ptlr\tkruW{UoekhPp`f?5;e~:11m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1?1ltv1=>`kjea$`bifc^cp[qkwWyd\7f~R|Pdhde[ugc4;4Tota=9:dofim(dfmboRo|_uos[uhszVxThdhi_qcg878Xpfx9;6hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<3<`}7><nehgg"b`gha\evYseyU{by|Pr^fjbcYwim692a{{289ehgjl'eelenQns^vntZvi|{UySigif^rb`959Wjsd>45ilcnh+ii`ajUj\7fRzbp^rmpwYuWmcmjR~nd=1=[}iu:>1m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1=1cx0;?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;;7f~x?74fm`oo*jho`iTm~Q{mq]sjqtXzVnbjkQ\7fae>0:iss9;30jalck.nlcleXizU\7fa}Q\7fnup\vZbnnoU{mi2;>^azk7?<nehgg"b`gha\evYseyU{by|Pr^fjbcYwim6?2Rv`r358bidkc&fdkdmPar]wiuYwf}xT~Rjffg]sea:36js946hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<5<oqq4>3ofi`f!cofk`[duX|dzT|cz}_s]gmc`Xxhn793Qlyn0:?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;=7Usc\7f<8;gnahn)kgnchSl}Ptlr\tkruW{UoekhPp`f?1;e~:11m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1;1ltv1=>`kjea$`bifc^cp[qkwWyd\7f~R|Pdhde[ugc4?4Ttb|=8:dofim(dfmboRo|_uos[uhszVxThdhi_qcg838k}}827kbmlj-okbodWhyTx`~Ppovq[rYcaolT|lj30?]`}j4>3ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn7<3Qwos04?cjedb%gcjgl_`q\phvXxg~ySzQkigd\tdb;87ir>55ilcnh+ii`ajUj\7fRzbp^rmpwYpWmcmjR~nd=2=hpr512lgnae lnejgZgtW}g{S}`{r^u\`l`aWyko0<0Pcxm1=>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc484Ttb|=7:dofim(dfmboRo|_uos[uhszV}Thdhi_qcg848dq;20jalck.nlcleXizU\7fa}Q\7fnup\sZbnnoU{mi2>>mww6<=adkf`#aahib]bwZrjxVzex\7fQx_ekebZvfl585Snw`289ehgjl'eelenQns^vntZvi|{U|Sigif^rb`949Wqey>:5ilcnh+ii`ajUj\7fRzbp^rmpwYpWmcmjR~nd=0=g|4?3ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn7>3bzt3;8bidkc&fdkdmPar]wiuYwf}xT{Rjffg]sea:46Virc?74fm`oo*jho`iTm~Q{mq]sjqtX\7fVnbjkQ\7fae>0:Z~hz;=0jalck.nlcleXizU\7fa}Q\7fnup\sZbnnoU{mi2<>b{1<>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc4:4gyy<6;gnahn)kgnchSl}Ptlr\tkruW~UoekhPp`f?0;Ydqf827kbmlj-okbodWhyTx`~Ppovq[rYcaolT|lj34?]{kw403ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn783mv299ehgjl'eelenQns^vntZvi|{U|Sigif^rb`929d|~956hcbmi,hjankVkxSyc\7f_qlwvZqXl`lmS}ok<4<\g|i512lgnae lnejgZgtW}g{S}`{r^u\`l`aWyko080Pxnp13>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc4<4hu?64fm`oo*jho`iTm~Q{mq]sjqtX\7fVnbjkQ\7fae>6:iss:01m`obd/mmdmfYf{V~f|R~ats]t[aoanVzjh181_ymq6==adkf`#aahib]bwZrjxVzex\7fQx_ekebZvfl5<5`xz>4:dofim(zyxnabj _o2346723ofi`f!}psgnka)Xf9:;?<?;;gnahn)ux{ofci!Pn123243<nehgg"|\7frdol`*Yi89:==<:4fm`oo*twzlgdh"Qa013650=adkf`#\7f~}elmg+Zh788?:=n5ilcnh+wvumdeo#}|jlncgwqg`m;;:m6hcbmi,vutbefn$~lcPre]fjZo6901m`obd/srqahic'{kfS{ocie]j5c=adkf`#\7f~}elmg+wcflVnjxlQyamkg[l7?3ofi`f!}psgnka)r{lxTi`~{y328bidkc&~c~`ak/dnlcle(MDZ_UR@@NSGD66=adkf`#yf}mnf,aii`aj%NA]ZV_OMMV@AXa8;m7kbmlj-wlwkhl&ogcjgl/SCN[@KW\PUb>=5ilcnh+qnuefn$iaahib-`5*bh}}Ub====0:dofim(|axfci!jlnejg*e6'me~xRg>193e?cjedb%\7fd\7fc`d.gokbod'j;$hb{{_h165c=adkf`#yf}mnf,aii`aj%h="j`uu]j33473ofi`f!{hsol`*ckgnch#n< dnww[l77;;:0jalck.vkvhic'lfdkdm c3-gkprXa8;3=k5ilcnh+qnuefn$iaahib-`6*bh}}Ub?8?i;gnahn)s`{gdh"kcofk`+f4(lf\7f\7fSd991d9ehgjl'}byabj emmdmf)d:&ndyyQf80a8bidkc&~c~`ak/dnlcle(kfg{=b{{1b9ehgjl'}byabj emmdmf)dgdz9cxz>f:dofim(|axfci!ilnejg*@RDEUECC\JG308bidkc&~c~`ak/gnlcle(N\FGSCAARDE\m47b3ofi`f!{hsol`*`kgnch#_OB_GWOHZo5;2lgnae tipnka)adfmbo"m`mq3,`jssW`;;??=4fm`oo*rozdeo#kb`gha,gjkw9&ndyyQf10:16>`kjea$xe|boe-ehjank&ida}? dnww[l52:;1m`obd/ujqijb(neelen!lolr2+air|Vc<:??4fm`oo*rozdeo#kb`gha,gjkw9&ndyyQf8318bidkc&~c~`ak/gnlcle(kfg{>"j`uu]j5555;2lgnae tipnka)adfmbo"m`mq0,`jssW`;:4?<4fm`oo*rozdeo#kb`gha,gjkw:&ndyyQf3401?cjedb%\7fd\7fc`d.dokbod'jef|?!kotv\m20592lgnae tipnka)adfmbo"m`mq0,`jssW`2:i6hcbmi,pmtjgm%m`bifc.aliuYa}ef:=h5ilcnh+qnuefn$jaahib-`khvXn|fg><m4fm`oo*rjxVzex\7fQ}_ekebZvfl5:5=n5ilcnh+qkwWyd\7f~R|Pdhde[ugc484:o6hcbmi,phvXxg~yS\7fQkigd\tdb;:7;m7kbmlj-wiuYwf}xT~Rjffg]sea:56Vx\7f=n5ilcnh+qkwWyd\7f~R|Pdhde[ugc4:4:j6hcbmi,phvXxg~yS\7fQkigd\tdb;;7Uyx<m4fm`oo*rjxVzex\7fQ}_ekebZvfl5>5=k5ilcnh+qkwWyd\7f~R|Pdhde[ugc4=4T~y?l;gnahn)seyU{by|Pr^fjbcYwim6>2<h4fm`oo*rjxVzex\7fQ}_ekebZvfl5?5S\7fz>c:dofim(|dzT|cz}_s]gmc`Xxhn7:3?i;gnahn)seyU{by|Pr^fjbcYwim6=2R|{1b9ehgjl'}g{S}`{r^u\`l`aWyko0=0>c:dofim(|dzT|cz}_v]gmc`Xxhn7=3?l;gnahn)seyU{by|Pw^fjbcYwim692<h4fm`oo*rjxVzex\7fQx_ekebZvfl585S\7fz>c:dofim(|dzT|cz}_v]gmc`Xxhn7?3?i;gnahn)seyU{by|Pw^fjbcYwim682R|{1b9ehgjl'}g{S}`{r^u\`l`aWyko090>f:dofim(|dzT|cz}_v]gmc`Xxhn783Q}t0a8bidkc&~f|R~ats]t[aoanVzjh1;11g9ehgjl'}g{S}`{r^u\`l`aWyko080Pru3`?cjedb%\7fa}Q\7fnup\sZbnnoU{mi29>0d8bidkc&~f|R~ats]t[aoanVzjh181_sv2<>`kjea${}|jmnf,VDKX_[UNB<:4ftnob>oijea$~iQ}su]ef45<aghgg"|k_sqw[lhs4:4:<6gabmi,vaYu{}Uyij?<;hlahn)pzVxxxRgat=1=57=nfkf`#z|Prrv\mkrX98:0eclck.uq[wusW{olh6cjmcnh+AIR\V:o7`kbbmi,@JSSW8n0ahcmlj-GKPRX:m1fi`lck.FLQQY4l2gnaobd/EMVPZ2c3dofnae DNWW[0b<elgi`f!KOTV\2a=jmdhgg"J@UU]455=jmdhgg"J@UU]j858682gnaobd/EMVPZo;97;;7`kbbmi,@JSSW`692<>4mdoahn)CG\^Te1=1119nahdkc&NDYYQf<5<24>kbekf`#IAZT^k?1;773dofnae DNWW[l:168:0ahcmlj-GKPRXa5=5?n5bel`oo*gtqgiTjdh`_9];[44?WocmcRijndpbpjtX~;U9Su}{_0]`kwcnfz~:86cjmcnh+qkwW{kfS\7fjPeo36?hcjjea$x`~Pr`o\vaYbf820c{k}fmmte>vugnUna}zv159svjaXmdz\7fuRzgrdqk8586<2zycjQjmqvz[qnumzb7=3?;;qplcZcjx}sTxe|jsi>1:42<x{elShc\7ftx]wlwct`595=95\7frne\ahvsqV~c~h}g<5<20>vugnUna}zv_ujqavn;=7;=7}|`g^gntq\7fX|axn\7fe29:1<20>vugnUna}zv_ujqavn;>7;i7}|`g^gntq\7fX|axn\7feQnsrgqp9699k1{~biPelrw}ZrozlycSl}|esv?5;7e3yxdkRkbpu{\pmtb{aUj\7f~k}t=0=5g=wzfmTi`~{y^vkv`uoWhyxi\7fz33?3a?uthoVof|ywPtipfwmYf{zoyx1:11c9svjaXmdz\7fuRzgrdqk[dutm{~793?k;qplcZcjx}sTxe|jsi]bwvcu|5<1<3?m;qplcZcjx}sTxe|jsi]bwvcu|5<5=o5\7frne\ahvsqV~c~h}g_ogdeqc;87;i7}|`g^gntq\7fX|axn\7feQaefcwa9799k1{~biPelrw}ZrozlycSckhaug?6;7e3yxdkRkbpu{\pmtb{aUeijo{e=1=5g=wzfmTi`~{y^vkv`uoWgolmyk34?3a?uthoVof|ywPtipfwmYimnk\7fi1;11e9svjaXmdz\7fuRzgrdqk[kc`i}o7:7>11c9svjaXmdz\7fuRzgrdqk[kc`i}o7:374psmd[cskd890|\7fah_gwohZrozlyc0=0>3:rqkbYa}efTxe|jsi>2:45<x{elSk{cl^vkv`uo4;4:?6~}of]eqijX|axn\7fe2<>018twi`Wo\7fg`Rzgrdqk8186;2zycjQiumn\pmtb{a6>2<;4psmd[cskdV~c~h}g<783:45<x{elSk{cl^vkv`uo4?4:m6~}of]eqijX|axn\7feQnsrgqp9699h1{~biPftno[qnumzbTm~}jru>2:4g<x{elSk{cl^vkv`uoWhyxi\7fz32?3b?uthoVl~`aQ{hsgplZgt{lx\7f0>0>a:rqkbYa}efTxe|jsi]bwvcu|5>5=l5\7frne\bpjkW}byi~fParqfvq:268i0|\7fah_gwohZrozlycSl}|esv?2?699h1{~biPftno[qnumzbTm~}jru>5:4g<x{elSk{cl^vkv`uoWgolmyk30?3b?uthoVl~`aQ{hsgplZhboh~n0<0>a:rqkbYa}efTxe|jsi]mabgsm585=l5\7frne\bpjkW}byi~fPndebp`:468k0|\7fah_gwohZrozlycSckhaug?0;7f3yxdkRhzlm]wlwct`Vdnklzj<4<2g>vugnUmyabPtipfwmYimnk\7fi1850?3b?uthoVl~`aQ{hsgplZhboh~n0;0k;scn[wc`g|~Tic84re]`hn773{nThlzn_bmvjq:768:0~iQkauc\gjsi|5;5==5}d^fbpdYdg|d\7f0?0>0:pg[agsiVidycz33?33?wbXlh~jSnaznu>7:46<zmUomyoPcnwmp939991yhRjnt`]`kphs4?4:>6|k_ecweZeh}g~7;7>1119q`Zbf|hUhcx`{<6<6?wbXmg<0~iQ}su18vvr>3|doi\7fhcov78rdjnl?1|~Rolk79tvZekc8:0{\7fQkauc\gjsi|5:5==5xr^fbpdYdg|d\7f0<0>0:uq[agsiVidycz32?33?rtXlh~jSnaznu>0:46<\7f{UomyoPcnwmp929991|~Rjnt`]`kphs4<4:<6y}_ecweZeh}g~7:3?=;vp\`drfWje~by28:1<24>quWmk\7fmRm`uov?3;3<\7f{Unb;5xr^ppp2=\7fk;|{;=?>;Âɾ¹Ã¸ÐÄÍ´Ì°²Þ·³»g8Õǹ×Ä·ÝηÄγÅÄ\7fCDugc<2JKt<:?:G81>4}T>90:?i4ma;3064>4j3=<58ua12`95>h6;j0?7)?<a;300>{T=o0:?i4ma;3064>4j3=<585k15294?7=9rY=<7?<d;`b>455919i6:965:tW54c=83;1=7?66zQ54?74l3hj6<==191a>21>=2.:>84l2:&g0?27j2h:8=4?:7296?3fsS><6ou>3;05>41=9?0:97?;:0090?4b2;i1>i4r$03e>4273A;9>6*>388113=n9=>1<75f3g;94?=n;oh1<75f15194?=n<931<75f3dd94?=n;ok1<75f3gd94?=n9=81<75f41c94?=n;ji1<7*k6;1`f>hc=3:07d=la;29 a0=;jh0bi;51:9j7f?=83.o:7=lb:lg1?4<3`9h47>5$e497fd<fm?1?65f3b594?"c>39hn6`k5;68?l5d>3:1(i853b`8ja3==21b?n;50;&g2?5dj2do9784;h07f?6=,m<1>9o4ne794>=n:=31<7*k6;07e>hc=3;07d<;8;29 a0=:=k0bi;52:9j611=83.o:7<;a:lg1?5<3`8?:7>5$e4961g<fm?1865f25794?"c>38?m6`k5;78?l43<3:1(i8525c8ja3=>21b>9=50;&g2?43i2do9794;h1f`?6=,m<1?hm4ne794>=n;lh1<7*k6;1fg>hc=3;07d=ja;29 a0=;li0bi;52:9j7`?=83.o:7=jc:lg1?5<3`9n47>5$e497`e<fm?1865f3d594?"c>39no6`k5;78?l5b>3:1(i853da8ja3=>21b?h;50;&g2?5b<2do97>4;h1f7?6=,m<1?h:4ne795>=n;l81<7*k6;1f0>hc=3807d=j1;29 a0=;l>0bi;53:9j7`6=83.o:7=j4:lg1?2<3`9oj7>5$e497`2<fm?1965f3eg94?"c>39n86`k5;48?l5cl3:1(i853ea8ja3=821b?il50;&g2?5ck2do97?4;h1ge?6=,m<1?im4ne796>=n;m31<7*k6;1gg>hc=3907d=k8;29 a0=;mi0bi;54:9j7a1=83.o:7=kc:lg1?3<3`9o:7>5$e497ae<fm?1:65f3e694?"c>39o?6`k5;28?l5c:3:1(i853e18ja3=921b?i?50;&g2?5c;2do97<4;h1g4?6=,m<1?i=4ne797>=n;jl1<7*k6;1g7>hc=3>07d=le;29 a0=;m90bi;55:9j7fb=83.o:7=k3:lg1?0<3`9h87>5$e497f5<fm?1<65f3b094?"c>39h?6`k5;38?l5d93:1(i853b18ja3=:21b?n>50;&g2?5d;2do97=4;h1ab?6=,m<1?n=4ne790>=n;ko1<7*k6;1`7>hc=3?07d=md;29 a0=;j90bi;56:9l56`=831d?kk50;9l603=831d?km50;9l56c=831d?ol50;9l7cb=831d?l?50;9l7ge=831d?i;50;9l65g=83.o:7<?9:lg1?6<3f8;47>5$e4965?<fm?1=65`41:94?"c>3>;;6`k5;28?j27>3:1(i854158ja3=921d8=;50;&g2?27?2do97<4;n630?6=,m<18=94ne797>=h<991<7*k6;633>hc=3>07b:?2;29 a0=<9=0bi;55:9l057=83.o:7:?7:lg1?0<3f>;<7>5$e49051<fm?1;65`24694?"c>38>?6`k5;28?j42:3:1(i852418ja3=921d>8?50;&g2?42;2do97<4;n064?6=,m<1>8=4ne797>=h:=l1<7*k6;067>hc=3>07b<;e;29 a0=:<90bi;55:9l61b=83.o:7<:3:lg1?0<3f8?o7>5$e49605<fm?1;65`3g:94?"c>39m;6`k5;28?j5a>3:1(i853g58ja3=921d?k;50;&g2?5a?2do97<4;n1e0?6=,m<1?k94ne797>=h;o91<7*k6;1e3>hc=3>07b=i2;29 a0=;o=0bi;55:9l7c7=83.o:7=i7:lg1?0<3f9m<7>5$e497c1<fm?1;65m13294??d28?<6<8m{[64>45|l3886<?5118e>`<d28l1>=4>a;3a>4e=9009n7?k:0:95`<5?38j6p*>1g8112=O9;80(9>k:52`?l76?3:17d?>a;29?l74;3:17d??d;29?l7513:17dk7:18'`3<b?2do97>4;hg5>5<#l?0n;6`k5;38?lc2290/h;4j7:lg1?4<3`o?6=4+d78f3>hc=3907dk<:18'`3<b?2do97:4;hg1>5<#l?0n;6`k5;78?lc6290/h;4j7:lg1?0<3`=m6=4+d784a>hc=3:07d9k:18'`3<0m2do97?4;h5`>5<#l?0<i6`k5;08?l1e290/h;48e:lg1?5<3`=j6=4+d784a>hc=3>07d96:18'`3<0m2do97;4;h5;>5<#l?0<i6`k5;48?l10290/h;48e:lg1?1<3`;;57>5$e4955><fm?1<65f11594?"c>3;;46`k5;38?l77>3:1(i8511:8ja3=:21b==;50;&g2?7702do97=4;h330?6=,m<1==64ne790>=n9991<7*k6;33<>hc=3?07d??2;29 a0=9920bi;56:9j557=83.o:7??0:lg1?6<3`lm6=4+d78245=il<0:76gie;29 a0=99:0bi;52:9jba<72-n=6<>?;of6>6=<aoi1<7*k6;334>hc=3>07dhm:18'`3<6891eh84:;:kee?6=,m<1==>4ne792>=nn00;6)j9:g:8ja3=821bj:4?:%f5>c><fm?1=65ff783>!b12o20bi;52:9jb0<72-n=6k64ne797>=nn=0;6)j9:g:8ja3=<21bj>4?:%f5>c><fm?1965ff383>!b12o20bi;56:9jb5<72-n=6hh4ne794>=nml0;6)j9:dd8ja3=921bii4?:%f5>``<fm?1>65feb83>!b12ll0bi;53:9jag<72-n=6hh4ne790>=nmh0;6)j9:dd8ja3==21bi44?:%f5>``<fm?1:65fe183>!b12ml0bi;50:9j``<72-n=6ih4ne795>=nlm0;6)j9:ed8ja3=:21bhn4?:%f5>a`<fm?1?65fdc83>!b12ml0bi;54:9j`d<72-n=6ih4ne791>=nl00;6)j9:ed8ja3=>21d:94?::m57?6=3f>?6=44o7094?=h><0;66a>2983>>ifm3:17b?=1;29?j242900ci<50;9l575=831dn:4?::mg<?6=3fl:6=44o31b>5<#l?09?45ad483?>i5;10;6)j9:31:?kb22810c?=8:18'`3<5;01eh84=;:m173<72-n=6?=6;of6>6=<g;9>6=4+d7817<=il<0?76a=3583>!b12;927cj::498k754290/h;4=389m`0<132e98?4?:%f5>7263gn>6=54o363>5<#l?098<5ad482?>i5;o0;6)j9:362?kb22;10c?=j:18'`3<5<81eh84<;:m17a<72-n=6?:>;of6>1=<g;9h6=4+d78104=il<0>76a=3c83>!b12;>:7cj::798k775290/h;4=109m`0<732e9==4?:%f5>7763gn>6<54o32e>5<#l?09=<5ad481?>i58l0;6)j9:332?kb22:10c?>k:18'`3<5981eh84;;:m14f<72-n=6??>;of6>0=<g;:i6=4+d78154=il<0=76a=1`83>!b12;;27cj::198k77?290/h;4=189m`0<632e9=:4?:%f5>77>3gn>6?54o335>5<#l?09=45ad480?>i59<0;6)j9:33:?kb22=10c??;:18'`3<5901eh84:;:m156<72-n=6??6;of6>3=<g;896=4+d78164=il<0;76a=2183>!b12;8:7cj::098k77a290/h;4=209m`0<532e9=h4?:%f5>7463gn>6>54o33g>5<#l?09><5ad487?>i59j0;6)j9:302?kb22<10c??m:18'`3<5:81eh849;:m41?6=,m<1;95ad483?>i0;3:1(i85759m`0<632e<>7>5$e4931=il<0976a81;29 a0=?=1eh84<;:m44?6=,m<1;95ad487?>i1n3:1(i85759m`0<232e=i7>5$e4931=il<0=76a>3383>!b1289:7cj::198k457290/h;4>309m`0<632e:>k4?:%f5>4563gn>6?54o00f>5<#l?0:?<5ad480?>i6:m0;6)j9:012?kb22=10c<<l:18'`3<6;81eh84:;:m26g<72-n=6<=>;of6>3=<g88j6=4+d78274=il<0<76a=2`83>!b12;827cj::198k74?290/h;4=289m`0<632e9>:4?:%f5>74>3gn>6?54o305>5<#l?09>45ad480?>i5:<0;6)j9:30:?kb22=10c?<;:18'`3<5:01eh84:;:m166<72-n=6?<6;of6>3=<g?n1<7*k6;4`?kb22910c;l50;&g2?0d3gn>6<54o7c94?"c>3<h7cj::398k3?=83.o:78l;of6>6=<g?21<7*k6;4`?kb22=10c;950;&g2?0d3gn>6854o7494?"c>3<h7cj::798k755290/h;4=309m`0<732e9?=4?:%f5>7563gn>6<54o30e>5<#l?09?<5ad481?>i5:l0;6)j9:312?kb22:10c?<k:18'`3<5;81eh84;;:m16f<72-n=6?=>;of6>0=<g;8i6=4+d78174=il<0=76a6a;29 a0=101eh84?;:m:<?6=,m<1545ad482?>i>?3:1(i85989m`0<532e2:7>5$e49=<=il<0876a65;29 a0=101eh84;;:m:0?6=,m<1545ad486?>i>;3:1(i85989m`0<132e2>7>5$e49=<=il<0<76a>1783>!b128;>7cj::198k473290/h;4>149m`0<632e:=>4?:%f5>4723gn>6?54o031>5<#l?0:=85ad480?>i6980;6)j9:036?kb22=10c<??:18'`3<69<1eh84:;:m24c<72-n=6<?:;of6>3=<g8:n6=4+d78250=il<0<76l<a383>1<729q/=<h5b49K574<@89=7E::;h42>5<<am=1<75f4983>>i68h0;66sm3`f94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa52g=8391<7>t$03e>4523A;9>6F>379j1g<722ch<7>5;nf2>5<<uk;8;7>51;294~"69o0i56F>239K560<gk21<75rb06g>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd61o0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa5f>=8391<7>t$03e>4523A;9>6F>379j1g<722ch<7>5;nf2>5<<uk;nj7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm14394?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn<=7:182>5<7s-;:j7?=4:J267=O9:<0ci=50;9~f6g1290?6=4?{%32b?d23A;9>6F>379K00=n>80;66gk7;29?l2?2900c<>n:188yg5f<3:197>50z&25c<e>2B:>?5G1248L13<a?;1<75f4`83>>oc?3:17d:7:188k46f2900qo=n7;291?6=8r.:=k4m6:J267=O9:<0D9;4i7394?=n<h0;66gk7;29?l2?2900c<>n:188yg5fm3:197>50z&25c<e<2B:>?5G1248m37=831b8l4?::k6a?6=3`>36=44o02b>5<<uk9jj7>55;294~"69o0i86F>239K560<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo=ma;297?6=8r.:=k4l5:J267=#jo0jh6F>379jfg<722cio7>5;nf2>5<<uk9i47>53b83>5}]<>0=wl4m:36960<503826p*>1g8204=O9;80enj50;9jg`<722cjj7>5;h`3>5<<a88=6=44i004>5<<a<i1<75f5e83>>o69j0;66g>1e83>>o413:1(i85399m`0<732c8;7>5$e497==il<0:76g<6;29 a0=;11eh84=;:k01?6=,m<1?55ad480?>o4<3:1(i85399m`0<332c8?7>5$e497==il<0>76g<2;29 a0=;11eh849;:k75?6=,m<18=5ad483?>o4n3:1(i85419m`0<632c8i7>5$e4905=il<0976g<d;29 a0=<91eh84<;:k0g?6=,m<18=5ad487?>o4j3:1(i85419m`0<232c8m7>5$e4905=il<0=76g78;29 a0=0>1eh84?;:k;2?6=,m<14:5ad482?>o?=3:1(i85869m`0<532c387>5$e49<2=il<0876g73;29 a0=0>1eh84;;:k;6?6=,m<14:5ad486?>o?93:1(i85869m`0<132c3<7>5$e49<2=il<0<76g61;29 a0=191eh84?;:k;b?6=,m<15=5ad482?>o?m3:1(i85919m`0<532c3h7>5$e49=5=il<0876g7c;29 a0=191eh84;;:k;f?6=,m<15=5ad486?>o?i3:1(i85919m`0<132c357>5$e49=5=il<0<76a>1983>>i6900;66a>0c83>>i68j0;66an3;29 a0=i;1eh84?;:mb5?6=,m<1m?5ad482?>if83:1(i85a39m`0<532e2j7>5$e49e7=il<0876a6e;29 a0=i;1eh84;;:m:`?6=,m<1m?5ad486?>i>k3:1(i85a39m`0<132e2n7>5$e49e7=il<0<76anc;29 a0=ik1eh84?;:mbe?6=,m<1mo5ad482?>if13:1(i85ac9m`0<532ej47>5$e49eg=il<0876an7;29 a0=ik1eh84;;:mb2?6=,m<1mo5ad486?>if=3:1(i85ac9m`0<132ej87>5$e49eg=il<0<76sm3`:94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa7d?=83?1<7>t$03e>g2<@8897E?<6:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e;hk1<7;50;2x 47a2k>0D<<=;I302>o193:17d:n:188m0c=831b854?::m24d<722wi?ll50;794?6|,8;m6o:4H001?M74>2c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm3`a94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa5a5=83?1<7>t$03e>g2<@8897E?<6:&ab?6<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo?k5;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9jn1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?k9;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9m=1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3`a?6==3:1<v*>1g8a2>N6:;1C=>84$cd96>o193:17d:n:188ma1=831b854?::m24d<722wi=nh50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7c93:197>50z&25c<e<2B:>?5G1248 g`=82c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm1b`94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg7dk3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`2fa<72;0;6=u+10d9g6=O9;80(oh52:J273=njk0;66ak1;29?xd6jj0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa7=7=83?1<7>t$03e>f?<@8897)li:228L4513`hi6=44ica94?=njm0;66gme;29?jb62900qo?l0;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th:nk4?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb0a0>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?l2;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa5f0=83>1<7>t$03e>fg<@8897E?<6:k6f?6=3`==6=44i03a>5<<gm;1<75rb0a6>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd6k00;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa5=3=83?1<7>t$03e>g2<@8897E?<6:&ab?6<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo?77;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9>l1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?7b;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9131<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3;4?6==3:1<v*>1g8a2>N6:;1C=>84$cd96>o193:17d:n:188ma1=831b854?::m24d<722wi=5?50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7?;3:197>50z&25c<e<2B:>?5G1248 g`=82c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm16f94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg70m3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`22c<72;0;6=u+10d9g6=O9;80(oh52:J273=njk0;66ak1;29?xd6>l0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa533=8381<7>t$03e>f5<@8897)li:29K560<akh1<75`d083>>{e9>81<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f41629086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th:;84?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e9>>1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?88;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th:;:4?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb05a>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?ia;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9oi1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3e0?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e:9:1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3ea?6==3:1<v*>1g8a0>N6:;1C=>84$cd94>o193:17d:n:188m0c=831b854?::m24d<722wi=k;50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7a>3:197>50z&25c<e>2B:>?5G1248 g`=:2c==7>5;h6b>5<<am=1<75f4983>>i68h0;66sm1g:94?3=83:p(<?i:c68L4453A;8:6*mf;28m37=831b8l4?::k6a?6=3`>36=44o02b>5<<uk;m>7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm1g194?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn<k;:181>5<7s-;:j7m<;I316>"en380D<=9;h`a>5<<gm;1<75rb0g0>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?m3;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3f3?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl>e783>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f4cf290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c3f=?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e9ln1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f4cd29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th:j=4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e:1>1<7:50;2x 47a2j20D<<=;%`e>77<@89=7dlm:188mge=831bni4?::m`5?6=3th8>44?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb234>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd4<=0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn>;j:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`20`<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm15c94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg41>3:187>50z&25c<e;2B:>?5G1248m37=831b9h4?::k7<?6=3f;;m7>5;|`11c<72=0;6=u+10d9f6=O9;80D<=9;h42>5<<a<o1<75f4983>>i68h0;66sm15`94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>o?:180>5<7s-;:j7m:;I316>"en3?0D<=9;h`a>5<<aki1<75`d083>>{e;1>1<7;50;2x 47a2j30D<<=;%`e>66<@89=7dlm:188mge=831bni4?::kaa?6=3fn:6=44}c157?6=<3:1<v*>1g8`3>N6:;1/nk48;I302>oej3:17dll:188mgb=831dh<4?::\7fa6g?=83>1<7>t$03e>g5<@8897E?<6:J71>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th94;4?:583>5}#98l1o55G1308 g`=:81C=>84ic`94?=njj0;66gmd;29?je62900qo=9f;291?6=8r.:=k4l9:J267=#jo09>6F>379jfg<722cio7>5;h`g>5<<ako1<75`d083>>{e9==1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f42?29096=4?{%32b?e43A;9>6*mf;08L4513`hi6=44oe394?=zj8?<6=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg72<3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`225<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<;j:186>5<7s-;:j7l;;I316>N6;?1/nk4?;h42>5<<a=k1<75f5d83>>o303:17b??a;29?xd6=j0;684?:1y'54`=j=1C=?<4H015?!da291b:<4?::k7e?6=3`?n6=44i5:94?=h99k1<75rb355>5<3290;w)?>f;`0?M75:2B:?;5f6083>>o2m3:17d:7:188k46f2900qo?:a;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9<31<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c36<?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e9?>1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c356?6==3:1<v*>1g8a0>N6:;1C=>84$cd94>o193:17d:n:188m0c=831b854?::m24d<722wi>:m50;694?6|,8;m6n64H001?!da2;;0D<=9;h`a>5<<aki1<75fbe83>>id93:17pl=6183>1<729q/=<h5b29K574<@89=7d8>:188m0c=831b854?::m24d<722wi>;?50;694?6|,8;m6o=4H001?M74>2c==7>5;h7f>5<<a=21<75`11c94?=zj;<96=4;:183\7f!76n3h87E?=2:J273=n>80;66g:e;29?l2?2900c<>n:188yg41;3:187>50z&25c<e;2B:>?5G1248m37=831b9h4?::k7<?6=3f;;m7>5;|`121<72=0;6=u+10d9f6=O9;80D<=9;h42>5<<a<o1<75f4983>>i68h0;66sm27794?2=83:p(<?i:c18L4453A;8:6g91;29?l3b2900e9650;9l55g=831vn?;7:187>5<7s-;:j7l<;I316>N6;?1b:<4?::k6a?6=3`>36=44o02b>5<<uk8>57>54;294~"69o0i?6F>239K560<a?;1<75f5d83>>o303:17b??a;29?xd5=h0;694?:1y'54`=j:1C=?<4H015?l062900e8k50;9j0=<722e:<l4?::\7fa60d=83>1<7>t$03e>g5<@8897E?<6:k55?6=3`?n6=44i5:94?=h99k1<75rb37`>5<3290;w)?>f;`0?M75:2B:?;5f6083>>o2m3:17d:7:188k46f2900qo<:d;290?6=8r.:=k4m3:J267=O9:<0e;?50;9j1`<722c?47>5;n33e?6=3th99h4?:583>5}#98l1n>5G1308L4513`<:6=44i4g94?=n<10;66a>0`83>>{e;;o1<7=50;2x 47a2j<0D<<=;%`e>7`<@89=7dlm:188mge=831do<4?::\7fa77b=83>1<7>t$03e>fg<@8897E?<6:k6f?6=3`==6=44i03a>5<<gm;1<75rb20`>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd4;;0;6>4?:1y'54`=k?1C=?<4$cd96c=O9:<0eol50;9jff<722eh=7>5;|`074<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm32294?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg54>3:1?7>50z&25c<d>2B:>?5+bg81b>N6;?1bno4?::kag?6=3fi:6=44}c101?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl<3583>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f65f29086=4?{%32b?e23A;9>6*mf;0e?M74>2cin7>5;h``>5<<gm;1<75rb21:>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo=<8;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa76`=8391<7>t$03e>f0<@8897)li:3d8L4513`hi6=44ica94?=hk80;66sm32g94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>=k:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`006<72:0;6=u+10d9g3=O9;80(oh52g9K560<akh1<75fbb83>>id93:17pl<4383>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi?9?50;194?6|,8;m6<=:;I316>N6;?1b9o4?::k`4?6=3fn:6=44}c171?6=;3:1<v*>1g8`2>N6:;1/nk4=f:J273=njk0;66gmc;29?je62900qo<88;290?6=8r.:=k4l7:J267=#jo0?56F>379jfg<722cio7>5;h`g>5<<gm;1<75rb26:>5<4290;w)?>f;a5?M75:2.ij7<i;I302>oej3:17dll:188kf7=831vn>:7:187>5<7s-;:j7mn;I316>N6;?1b9o4?::k42?6=3`;:n7>5;nf2>5<<uk9?;7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm35f94?5=83:p(<?i:b48L4453-hm6?h4H015?lde2900eom50;9lg4<722wi?9m50;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:>i6=4<:183\7f!76n3;896F>239K560<a<h1<75fc183>>ic93:17pl<5083>6<729q/=<h5c79K574<,kl1>k5G1248mgd=831bnn4?::m`5?6=3th89=4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;=l1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo=:5;297?6=8r.:=k4l6:J267=#jo09j6F>379jfg<722cio7>5;na2>5<<uk9>87>54;294~"69o0hm6F>239K560<a<h1<75f7783>>o69k0;66ak1;29?xd4=:0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn>;6:180>5<7s-;:j7m9;I316>"en38m7E?<6:kaf?6=3`hh6=44ob394?=zj:?36=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg52?3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi?8j50;194?6|,8;m6n84H001?!da2;l0D<=9;h`a>5<<aki1<75`c083>>{e;<i1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f63e29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th89k4?:283>5}#98l1o;5G1308 g`=:o1C=>84ic`94?=njj0;66al1;29?xd5?l0;694?:1y'54`=k11C=?<4$cd964=O9:<0eol50;9jff<722cih7>5;na2>5<<uk9;57>52;294~"69o0h86F>239'fc<53A;8:6gmb;29?je62900qo=?8;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th9<<4?:383>5}#98l1o>5G1308 g`=;2B:?;5fbc83>>ic93:17pl<0b83>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi?=l50;194?6|,8;m6<=:;I316>N6;?1b9o4?::k`4?6=3fn:6=44}c13b?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl<0d83>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f675290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c125?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e;8?1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f67329086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th8=54?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;8h1<7<50;2x 47a2j>0D<<=;%`e>7=O9:<0eol50;9lg4<722wi?<o50;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:286=4::183\7f!76n3i27E?=2:&ab?573A;8:6gmb;29?ldd2900eoj50;9jf`<722eo=7>5;|`05`<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm30f94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg5593:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`065<72:0;6=u+10d9563<@8897E?<6:k6f?6=3`i;6=44oe394?=zj:8?6=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg55;3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi??950;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:8=6=4<:183\7f!76n3;896F>239K560<a<h1<75fc183>>ic93:17pl<2`83>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi>5>50;694?6|,8;m6n64H001?!da2;;0D<=9;h`a>5<<aki1<75fbe83>>id93:17pl=8383>1<729q/=<h5c99K574<,kl1><5G1248mgd=831bnn4?::ka`?6=3fi:6=44}c15e?6=<3:1<v*>1g8a1>N6:;1C=>84i7394?=nl>0;66g;8;29?j77i3:17pl>5783>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f60?290>6=4?{%32b?d33A;9>6F>379j24<722c?m7>5;h7f>5<<a=21<75`11c94?=zj:<26=4;:183\7f!76n3h87E?=2:J273=n>80;66g:e;29?l2?2900c<>n:188yg72;3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi?;;50;794?6|,8;m6n74H001?!da2=80D<=9;h`a>5<<aki1<75fbe83>>oem3:17bj>:188yg5193:187>50z&25c<d?2B:>?5+bg8a5>N6;?1bno4?::kag?6=3`ho6=44oe394?=zj:<=6=4;:183\7f!76n3i<7E?=2:&ab?2>3A;8:6gmb;29?ldd2900eoj50;9l`4<722wi?;950;794?6|,8;m6n74H001?!da2?1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f7dd290?6=4?{%32b?d43A;9>6F>379K00=#jo0;7d8>:188m0c=831b854?::m24d<722wi>i950;794?6|,8;m6n74H001?!da201C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f7?e290?6=4?{%32b?e03A;9>6*mf;12?M74>2cin7>5;h``>5<<akn1<75`d083>>{e:m21<7;50;2x 47a2j30D<<=;%`e><=O9:<0eol50;9jff<722cih7>5;h`f>5<<gm;1<75rb3`b>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:m81<7=50;2x 47a2j?0D<<=;%`e>==O9:<0eol50;9jff<722eo=7>5;|`1fg<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8<m7>54;294~"69o0h46F>239'fc<63A;8:6gmb;29?ldd2900eoj50;9lg4<722wi>nm50;194?6|,8;m6n;4H001?!da211C=>84ic`94?=njj0;66ak1;29?xd5l<0;6>4?:1y'54`=k<1C=?<4$cd9<>N6;?1bno4?::kag?6=3fn:6=44}c0``?6=;3:1<v*>1g8`1>N6:;1/nk47;I302>oej3:17dll:188ka7=831vn?mj:180>5<7s-;:j7m:;I316>"en320D<=9;h`a>5<<aki1<75`d083>>{e:jl1<7=50;2x 47a2j?0D<<=;%`e>==O9:<0eol50;9jff<722eo=7>5;|`1`5<72:0;6=u+10d9g0=O9;80(oh58:J273=njk0;66gmc;29?jb62900qo<k1;297?6=8r.:=k4l5:J267=#jo037E?<6:kaf?6=3`hh6=44oe394?=zj;nm6=4;:183\7f!76n3h87E?=2:J273=O<<1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm31494?2=83:p(<?i:c18L4453A;8:6*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`1b=<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8o57>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3fb>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:mh1<7:50;2x 47a2k90D<<=;I302>N3=2.ij7>4i7394?=n=l0;66g;8;29?j77i3:17pl=db83>1<729q/=<h5b29K574<@89=7E::;%`e>5=n>80;66g:e;29?l2?2900c<>n:188yg4cl3:187>50z&25c<e;2B:>?5G1248L13<,kl1<6g91;29?l3b2900e9650;9l55g=831vn?jj:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa756=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd4880;694?:1y'54`=j:1C=?<4H015?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk9;>7>54;294~"69o0i?6F>239K560<,kl1<6g91;29?l3b2900e9650;9l55g=831vn>><:187>5<7s-;:j7l<;I316>N6;?1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm31694?2=83:p(<?i:c18L4453A;8:6*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`040<72=0;6=u+10d9f6=O9;80D<=9;%`e>5=n>80;66g:e;29?l2?2900c<>n:188yg4a:3:187>50z&25c<e;2B:>?5G1248L13<,kl1<6g91;29?l3b2900e9650;9l55g=831vn?h<:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6c2=83>1<7>t$03e>g5<@8897E?<6:J71>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th9j84?:583>5}#98l1n>5G1308L4513A>>7)li:19j24<722c>i7>5;h6;>5<<g8:j6=44}c0e2?6=<3:1<v*>1g8a7>N6:;1C=>84H578 g`=82c==7>5;h7f>5<<a=21<75`11c94?=zj;l<6=4;:183\7f!76n3h87E?=2:J273=O<<1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm2e194?2=83:p(<?i:b58L4453-hm6>?4H015?lde2900eom50;9jfa<722eo=7>5;|`03d<72<0;6=u+10d9g<=O9;80(oh5479K560<akh1<75fbb83>>oel3:17dlj:188ka7=831vn?7k:186>5<7s-;:j7m6;I316>"en330D<=9;h`a>5<<aki1<75fbe83>>oem3:17bj>:188yg4>03:187>50z&25c<d?2B:>?5+bg805>N6;?1bno4?::kag?6=3`ho6=44oe394?=zj;3<6=4<:183\7f!76n3i>7E?=2:&ab?><@89=7dlm:188mge=831dh<4?::\7fa6<e=83?1<7>t$03e>f?<@8897)li:89K560<akh1<75fbb83>>oel3:17dlj:188ka7=831vn?j9:187>5<7s-;:j7m8;I316>"en39:7E?<6:kaf?6=3`hh6=44icf94?=hl80;66sm28394?5=83:p(<?i:b78L4453-hm655G1248mgd=831bnn4?::mg5?6=3th95l4?:283>5}#98l1o85G1308 g`=02B:?;5fbc83>>oek3:17bj>:188yg4>:3:1?7>50z&25c<d=2B:>?5+bg8;?M74>2cin7>5;h``>5<<gm;1<75rb3;0>5<4290;w)?>f;a6?M75:2.ij764H015?lde2900eom50;9l`4<722wi>4:50;194?6|,8;m6n;4H001?!da211C=>84ic`94?=njj0;66ak1;29?xd51<0;6>4?:1y'54`=k<1C=?<4$cd9<>N6;?1bno4?::kag?6=3fn:6=44}c0:2?6=;3:1<v*>1g8`1>N6:;1/nk47;I302>oej3:17dll:188ka7=831vn?o;:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6fd=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd5jm0;694?:1y'54`=j:1C=?<4H015?M223-hm6=5f6083>>o2m3:17d:7:188k46f2900qo<6e;290?6=8r.:=k4m3:J267=O9:<0D9;4$cd94>o193:17d;j:188m1>=831d==o50;9~f7?a290?6=4?{%32b?d43A;9>6F>379K00=#jo0;7d8>:188m0c=831b854?::m24d<722wi>l>50;694?6|,8;m6o=4H001?M74>2B?96*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`1e4<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8j>7>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3c0>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:j?1<7:50;2x 47a2k90D<<=;I302>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th9o;4?:583>5}#98l1n>5G1308L4513-hm6=5f6083>>o2m3:17d:7:188k46f2900qo<l7;290?6=8r.:=k4m3:J267=O9:<0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3a;>5<3290;w)?>f;`0?M75:2B:?;5+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6f?=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd5kh0;694?:1y'54`=j:1C=?<4H015?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8i;7>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3`;>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e9<:1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?6b;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa73e=83>1<7>t$03e>f1<@8897)li:c08L4513`hi6=44ica94?=njm0;66ak1;29?xd6j80;6?4?:1y'54`=k:1C=?<4$cd97>N6;?1bno4?::mg5?6=3th:5n4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;?n1<7:50;2x 47a2k?0D<<=;I302>"en380e;?50;9j`2<722c?47>5;n33e?6=3th8;>4?:483>5}#98l1o45G1308 g`=:;1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f4??29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th84?4?:483>5}#98l1o45G1308 g`=:;1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f61e290?6=4?{%32b?d23A;9>6F>379'fc<53`<:6=44ie594?=n<10;66a>0`83>>{e;1?1<7=50;2x 47a2j?0D<<=;%`e>7`<@89=7dlm:188mge=831dh<4?::\7fa7=6=8391<7>t$03e>f3<@8897)li:3d8L4513`hi6=44ica94?=hl80;66sm18;94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>9;:186>5<7s-;:j7m6;I316>"en39;7E?<6:kaf?6=3`hh6=44icf94?=njl0;66ak1;29?xd61l0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn<o>:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`2e1<72:0;6=u+10d9563<@8897E?<6:k6f?6=3`i;6=44oe394?=zj8h;6=4::183\7f!76n3h?7E?=2:J273=#jo0;7d8>:188m1g=831b9h4?::k7<?6=3f;;m7>5;|`2f7<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<o9:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`2e2<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<o7:186>5<7s-;:j7l;;I316>N6;?1/nk4?;h42>5<<a=k1<75f5d83>>o303:17b??a;29?xd6ih0;684?:1y'54`=j=1C=?<4H015?!da291b:<4?::k7e?6=3`?n6=44i5:94?=h99k1<75rb0c`>5<2290;w)?>f;`7?M75:2B:?;5+bg83?l062900e9o50;9j1`<722c?47>5;n33e?6=3th:mh4?:483>5}#98l1n95G1308L4513-hm6=5f6083>>o3i3:17d;j:188m1>=831d==o50;9~f4g5290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c3b1?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl>9783>7<729q/=<h5c29K574<,kl1>6F>379jfg<722eo=7>5;|`2=0<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm37g94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk9<=7>55;294~"69o0h56F>239'fc<482B:?;5fbc83>>oek3:17dlk:188mgc=831dh<4?::\7fa720=8391<7>t$03e>f3<@8897)li:3d8L4513`hi6=44ica94?=hl80;66sm36g94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk;3o7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo=8d;291?6=8r.:=k4l9:J267=#jo09>6F>379jfg<722cio7>5;h`g>5<<ako1<75`d083>>{e;>i1<7;50;2x 47a2j30D<<=;%`e>66<@89=7dlm:188mge=831bni4?::kaa?6=3fn:6=44}c144?6==3:1<v*>1g8`=>N6:;1/nk4<0:J273=njk0;66gmc;29?ldc2900eok50;9l`4<722wi=io50;094?6|,8;m6n=4H001?!da2:1C=>84ic`94?=hl80;66sm36d94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk9<>7>55;294~"69o0h56F>239'fc<482B:?;5fbc83>>oek3:17dlk:188mgc=831dh<4?::\7fa723=83?1<7>t$03e>f?<@8897)li:228L4513`hi6=44ica94?=njm0;66gme;29?jb62900qo?nd;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c36b?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7c03:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;o<7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?k2;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3g0?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7c>3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;3m7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?72;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3;0?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7?>3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;347>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?if;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3e3?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7a13:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;mn7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?id;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c36`?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg72j3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;=?7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?91;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c10f?6=;3:1<v*>1g8`2>N6:;1/nk4=f:J273=njk0;66gmc;29?je62900qo=67;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1:=?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg5>j3:1>7>50z&25c<d<2B:>?5+bg80?M74>2cin7>5;na2>5<<uk92h7>52;294~"69o0h86F>239'fc<43A;8:6gmb;29?je62900qo=6f;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1;f?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg5?l3:1>7>50z&25c<d<2B:>?5+bg80?M74>2cin7>5;na2>5<<uk93j7>52;294~"69o0h86F>239'fc<43A;8:6gmb;29?je62900qo=61;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1:7?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg7fj3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;j57>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?nf;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}r47>5<6;rT=863<b`8af>;60<0?m63>8687e>;60k0?m63>8887e>;6090?m63>8087e>;60:0?m63>6187e>;6=l0?m63>5b87e>;6=h0?m63>5887e>;6>=0?m63>6387e>;4>10==63<668g5>;4>j0in6s|b683>0}Y>:1Un:523`29fg=:;>k1nn5236`955g<uz3j6=4={_;b?85fn3;;m6s|10594?0|V8;<70=93;`g?851=3hn70=91;`a?851>3ho70=97;``?xu61h0;6>u218d91g=:90i1h<5218g91g=z{::j6=4<{<13g?b6349;j7;m;<13a?3e3ty:n44?:3y>5g4=>816=l85d09~w74f290?wS<=a:?2`<<68h16=io5bc9>72`=jl1v\7f<78:180\7f87>j3?i70?6c;7a?87>13n:7p}<a483>60|5:k=6<>n;<1b3?2f349i47?>c:?2`6<2m27:h84:e:?2`<<2m27:h:4:e:?2g`<c?27:ok4:e:?2`4<2m27:jl4:e:?2bf<2m279<=4:e:?2b`<2m27:j84:e:?2b3<c?27:j54:e:?123<2m279;;4:e:?125<2m279:<4:e:?127<2m279:>4:e:?121<2m279:84:e:?1b=<2m279j?4:e:?1b6<2m279j94:e:?1b0<2m279j;4:e:?1b2<2m279m94:e:?1gg<2m2795h4:e:?1=c<2m279m=4:e:?1e4<2m279m?4:e:?1e6<2m279o84:e:?1g3<2m279o:4:e:?1g=<2m279o44:e:?1gd<2m278;o4k7:?2f5<2m27:n?4:e:?2e2<2m27:m54:e:?2ed<2m27:mn4:e:?2e`<2m2wx=8;50;0x94302m;01<;7:4`8yv76i3:19vP>1`9>7d4=l>16?l85d69>7d2=l>16?l95d69~w34=83>pR;<4=246>gb<5:<<6ol4=24g>46f3ty:::4?:3y>51b=l816=8m5609~w33=83;3wS8:;<1a<?75>27:h>4;a:?2`0<3i27:h44;a:?2`2<3i27:oh4;a:?2gc<3i27:h<4;a:?2bd<3i27:jn4;a:?145<3i27:jh4;a:?2b0<3i27:j;4;a:?2b=<3i278m=4k1:?2f5<3i27:n?4;a:?2e2<3i27:m54;a:?2ed<3i27:mn4;a:?2e`<3i2wx>>>50;6xZ7573493=7lj;<3ea?77i27:jk4mb:\7fp530=838p1<:n:e38943f2?;0q~<ia;297~;5l10io63<00824d=::m<1ni5rs010>5<4sW;8?63<a18ag>;4?h0ih6s|23494?2|V;8=70?k3;33e>;4090io63>d58af>{t:;>1<7:t^307?87dn3;;m63<7d8aa>;6l90in6s|11f94?5esW;;h63<a387<>;4im0?463<a587<>;4il0?463<ag87<>;4j10>h63<a987<>;4i00?463<a`87<>;4ik0?463<ab87<>;60<0?463>8687<>;60k0?463>8887<>;6090?463>8087<>;60:0?463=5g87<>;5j00?463>6187<>;6=l0?463>5b87<>;6=h0?463>5887<>;6>=0?463>6387<>;5=10?463=5887<>;5=h0?463=5c87<>;5=j0?463=5e87<>;5=l0?463<6`87<>;4>10?463<6887<>;5jj0?463=b`87<>;5jk0?463=dg87<>;48?0?463=d887<>;5lh0?463=dc87<>;5lj0?463=de87<>;5ll0?463<0187<>;4880?463<0387<>;48:0?463<0587<>;48<0?463=be87<>;5j>0?463=b987<>;4>m0?46s|2dd94?4|5::?6;?4=3d5>46f3ty9>84?:5y]673<58n:6<>n;<14a?dd34;o>7lm;|q:6?6=:rT2>63<a9824d=z{;886=4;{_017>;6kl0:<l521cf9fg=:;>l1nn5rs2c0>5<4jr78m?4>0`9>7db==l16?l:54`9>7dc==l16?lh55d9>7gg=jj16?o6510f896g?2<o01>o6:4g896gf2<o01>om:4g896gd2<o01<6::4g894>02<o01<6m:4g894>>2<o01<6?:e5894>62<o01<6<:4g8973a2<o01?l6:4g894072<o01<;j:4g8943d2<o01<;n:4g8943>2<o01<8;:4g894052<o01?;7:4g8973>2<o01?;n:4g8973e2<o01?;l:4g8973c2<o01?;j:4g8960f2m=01>87:4g8960>2<o01?ll:4g897df2<o01?lm:4g897ba2<o01>>9:4g897b>2<o01?jn:4g897be2<o01?jl:4g897bc2<o01?jj:4g896672<o01>>>:4g896652<o01>><:4g896632<o01>>::4g897dc2<o01?l8:4g897d?2<o01>8k:e58yv7113:1>v3>61855>;6=:0o=6s|23594?2|V;8<70?k5;33e>;4?j0ii63>d78af>{t1<0;6?uQ949>7dd=99k0q~<jc;296~;4880==63=f2824d=z{8826=4<7z\26<=:;h<185523`590==:;k219n521e190==:9m?185521e;90==:9m=185521bg90==:9jl185521e390==:9ok185521ga90==::9:185521gg90==:9o?185521g490==:9o21855227490==::><1855227290==::?;1855227090==::?91855227690==::??185522g:90==::o8185522g190==::o>185522g790==::o<185522g590==::h>185522b`90==::0o1855228d90==::h:185522`390==::h8185522`190==::j?185522b490==::j=185522b:90==::j3185522bc90==:;>h185521c290==:9k8185521`590==:9h2185521`c90==:9hi185521`g90==z{;996=4;{_006>;4080io63=01824d=::9;1no5rs8494?4|V0<01>ol:02b?xu5ih0;6?u22ca924=::0;1h<5rs3d`>5<5s48o;7lm;<137?77i2wx5:4?:3y]=2=:;hn1==o4}r;;>5<5sW3370=ne;33e>{t98;1<7<t^032?842j3;;m6s|13g94?4|V88n70<93;33e>{t:h21<7<t=3`b>37<5;386i?4}r0bb?6=:r795:4k1:?1e6<192wx>ok50;0x97?c2kh01?m::02b?xu4>00;6hu22969ff=:;?91nn522949ff=::>i1nn5226:9ff=::>o1nn522929ff=::181nn5237;955g<5:<>6om4=242>ge<5:<=6ol4=244>gb<5;=j6om4}r0f<?6=:r79h84k1:?1`g<192wx>k?50;0x96612?;01?h7:02b?xu5no0;68u22e59f`=::m81nn522ed924=:;9<1==o4=3f0>gb<uz8i97>52z?1ff<68h16>no5609~w44c2909wS?=d:?127<68h1v\7f<>j:181\7f[77m279954>0`9~w4552909wS?<2:?123<68h1v\7f<<l:181\7f[75k279:<4>0`9~w7da2908w0<6b;`g?84>l3hh70<l6;33e>{t9::1<7<t^013?841=3;;m6s|10494?4|V8;=70<:f;33e>{t:j:1<7:t=3;a>gd<5;3o6oj4=3;b>gd<5;i<6<>n;|q26c<72;qU=?h4=347>46f3ty:594?:2y>5<>==k16=4755c9>5<3=l81v\7fnl50;ax945?2m901<ll:648940b2><01<k<:64894202><01><k:4`8964d2<h01>:7:4`896202<h01>>7:648967f2><01<7::648yv5f?3:1>v3<a7855>;4i>0:<l5rs3c`>5<5s48247j>;<0b6?063ty9o94?:4y>6<>=jm16>495bb9>6<e=jl16>l:5609>6fd=99k0q~<n5;296~;51?0o=63=b6855>{t1=0;6?uQ959>7dg=99k0q~<m2;296~;5j00:<l522b5924=z{8;?6=4={_320>;5=l0:<l5rs030>5<5sW;:?63=5e824d=z{8:m6=4={_33b>;5=00:<l5rs3a2>5<5s482o7lm;<0`<?77i2wx=9h50;1x94362m;01<;;:4`894342<h0q~<nb;296~;51m0o=63=9d855>{t9;k1<7<t^00b?840>3;;m6s|34c94?4|5:?n68l4=27`>a7<uz;9n7>52z\26g=::?:1==o4}r326?6=:rT:=?5224a955g<uz;=m7>52z?227<1927:9;4k1:\7fp5<5=839p1<o8:73894?12m;01<7::03a?xu>;3:1>vP63:?0e<<68h1v\7f<??:181\7f[7682799l4>0`9~w7cb2909w0=?3;42?84a=3;;m6s|ad83>7}Yil16?;o511c8yv5bm3:15v3<ae87e>;4il0?m63<ag87e>;4i10?m63<a887e>;4ih0?m63<ac87e>;4ij0?m63<678g5>{tn80;69?t^568Z44?3W;9=6P;3:\g6>X6::1Uh55Qf09>561=j116=4h5779>507=??16?l:5609>7d1=>816?o65ce9>7g>=kl16?o65ag9>7g>=9;=01>l7:83896d?21l01>l7:9g896d?21n01>l7:9a896d?21h01>l7:9c896d?21301<ml:64894dd2<h01<m?:64894e42><01<m9:64894e>2><01<9j:648940b2<h01<9=:64894122><01<97:648941e2><01<h<:64894c42<h01<k8:64894cf2><01<kk:64894`72><01<:j:648942e2><01<:8:4`894302><01<;;:648966?2<h01>>l:648966a2><01>?=:64896722><01>?7:648967f2<h01>?j:64896462><01><;:64896402><01><n:64894?d2><01<76:64894g52><01<o::64894?22<h0q~<<a;291~X5;h16?9;5bc9>6a`=99k01>9>:cg896152ki0q~<<8;292~X5;116?9=5bc9>714=??16>ik511c8960b2ki01>9=:cg8yv44?3:1:vP=369>76`=jk16?>k5779>6ab=99k01>8j:cg896112ki0q~<<6;292~X5;?16?>o5bc9>76?=??16>im511c896132ki01>=m:c`8yv44=3:1:vP=349>760=jk16?>;5779>6ad=99k01>9;:cg896172ki0q~<<4;292~X5;=16?><5bc9>767=??16>io511c896172ko01>9::ca8yv44;3:1:vP=329>77c=jk16??j5779>6a?=99k01>9>:ca896122ko0q~<jd;296~;48;0==63=f5824d=z{;k=6=4={<0:1?b6348i478>;|q2e5<72:q6=l:55c9>5d4=l816=l;55c9~w6032909w0=98;6b?851=3n:7p}<0683>6}:;921h<5231a91g=:;9h19o5rs353>5<5s49>i7m?;<16b?e63ty9:k4?:2y>70b=k816?8m510`8963e2j:0q~=>f;297~;4:80o=63<2586f>;4::0>n6s|27a94?5|5:?:6n?4=273>47e349?j7m?;|q12=<72:q6?9=5c09>714=98h01>:>:b28yv40<3:1?v3<338`5>;4;80:=o523229g5=z{;<j6=4<{<17=?e6349?47?>b:?002<d82wx>;k50;1x963>2j;01>;7:03a?852?3i;7p}:2;296~;40:0o=63<838ag>{t:>?1<7=t=215>f7<5:9>6<?m;<100?e73ty9::4?:2y>76`=k816?>k510`8965c2j:0q~<99;296~;4<=0h<63<448`5>{t:?h1<7=t=26g>f7<5:>h6<?m;<17f?e73ty9:i4?:2y>703=k816?8:510`896342j:0q~==5;297~;4:00>n63<268g5>;4:h0>n6s|26194?5|5:8n6n?4=20g>47e3499o7m?;|q167<72<qU>?<4=2:2>gd<5:?m6om4=3c7>46f349<j7lk;|q165<72<qU>?>4=2:2>gb<5:?o6om4=3c0>46f349<o7lm;|q15c<72<qU><h4=27:>ge<5;k96<>n;<1;1?de349<o7lk;|q15`<72<qU><k4=276>ge<5:286ol4=3c2>46f3493<7lm;|q15a<72<qU><j4=272>ge<5:286oj4=3c3>46f349<i7lm;|q15f<72<qU><m4=2:7>gd<5:>o6om4=3;e>46f349<i7lk;|q15g<72<qU><l4=2:7>gb<5:>26om4=3;f>46f349<j7lm;|q41?6=0rT98?5Q749>7g>=;016=o=5bc9>70`=jk16>nm5bb9>6c>=>816=o<511c8yv142902wS<;0:\47>;4j108;63<5e8af>;4=j0<:63=cb8af>;5km0io63>b08af>;6j90:<l5rs6094??|V;9m7S9=;<1a<?51349>57lm;<16<?11348hh7lm;<0`a?dd34;ji7??a:?2ec<ej2wx;<4?:8y]66c<V>;01>l7:27896322kh01>;;:64897eb2kh01?mi:ca894gd28:j70?nd;`a?xu083:15vP=3e9]35=:;k21?9523439fg=:;<:1;;522bd9fg=::m:1nn521`c955g<58ki6ol4}r4e>5<>sW88o6P9f:?0f=<4;2788i4mb:?00f<0>279h=4mb:?1`4<ek27:m54>0`9>5d?=jk1v\7f;k50;:xZ75e3W<n70=m8;11?85313hi70=;8;55?84c93hi70?n7;33e>;61?0in6s|21g94?2|V;:n70?75;33e>;4?=0in63>878af>{t:8:1<7:t^333?87?13;;m63<738a`>;60h0in6s|2d694?4|5;io6i?4=3d5>37<uz>o6=4={<147?de349<:7j>;|q0e1<72;q6?l<5609>7d2=99k0q~<id;297~;5l>0io63<05824d=::m91no5rs30`>5<3sW89o63>f7824d=:;1>1nn521g59fg=z{;8n6=4;{_01a>;6nh0:<l523919ff=:9oh1no5rs265>5<4s49?47j>;<17g?3e349?n7;m;|q055<72:q6?<<5d09>743==k16?<:55c9~w6272909w0=;4;7a?853:3n:7p}<3b83>6}:;:o1h<5235091g=:;=;19o5rs214>5<4s49857j>;<10a?3e3498h7;m;|q076<72:q6?>;5d09>76?==k16?>655c9~w64a2908w0=<1;f2?854=3?i70=<4;7a?xu1l3:15vP=1`9]2a=:;k218<521779fg=:9?>1==o4=266>ge<5;3:6om4=3`g>37<5:=:6oj4}r4a>5<>sW8:46P9b:?0f=<4n27::?4>0`9>715=jj16>4?5bc9>6<4=jj16?;k5bc9>535=jk1v\7f;o50;;xZ7703W<j70=m8;1f?87183;;m63<3g8ag>;51;0in63=928ag>;4>l0ih63>608af>{t>00;64uQ2048Z3?<5:h36>j4=07f>46f3498m7ll;<0:7?de348287ll;<36b?de3498n7ll;|q5<?6=1rT9=85Q699>7g>=;j16=8m511c896512ki01?7;:c`897?22ki01>9?:c`8943c2kh0q~88:18:\7f[46<2T=;63<b980f>;6=h0:<l523209ff=::0?1no522849ff=:;>:1ni5214`9fg=z{?<1<76t^330?[01349i47=n;<37<?de34;>57??a:?06`<ek2795;4mb:?034<ej2wx??l50;1x964c2m;01>=>:4`896572<h0q~=>c;297~;49l0o=63<2086f>;4:90>n6s|33094?5|5:8?6i?4=204>0d<5:8=68l4}r162?6=;r78954k1:?01f<2j2789o4:b:\7fp704=839p1>;;:e38963?2<h01>;8:4`8yv53m3:1?v3<518g5>;4==0>n63<5286f>{t;=k1<7=t=26`>a7<5:?;68l4=26e>0d<uz89n7>54z\16g=:9o?1==o4=0g7>gd<5:2?6ok4}r01<?6=<rT9>5521e5955g<5:=h6om4=0f;>gd<uz;=47>52z?21`<1927:9=4k1:\7fp644=83>pR??=;<3;f?77i27:4n4mb:?037<ej2wx=l=50;0x94g12<h01<o::e38yv73k3:1?v3>5086f>;6<l0o=63>5186f>{t9<81<7=t=074>0d<58??6i?4=075>0d<uz8;o7>54z\14f=:91;1==o4=256>gd<58296ol4}r35f?6=:r7:954k1:?221<192wx>?j50;6xZ74c34;m47??a:?0<6<em27:j44mb:\7fp51?=839p1<:k:4`8942b2<h01<:m:e38yv73=3:1?v3>46825g=:9=21h<5214;924=z{;:m6=4;{_03b>;60>0:<l523649fg=:9121no5rs32g>5<3sW8;h63>82824d=:;>>1ni521969fg=z{;8m6=4;{_01b>;6nj0:<l523979ff=:9on1no5rs32a>5<3sW8;n63>81824d=:9?l1no523679fa=z{;o86=4={<0`a?b6348m978>;|q1b`<72=q6>i95be9>6a4=jk16?=;511c897b42ki0q~<ja;296~;5l;0o=63=dd855>{t:l31<7<t=3fb>37<5;n=6i?4}r0a2?6=:r79oo491:?1fa<68h1v\7f?l;:181\7f84ej3;;m63=c8855>{t:031<7;t=3;a>ge<5;3o6ok4=3;`>a7<5;3j6om4=3c2>37<uz=m6=4={_5e?85e03237p}8d;296~X0l278n5476:\7fp3f<72;qU;n523c:9<0=z{>h1<7<t^6`896d?21>0q~9n:181\7f[1f349i476<;|q4=?6=:rT<563<b98;6>{t?10;6?uQ799>7g>=081v\7f:950;0xZ21<5:h365>4}r0a5?6=:r79o;491:?1f=<68h1v\7f?ok:181\7f84>i3n:70<n0;42?xu5m>0;6?u22ef924=::m91h<5rs3g6>5<5s48ho7j>;<0e3?063ty8;:4?:3y>73`=l816?;m5be9~w64?2909w0<76;`g?855i3n:7p}=e183>7}::m;1h<522g0924=z{:;26=4<{<12e?b6349:i7;m;<12`?3e3ty94h4?:3y>775=l816>5>5be9~w6?22909w0=;b;f2?85713hi7p}<b083>7}:;k21m8523`;924=z{:h96=4={<1a<?g1349jm78>;|q0f<<72;q6?oo5d09>7g>=j91v\7f>l8:181\7f85fn3<:70=m8;c`?xu4j?0;6?u23`g924=:;k21ml5rs2`7>5<5s49i47o7;<1bg?063ty8n84?:3y>7db=>816?o65a89~w6d42909w0=m8;c4?85fj3<:7p}<b183>7}:;k21m9523`:924=z{8i<6=4<{<3`f?3e34;ho7;m;<3`=?b63ty:o94?:2y>5f>==k16=n85d09>5f?==k1v\7f<m>:180\7f87d;3n:70?l6;7a?87d=3?i7p}>e183>7}:9jn1h<521e;924=z{8hn6=4<{<3`4?b634;h?7;m;<3`6?3e3ty:no4?:2y>5ge=l816=n>55c9>5g`==k1v\7f<ln:180\7f87dm3<:70?md;f2?87ek3;:n6s|1bc94?4|58io68l4=0a`>a7<uz;on7>52z?2gc<1927:nk4k1:\7fp5a`=838p1<j8:73894ee2m;0q~?kc;296~;6l80==63>c38g5>{t9mn1<7<t=0f0>37<58i>6i?4}r3ga?6=:r7:o54k1:?2`0<192wx=;;50;0x94022m;01<;7:b28yv7013:1?v3>7e86f>;6?l0>n63>7c8g5>{t9><1<7=t=05b>0d<58=36i?4=05a>0d<uz;<?7>53z?230<c927:;54:b:?232<2j2wx=4<50;0x941a2m;01<6m:738yv7083:1?v3>738g5>;6?<0>n63>7586f>{t9?n1<7=t=04f>a7<58=968l4=052>0d<uz;=o7>53z?2<5<1927::k4k1:?22`<69k1v\7f<9l:181\7f870n3?i70?8e;f2?xu60m0;6?u2193924=:9>;1h<5rs0;2>5<5s4;3578>;<34`?b63ty:4h4?:3y>5=5=>816=::5d09~w4>a2909w0?75;42?870?3n:7p}>9183>7}:9>k1h<52195924=z{8h86=4={<3a7?b634;j:7m?;|q2a`<72:q6=k<55c9>5c5==k16=k>5d09~w4ce2908w0?jf;7a?87bl3n:70?i0;7a?xu6m10;6>u21dc9`4=:9ln19o521da91g=z{;:<6=4={<3e0?b6348;<78>;|q2a0<72:q6=h95d09>5`g==k16=h755c9~w4c52908w0?j3;f2?87b?3?i70?j6;7a?xu6m80;6>u21g7924=:9l>1h<521d1954d<uz;m=7>52z?2b1<2j27:j>4k1:\7fp654=838p1<h9:73894c12m;0q~<?6;296~;6nl0==63>f38g5>{t:991<7<t=0d;>37<58o26i?4}r030?6=:r7:jl491:?2af<c92wx>=;50;0x94ca2m;01<hl:738yv372909w0=83;`f?850:3n:7p}=7083>6}::?:1:<5231;9g4=:;921=<l4}r0;7?6=:r79494l1:?11`<192wx?;>50;0x960>2?;01>8>:e38yv7e<3:1>v3>998g5>;6i10==6s|26;94?4|5;?26;?4=35b>f7<uz9287>52z?133<192788:4k1:\7fp7<6=838p1>:>:e3896?62kh0q~=92;296~;4>:0o=63<6`855>{t;1i1<7<t=21;>a7<5:2o6ol4}r1;=?6=;r78?=4k1:?05g<ej279;l4md:\7fp72?=838p1>9n:e38961e2?;0q~<k4;291~;5l>0o=63=d98aa>;5l<0io63=db855>;5l?0io6s|37:94?c|5;2?6ol4=240>gd<5;2=6ol4=35`>gd<5;=36ol4=35f>gd<5;2;6ol4=3:1>gd<5:<36<>n;<151?de349==7lk;<152?dd349=;7lj;<04e?de3ty94<4?:3y>60b=>816>5<5c09~w6>b2909w0=<d;f2?85?n3hi7p}=e083>7}::m:1h<522g1924=z{;=m6=4={<06g?063483<7m>;|q0<2<72;q6?:o5bd9>7=4=l81v\7f?9k:181\7f842j3<:70<8e;a2?xu5?k0;6?u226a9g4=::<k1:<5rs3a1>5<4s48247lm;<0:g?dd348h57??a:\7fp6g5=838p1?ln:02b?84d03<:7p}>b683>7}:9h;1h<521`g924=z{;h;6=4={<0`1?06348i;7??a:\7fp7=>=838p1><l:e38971?2kn0q~?m6;296~;61l0o=63>ab855>{t9=<1<7=t=06b>0d<58>i68l4=064>a7<uz83j7>52z?063<c92794?4md:\7fp6f5=83>p1?77:ca897?02kh01?7l:cf897ef28:j7p}<8783>7}:;>k1no5236f9`4=z{8nj6=4={<3``?e734;om7j>;|q1ag<72;q6?=>5609>6c4=99k0q~?m8;296~;6i=0o=63>b1855>{t:l81<7<t=3ae>a7<5;l?6;?4}r77>5<5s493=7j>;<1;6?db3ty8:o4?:3y>73e=l816?;j5609~w7`72909w0=?5;42?84a?3;;m6s|39c94?4|5:9?6i?4=2:a>gd<uz8m57>52z?1`=<ej278<=4>0`9~w7c12909w0<k8;f2?84c13<:7p}<7983>7}:;?i1nn523619`4=z{83o6=4<{<3:b?b634;j=7;m;<3b6?3e3ty9484?:3y>60`=>816>585c09~w4d22909w0?6b;f2?87fi3<:7p}=9183>7}::1>1ni5233;9`4=z{:336=4={<167?b6349257lm;|q1e`<72;q6>4l5d09>6<`=>81v\7f>7l:181\7f852j3n:70=6d;`a?xu41;0;6?u23569`4=:;091no5rs2;5>5<5s49?j7j>;<1:3?de3ty9jo4?:5y>6a>=jm16>i;5bc9>754=99k01?j9:c`8yv5>i3:1>v3<568g5>;41k0in6s|38g94?4|5:?n6i?4=2;e>gd<uz8j57>52z?1fg<192795?4k1:\7fp14<72;q6?5<5bc9>7=3=l81v\7f?98:181\7f84203<:70<88;f2?xu50>0;6?u2273924=:;9h1h<5rs3:;>5<5s48=>78>;<13a?b63ty:n<4?:2y>5g7=l816=l:5c19>5d3=98h0q~<79;296~;5>:0==63<108g5>{t:h=1<7<t=3`:>37<5;3?6i?4}r0;e?6=:r79:9491:?051<c92wx?=j50;1x966a2m;01>?=:4`896762<h0q~=>3;297~;49>0>n63<148g5>;4910>n6s|29`94?4|5:;<6i?4=346>37<uz>n6=4={<147?dd349<87j>;|q053<72;q6>;85609>74>=l81v\7f?6l:181\7f840k3ho70=>d;f2?xu5?;0;6?u230`9g4=:;8k1=<l4}r0;`?6=:r79;h4md:?065<c92wx9;4?:3y>73`=jj16?:>5d09~w0>=838p1>8i:cg8960b2m;0q~;8:181\7f851n3ho70=81;f2?xu213:1>v3<818g5>;4?m0in6s|21394?4|58l?6n>4=322>a7<uz;3o7>52z?23c<d827:4n4k1:\7fp0f<72;q6?:j5bd9>72e=l81v\7f9l50;0x961c2kn01>9i:e38yv3f2909w0=8e;f2?850l3hh7p}:5;296~;4>o0in63<3`8g5>{t=:0;6?u23969`4=:;181ni5rs5d94?4|5:=86oj4=256>a7<uz;jh7>53z?2=c<69k16=4k5c19>5db=l81v\7f<;i:180\7f87293;:n63>518`4>;6=o0o=6s|1e:94?5|58ii6n>4=0a`>47e34;o47j>;|q2`5<72:q6=n>510`894da2j:01<j?:e38yv7c:3:1?v3>c2825g=:9j81o=521e09`4=z{8n?6=4<{<3`2?76j27:o84l0:?2`1<c92wx=i850;1x94e?2j:01<m6:03a?87c>3n:7p}>8`83>6}:9>n1o=5216g954d<582j6i?4}r3;6?6=;r7:;?4>1c9>527=k916=5<5d09~w4>32908w0?85;32f>;6?=0h<63>858g5>{t91<1<7=t=05;>47e34;<;7m?;<3;2?b63ty:454?:2y>52g=k916=:l510`894>?2m;0q~?if;297~;6n;0h<63>f2825g=:9ol1h<5rs0d4>5<4s4;n;7?>b:?2a3<d827:j:4k1:\7fp5c?=839p1<kn:03a?87b13i;70?i9;f2?xu6nk0;6>u21df954d<58oh6n>4=0da>a7<uz;mh7>53z?2ac<d827:j=4>1c9>5cb=l81v\7f<;k:180\7f873l3i;70?;e;32f>;6=m0o=6s|14`94?5|58>j6n>4=06a>47e34;>n7j>;|q226<72:q6=89510`894312j:01<8<:e38yv7193:1?v3>55825g=:9<91o=521739`4=z{ji1<7=t=21:>47e349847m?;<10f?e63ty85:4?:2y>75e=98h01>>m:b2896?02j;0q~=69;297~;48o0:=o5231g9g5=:;031o<5rs2;a>5<4s49:>7?>b:?054<d82785o4l1:\7fp7<b=839p1>?::03a?856<3i;70=6d;a2?xu41o0;6>u23059g5=:;821=<l4=2;e>f7<uz93n7>53z?05`<69k16?<j5c19>7=d=k81v\7f>6k:180\7f85593;:n63<218`4>;40m0h=6s|39d94?5|5:8?6<?m;<117?e73493j7m>;|q0=4<72:q6??9510`896412j:01>7>:b38yv5>;3:1?v3<288`4>;4:h0:=o523819g4=z{8ki6=4<{<3:f?e734;2o7?>b:?2eg<c92wx=l750;1x94??2j:01<76:03a?87f13n:7p}>ag83>6}:9h;1o=521`0954d<58km6i?4}|`272<7280;6=u+10d9f<=O9;80D<=9;n`;>5<<uz9h=7>52z\0g4=:9;:1hi5rs2`g>5<5sW9ih63>218g=>{t;m81<7<t^2f1?87583on7p}<f883>7}Y;o301<<?:034?xu4k;0;6?uQ3b0894472mo0q~?<f;296~X6;o16=?>5459~w6`e2909wS=ib:?265<69h1v\7f>hj:181\7f[5am27:>=4>299~w6b32909wS=k4:?265<a82wx>8;50;0xZ73234;9<7oj;|q0g1<72;qU?n:4=003>`6<uz>;57>52z\74<=:9;:1=>=4}r1eg?6=:rT8jn521329577<uz;8i7>52z\27`=:9;:18>5rs2ge>5<5sW9nj63>21824a=z{:io6=4={_1``>;6:90n56s|3c`94?4|V:hi70?=0;f1?xu4jl0;6?uQ3cg894472mk0q~=k6;296~X4l?16=?>5f39~w6`c2909wS=id:?265<6::1v\7f>o>:181\7f[5f927:>=4m7:\7fp7ge=838pR>ll;<314?b?3ty8oh4?:3y]7fc<588;6ho4}r1eb?6=:rT8jk52132957?<uz9o97>52z\0`0=:9;:1j<5rs2ae>5<5sW9hj63>218ff>{t;m:1<7<t^2f3?87583oh7p}<d683>7}Y;m=01<<?:g18yv5en3:1>vP<bg9>576=lk1v\7f>j7:181\7f[5c027:>=4i4:\7fp7f6=838pR>m?;<314?bd3ty9<54?:2y]65g<V;:370?<7;`;?xu4l80;6?uQ3e3894472ln0q~:?8;296~X38116=?>51208yv27>3:1>vP;079>576=9::0q~:?5;296~X38<16=?>513d8yv27<3:1>vP;059>576=9;o0q~:?3;296~X38:16=?>513f8yv27:3:1>vP;039>576=9;i0q~:?1;296~X38816=?>513`8yv2783:1>vP;019>576=9;k0q~<:4;296~X5==16=?>59`9~w7352909wS<:2:?265<>02wx>8?50;0xZ73634;9<778;|q115<72;qU>8>4=003><0<uz8?j7>52z\10c=:9;:1585rs36f>5<5sW8?i63>218:0>{t:=n1<7<t^36g?87583387p}=4b83>7}Y:=i01<<?:808yv5a03:1>vP<f99>576=98<0q~=i6;296~X4n?16=?>51068yv5a=3:1>vP<f49>576=9890q~=i4;296~X4n=16=?>51008yv5a;3:1>vP<f29>576=98;0q~=i2;296~X4n;16=?>51028yv5a93:1>vP<f09>576=99l0q~=i0;296~X4n916=?>511g8yv5dk3:1>vP<cb9>576=m11v\7f>mn:181\7f[5di27:>=4j6:\7fp7f?=838pR>m6;<314?c23ty8o54?:3y]7f><588;6h:4}r1`3?6=:rT8o:521329a6=z{:i=6=4={_1`2>;6:90n>6s|3b794?4|V:i>70?=0;g2?xu5<k0;6?uQ25`894472>l0q~<;9;296~X5<016=?>57e9~w72?2909wS<;8:?265<0k2wx>9950;0xZ72034;9<79m;|q103<72;qU>984=003>2g<uz8?97>52z\100=:9;:1;45rs367>5<5sW8?863>2184<>{t:=91<7<t^360?87583=<7p}<ee83>7}Y;ln01<<?:02:?xu4mk0;6?uQ3d`8944728:<7p}<e`83>7}Y;lk01<<?:025?xu4m00;6?uQ3d;8944728:>7p}<e983>7}Y;l201<<?:027?xu4m>0;6?uQ3d58944728:87p}<e783>7}Y;l<01<<?:021?xu4m<0;6?uQ3d78944728::7p}<e283>7}Y;l901<<?:gd8yv5b:3:1>vP<e39>576=nl1v\7f>k>:181\7f[5b927:>=4id:\7fp7`6=838pR>k?;<314?`d3ty8hk4?:3y]7a`<588;6kl4}r1ga?6=:rT8hh521329bd=z{:no6=4={_1g`>;6:90m56s|3e`94?4|V:ni70?=0;d4?xu4lh0;6?uQ3ec894472o<0q~=k9;296~X4l016=?>5f49~yk>b<3:1=vF>239~j=c2290:wE?=2:\7fm<`0=83;pD<<=;|l;a2<72;qC=?<4}o:f<?6=9rB:>?5rn9d2>5<>sA;9>6sa8dc94?4|@8897p`7eb83>4}O9;80qc6jd;296~N6:;1vb5kj:182\7fM75:2we4hh50;0xL4453td3j?4?:3yK574<ug2m?7>51zJ267=zf1l>6=4>{I316>{i0o<1<7?tH001?xh?n10;6?uG1308yk>ai3:1=vF>239~j=`e2909wE?=2:\7fm<cb=83;pD<<=;|l;b`<728qC=?<4}o:eb?6=9rB:>?5rn823>5<6sA;9>6sa91394?7|@8897p`60383>4}O9;80qc7?3;295~N6:;1vb4>;:182\7fM75:2we5=;50;0xL4453td2<;4?:3yK574<ug3;;7>52zJ267=zf0:36=4={I316>{i1931<7<tH001?xh>8h0;6?uG1308yk?7j3:1>vF>239~j<6d2909wE?=2:\7fm=5b=838pD<<=;|l:4`<72;qC=?<4}o;3b?6=:rB:>?5rn833>5<5sA;9>6sa90394?4|@8897p`61383>7}O9;80qc7>3;296~N6:;1vb4?;:181\7fM75:2we5<;50;0xL4453td2=;4?:3yK574<ug3:;7>52zJ267=zf0;36=4={I316>{i1831<7<tH001?xh>9h0;6?uG1308yk?6j3:1>vF>239~j<7d2909wE?=2:\7fm=4b=83;pD<<=;|l:5`<728qC=?<4}o;2b?6=9rB:>?5rn803>5<6sA;9>6sa93394?7|@8897p`62383>4}O9;80qc7=3;295~N6:;1vb4<;:181\7fM75:2we5?;50;0xL4453td2>;4?:3yK574<ug39;7>52zJ267=zf0836=4={I316>{i1;31<7<tH001?xh>:h0;6?uG1308yk?5j3:1>vF>239~j<4d290:wE?=2:\7fm=7b=83;pD<<=;|l:6`<728qC=?<4}o;1b?6=9rB:>?5rn813>5<6sA;9>6sa92394?7|@8897p`63383>4}O9;80qc7<3;295~N6:;1vb4=;:182\7fM75:2we5>;50;3xL4453td2?;4?:0yK574<ug38;7>51zJ267=zf0936=4>{I316>{i1:31<7?tH001?xh>;h0;6<uG1308yk?4j3:1=vF>239~j<5d290:wE?=2:\7fm=6b=83;pD<<=;|l432<728qC=?<4}o54f?6=9rB:>?5rn65`>5<6sA;9>6sa76f94?7|@8897p`87d83>4}O9;80qc98f;295~N6:;1vb:6?:182\7fM75:2Bo<6sa79394?7|@8897p`88283>4}O9;80qc974;295~N6:;1vb:6::182\7fM75:2we;5850;3xL4453td<4:4?:0yK574<ug=347>51zJ267=zf>2j6=4>{I316>{i?1h1<7?tH001?xh00m0;6<uG1308La6<ug=3i7>51zJ267=zf>3;6=4>{I316>{i?0;1<7?tH001?Mb73td<5?4?:0yK574<ug=2?7>51zJ267=zf>3>6=4>{I316>Nc82we;4950;3xL4453td<544?:0yK574<ug=2m7>51zJ267=zf>3m6=4>{I316>{i?h:1<7?tH001?xh0i80;6<uG1308yk1f:3:1=vF>239~j2g4290:wE?=2:\7fm3d2=83;pD<<=;If3?xh0i<0;6<uG1308yk1f>3:1=vF>239K`5=zf>ki6=4>{I316>{i?ho1<7?tH001?xh0j90;6<uG1308yk1e93:1=vF>239~j2d5290:wE?=2:Jg4>{i?k91<7?tH001?xh0j=0;6<uG1308yk1e=3:1=vF>239~j2d0290:wE?=2:Jg4>{i?kh1<7?tH001?xh0jj0;6<uG1308yk1el3:1=vF>239~j2da290:wE?=2:\7fm3f4=83;pD<<=;|l4g6<728qC=?<4}o5`2?6=9rB:>?5Gd19~j2e?290:wE?=2:\7fm3fg=83;pD<<=;|l4gg<728qC=?<4}o5`g?6=9rB:>?5rn6ag>5<6sA;9>6sa7bg94?7|@8897p`8cg83>4}O9;80qc9k0;295~N6:;1vb:j>:182\7fM75:2Bo<6sa7e094?7|@8897p`8d283>4}O9;80qc9k4;295~N6:;1vb:j::182\7fM75:2we;i850;3xL4453td<h:4?:0yK574<ug=o47>51zJ267=zf>n26=4>{I316>{i?mk1<7?tH001?xh0lk0;6<uG1308yk1ck3:1=vF>239~j2bc290:wE?=2:\7fm3ac=83;pD<<=;|l4`c<728qC=?<4}o5f4?6=9rB:>?5rn6g2>5<6sA;9>6sa7d094?7|@8897p`8e283>4}O9;80qc9j4;295~N6:;1vb:k::182\7fM75:2we;h850;3xL4453td<i:4?:0yK574<ug=n47>51zJ267=zf>o26=4>{I316>{i?lk1<7?tH001?xh0mk0;6<uG1308yk1bk3:1=vF>239~j2cc290:wE?=2:\7fm3`c=83;pD<<=;|l4ac<728qC=?<4}o5e4?6=9rB:>?5rn6d2>5<6sA;9>6sa7g094?7|@8897p`8f283>4}O9;80qc9i4;295~N6:;1vb:h::182\7fM75:2we;k850;3xL4453td<j:4?:0yK574<ug=m47>51zJ267=Ol91vb:h6:182\7fM75:2we;ko50;3xL4453td<jo4?:0yK574<ug=mo7>51zJ267=zf>lo6=4>{I316>{i?oo1<7?tH001?xh0no0;6<uG1308yk>783:1=vF>239~j=66290:wE?=2:\7fm<54=83;pD<<=;|l;46<728qC=?<4}o:30?6=9rB:>?5rn926>5<6sA;9>6sa81494?7|@8897p`70683>4}O9;80qc6?8;295~N6:;1vb5>6:182\7fM75:2we4=o50;3xL4453td3<o4?:0yK574<ug2;o7>51zJ267=zf1:o6=4>{I316>{i09o1<7?tH001?xh?8o0;6<uG1308yk>683:1=vF>239~j=76290:wE?=2:\7fm<44=83;pD<<=;|l;56<728qC=?<4}o:20?6=9rB:>?5rn936>5<6sA;9>6sa80494?7|@8897p`71683>4}O9;80qc6>8;295~N6:;1vb5?6:182\7fM75:2we4<o50;3xL4453td3=o4?:0yK574<ug2:o7>51zJ267=zf1;o6=4>{I316>{i08o1<7?tH001?xh?9o0;6<uG1308yk>583:1=vF>239~j=46290:wE?=2:\7fm<74=83;pD<<=;|l;66<728qC=?<4}o:10?6=9rB:>?5rn906>5<6sA;9>6Fk0:\7fm<70=83;pD<<=;If3?xh?:>0;6<uG1308yk>483:1=vF>239K`5=zf19:6=4>{I316>{i0:81<7?tH001?xh?;:0;6<uG1308yk>4<3:1=vF>239~j=52290:wE?=2:\7fm<60=83;pD<<=;|l;72<728qC=?<4}o:0<?6=9rB:>?5rn91:>5<6sA;9>6sa82c94?7|@8897p`73c83>4}O9;80qc6<c;295~N6:;1vb5=k:182\7fM75:2we4>k50;3xL4453td3?k4?:0yK574<ug2?<7>51zJ267=zf1>:6=4>{I316>{i0=81<7?tH001?xh?<:0;6<uG1308yk>3<3:1=vF>239~j=22290:wE?=2:\7fm<10=83;pD<<=;|l;02<728qC=?<4}o:7<?6=9rB:>?5rn96:>5<6sA;9>6sa85c94?7|@8897p`74c83>4}O9;80qc6;c;295~N6:;1vb5:k:182\7fM75:2we49k50;3xL4453td38k4?:0yK574<ug2><7>51zJ267=zf1?:6=4>{I316>{i0<81<7?tH001?xh?=:0;6<uG1308yk>2<3:1=vF>239~j=32290:wE?=2:\7fm<00=83;pD<<=;|l;12<728qC=?<4}o:6<?6=9rB:>?5rn97:>5<6sA;9>6sa84c94?7|@8897p`75c83>4}O9;80qc6:c;295~N6:;1vb5;k:182\7fM75:2we48k50;3xL4453td39k4?:0yK574<ug2=<7>51zJ267=zf1<:6=4>{I316>{i0?81<7?tH001?xh?>:0;6<uG1308yk>1<3:1=vF>239~j=02290:wE?=2:\7fm<30=83;pD<<=;|l;22<728qC=?<4}o:5<?6=9rB:>?5rn94:>5<6sA;9>6sa87c94?7|@8897p`76c83>4}O9;80qc69c;295~N6:;1vb58k:182\7fM75:2we4;k50;3xL4453td3:k4?:0yK574<ug2<<7>51zJ267=zf1=:6=4>{I316>{i0>81<7?tH001?xh??:0;6<uG1308yk>0<3:1=vF>239~j=12290:wE?=2:\7fm<20=83;pD<<=;|l;32<728qC=?<4}o:4<?6=9rB:>?5rn95:>5<6sA;9>6sa86c94?7|@8897p`77c83>4}O9;80qc68c;295~N6:;1vb59k:182\7fM75:2we4:k50;3xL4453td3;k4?:0yK574<ug23<7>51zJ267=zf12:6=4>{I316>{i0181<7?tH001?Mb73td34>4?:0yK574<ug2387>51zJ267=Ol91vb56::182\7fM75:2we45850;3xL4453td34:4?:0yK574<ug2347>51zJ267=zf1226=4>{I316>{i01k1<7?tH001?xh?0k0;6<uG1308yk>?k3:1=vF>239K`5=zf12o6=4>{I316>{i01o1<7?tH001?xh?0o0;6<uG1308yk>>83:1=vF>239~j=?6290:wE?=2:Jg4>{i0081<7?tH001?xh?1:0;6<uG1308yk>><3:1=vF>239~j=?2290:wE?=2:\7fm<<0=83;pD<<=;|l;=2<728qC=?<4}o::<?6=9rB:>?5rn9;:>5<6sA;9>6sa88c94?7|@8897p`79c83>4}O9;80qc66c;295~N6:;1vb57k:182\7fM75:2we44k50;3xL4453td35k4?:0yK574<ug2j<7>51zJ267=zf1k:6=4>{I316>{i0h81<7?tH001?xh?i:0;6<uG1308yk>f<3:1=vF>239~j=g2290:wE?=2:\7fm<d0=83;pD<<=;|l;e2<728qC=?<4}o:b<?6=9rB:>?5rn9c:>5<6sA;9>6sa8`c94?7|@8897p`7ac83>4}O9;80qc6nc;295~N6:;1vb5ok:182\7fM75:2we4lk50;3xL4453td3mk4?:0yK574<ug2i<7>51zJ267=zf1h:6=4>{I316>{i0k81<7?tH001?xh?j:0;6<uG1308yk>e<3:1=vF>239~j=d2290:wE?=2:\7fm<g0=83;pD<<=;|l;f2<728qC=?<4}o:a<?6=9rB:>?5rn9`:>5<6sA;9>6sa8cc94?7|@8897p`7bc83>4}O9;80qc6mc;295~N6:;1vb5lk:182\7fM75:2we4ok50;3xL4453td3nk4?:0yK574<ug2h<7>51zJ267=zf1i:6=4>{I316>{i0j81<7?tH001?xh?k:0;6<uG1308yk>d<3:1=vF>239~j=e2290:wE?=2:\7fm<f0=83;pD<<=;|l;g2<728qC=?<4}o:`<?6=9rB:>?5rn9a:>5<6sA;9>6sa8bc94?7|@8897p`7cc83>4}O9;80qc6lc;295~N6:;1vb5mk:182\7fM75:2we4nk50;3xL4453td3ok4?:0yK574<ug2o<7>51zJ267=zf1n:6=4>{I316>{i0m81<7?tH001?xh?l:0;6<uG1308yk>c<3:1=vF>239~j=b2290:wE?=2:\7fm<a0=83;pD<<=;|l;`2<728qC=?<4}o:g<?6=9rB:>?5rn9f:>5<6sA;9>6sa8ec94?7|@8897p`7dc83>4}O9;80qc6kc;295~N6:;1vb5jk:182\7fM75:2we4ik50;3xL4453td3hk4?:0yK574<ug2n<7>51zJ267=zf1o:6=4>{I316>{zutJKOvok4;44<3gaj<wKLOu?}ABS\7fxFG
\ No newline at end of file
diff --git a/bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base b/bee2-selectmap/.svn/text-base/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn.svn-base
new file mode 100644 (file)
index 0000000..4c68cbb
--- /dev/null
@@ -0,0 +1,576 @@
+(edif test (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0))
+(status (written (timeStamp 2006 2 18 19 6 6)
+   (author "Xilinx, Inc.")
+   (program "Xilinx CORE Generator" (version "Xilinx CORE Generator 7.1.04i; Cores Update # 3"))))
+   (comment "                                                                                
+      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-2005 Xilinx, Inc.                                      
+      All rights reserved.                                                      
+                                                                                
+   ")
+   (comment "Core parameters: ")
+       (comment "c_reg_inputsb = 0 ")
+       (comment "c_reg_inputsa = 0 ")
+       (comment "c_has_ndb = 0 ")
+       (comment "c_has_nda = 0 ")
+       (comment "c_ytop_addr = 1024 ")
+       (comment "c_has_rfdb = 0 ")
+       (comment "c_has_rfda = 0 ")
+       (comment "c_ywea_is_high = 1 ")
+       (comment "c_yena_is_high = 1 ")
+       (comment "InstanceName = async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst ")
+       (comment "c_yhierarchy = hierarchy1 ")
+       (comment "c_yclka_is_rising = 1 ")
+       (comment "c_family = virtex2p ")
+       (comment "c_ysinita_is_high = 1 ")
+       (comment "c_ybottom_addr = 0 ")
+       (comment "c_width_b = 8 ")
+       (comment "c_width_a = 8 ")
+       (comment "c_sinita_value = 0000 ")
+       (comment "c_sinitb_value = 00 ")
+       (comment "c_limit_data_pitch = 18 ")
+       (comment "c_write_modeb = 0 ")
+       (comment "c_write_modea = 0 ")
+       (comment "c_has_rdyb = 0 ")
+       (comment "c_yuse_single_primitive = 0 ")
+       (comment "c_has_rdya = 0 ")
+       (comment "c_addra_width = 7 ")
+       (comment "c_addrb_width = 7 ")
+       (comment "c_has_limit_data_pitch = 0 ")
+       (comment "c_default_data = 0000 ")
+       (comment "c_pipe_stages_b = 0 ")
+       (comment "c_yweb_is_high = 1 ")
+       (comment "c_yenb_is_high = 1 ")
+       (comment "c_pipe_stages_a = 0 ")
+       (comment "c_yclkb_is_rising = 1 ")
+       (comment "c_yydisable_warnings = 1 ")
+       (comment "c_enable_rlocs = 0 ")
+       (comment "c_ysinitb_is_high = 1 ")
+       (comment "c_has_web = 0 ")
+       (comment "c_has_default_data = 1 ")
+       (comment "c_has_wea = 1 ")
+       (comment "c_has_sinitb = 1 ")
+       (comment "c_has_sinita = 1 ")
+       (comment "c_has_dinb = 0 ")
+       (comment "c_has_dina = 1 ")
+       (comment "c_ymake_bmm = 0 ")
+       (comment "c_has_enb = 1 ")
+       (comment "c_has_ena = 0 ")
+       (comment "c_mem_init_file = mif_file_16_1 ")
+       (comment "c_depth_b = 128 ")
+       (comment "c_depth_a = 128 ")
+       (comment "c_has_doutb = 1 ")
+       (comment "c_has_douta = 0 ")
+       (comment "c_yprimitive_type = 4kx4 ")
+   (external xilinxun (edifLevel 0)
+      (technology (numberDefinition))
+       (cell VCC (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port P (direction OUTPUT))
+               )
+           )
+       )
+       (cell GND (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port G (direction OUTPUT))
+               )
+           )
+       )
+       (cell RAMB16_S9_S9 (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port WEA (direction INPUT))
+                   (port ENA (direction INPUT))
+                   (port SSRA (direction INPUT))
+                   (port CLKA (direction INPUT))
+                   (port (rename DIA_0_ "DIA<0>") (direction INPUT))
+                   (port (rename DIA_1_ "DIA<1>") (direction INPUT))
+                   (port (rename DIA_2_ "DIA<2>") (direction INPUT))
+                   (port (rename DIA_3_ "DIA<3>") (direction INPUT))
+                   (port (rename DIA_4_ "DIA<4>") (direction INPUT))
+                   (port (rename DIA_5_ "DIA<5>") (direction INPUT))
+                   (port (rename DIA_6_ "DIA<6>") (direction INPUT))
+                   (port (rename DIA_7_ "DIA<7>") (direction INPUT))
+                   (port (rename DOA_0_ "DOA<0>") (direction OUTPUT))
+                   (port (rename DOA_1_ "DOA<1>") (direction OUTPUT))
+                   (port (rename DOA_2_ "DOA<2>") (direction OUTPUT))
+                   (port (rename DOA_3_ "DOA<3>") (direction OUTPUT))
+                   (port (rename DOA_4_ "DOA<4>") (direction OUTPUT))
+                   (port (rename DOA_5_ "DOA<5>") (direction OUTPUT))
+                   (port (rename DOA_6_ "DOA<6>") (direction OUTPUT))
+                   (port (rename DOA_7_ "DOA<7>") (direction OUTPUT))
+                   (port (rename ADDRA_0_ "ADDRA<0>") (direction INPUT))
+                   (port (rename ADDRA_1_ "ADDRA<1>") (direction INPUT))
+                   (port (rename ADDRA_2_ "ADDRA<2>") (direction INPUT))
+                   (port (rename ADDRA_3_ "ADDRA<3>") (direction INPUT))
+                   (port (rename ADDRA_4_ "ADDRA<4>") (direction INPUT))
+                   (port (rename ADDRA_5_ "ADDRA<5>") (direction INPUT))
+                   (port (rename ADDRA_6_ "ADDRA<6>") (direction INPUT))
+                   (port (rename ADDRA_7_ "ADDRA<7>") (direction INPUT))
+                   (port (rename ADDRA_8_ "ADDRA<8>") (direction INPUT))
+                   (port (rename ADDRA_9_ "ADDRA<9>") (direction INPUT))
+                   (port (rename ADDRA_10_ "ADDRA<10>") (direction INPUT))
+                   (port (rename DIPA_0_ "DIPA<0>") (direction INPUT))
+                   (port (rename DOPA_0_ "DOPA<0>") (direction OUTPUT))
+                   (port WEB (direction INPUT))
+                   (port ENB (direction INPUT))
+                   (port SSRB (direction INPUT))
+                   (port CLKB (direction INPUT))
+                   (port (rename DIB_0_ "DIB<0>") (direction INPUT))
+                   (port (rename DIB_1_ "DIB<1>") (direction INPUT))
+                   (port (rename DIB_2_ "DIB<2>") (direction INPUT))
+                   (port (rename DIB_3_ "DIB<3>") (direction INPUT))
+                   (port (rename DIB_4_ "DIB<4>") (direction INPUT))
+                   (port (rename DIB_5_ "DIB<5>") (direction INPUT))
+                   (port (rename DIB_6_ "DIB<6>") (direction INPUT))
+                   (port (rename DIB_7_ "DIB<7>") (direction INPUT))
+                   (port (rename DOB_0_ "DOB<0>") (direction OUTPUT))
+                   (port (rename DOB_1_ "DOB<1>") (direction OUTPUT))
+                   (port (rename DOB_2_ "DOB<2>") (direction OUTPUT))
+                   (port (rename DOB_3_ "DOB<3>") (direction OUTPUT))
+                   (port (rename DOB_4_ "DOB<4>") (direction OUTPUT))
+                   (port (rename DOB_5_ "DOB<5>") (direction OUTPUT))
+                   (port (rename DOB_6_ "DOB<6>") (direction OUTPUT))
+                   (port (rename DOB_7_ "DOB<7>") (direction OUTPUT))
+                   (port (rename ADDRB_0_ "ADDRB<0>") (direction INPUT))
+                   (port (rename ADDRB_1_ "ADDRB<1>") (direction INPUT))
+                   (port (rename ADDRB_2_ "ADDRB<2>") (direction INPUT))
+                   (port (rename ADDRB_3_ "ADDRB<3>") (direction INPUT))
+                   (port (rename ADDRB_4_ "ADDRB<4>") (direction INPUT))
+                   (port (rename ADDRB_5_ "ADDRB<5>") (direction INPUT))
+                   (port (rename ADDRB_6_ "ADDRB<6>") (direction INPUT))
+                   (port (rename ADDRB_7_ "ADDRB<7>") (direction INPUT))
+                   (port (rename ADDRB_8_ "ADDRB<8>") (direction INPUT))
+                   (port (rename ADDRB_9_ "ADDRB<9>") (direction INPUT))
+                   (port (rename ADDRB_10_ "ADDRB<10>") (direction INPUT))
+                   (port (rename DIPB_0_ "DIPB<0>") (direction INPUT))
+                   (port (rename DOPB_0_ "DOPB<0>") (direction OUTPUT))
+               )
+           )
+       )
+   )
+(library test_lib (edifLevel 0) (technology (numberDefinition (scale 1 (E 1 -12) (unit Time))))
+(cell async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst
+ (cellType GENERIC) (view view_1 (viewType NETLIST)
+  (interface
+   (port ( rename dina_7_ "dina<7>") (direction INPUT))
+   (port ( rename dina_6_ "dina<6>") (direction INPUT))
+   (port ( rename dina_5_ "dina<5>") (direction INPUT))
+   (port ( rename dina_4_ "dina<4>") (direction INPUT))
+   (port ( rename dina_3_ "dina<3>") (direction INPUT))
+   (port ( rename dina_2_ "dina<2>") (direction INPUT))
+   (port ( rename dina_1_ "dina<1>") (direction INPUT))
+   (port ( rename dina_0_ "dina<0>") (direction INPUT))
+   (port ( rename dinb_7_ "dinb<7>") (direction INPUT))
+   (port ( rename dinb_6_ "dinb<6>") (direction INPUT))
+   (port ( rename dinb_5_ "dinb<5>") (direction INPUT))
+   (port ( rename dinb_4_ "dinb<4>") (direction INPUT))
+   (port ( rename dinb_3_ "dinb<3>") (direction INPUT))
+   (port ( rename dinb_2_ "dinb<2>") (direction INPUT))
+   (port ( rename dinb_1_ "dinb<1>") (direction INPUT))
+   (port ( rename dinb_0_ "dinb<0>") (direction INPUT))
+   (port ( rename ena "ena") (direction INPUT))
+   (port ( rename enb "enb") (direction INPUT))
+   (port ( rename wea "wea") (direction INPUT))
+   (port ( rename web "web") (direction INPUT))
+   (port ( rename sinita "sinita") (direction INPUT))
+   (port ( rename sinitb "sinitb") (direction INPUT))
+   (port ( rename nda "nda") (direction INPUT))
+   (port ( rename ndb "ndb") (direction INPUT))
+   (port ( rename clka "clka") (direction INPUT))
+   (port ( rename clkb "clkb") (direction INPUT))
+   (port ( rename addra_6_ "addra<6>") (direction INPUT))
+   (port ( rename addra_5_ "addra<5>") (direction INPUT))
+   (port ( rename addra_4_ "addra<4>") (direction INPUT))
+   (port ( rename addra_3_ "addra<3>") (direction INPUT))
+   (port ( rename addra_2_ "addra<2>") (direction INPUT))
+   (port ( rename addra_1_ "addra<1>") (direction INPUT))
+   (port ( rename addra_0_ "addra<0>") (direction INPUT))
+   (port ( rename addrb_6_ "addrb<6>") (direction INPUT))
+   (port ( rename addrb_5_ "addrb<5>") (direction INPUT))
+   (port ( rename addrb_4_ "addrb<4>") (direction INPUT))
+   (port ( rename addrb_3_ "addrb<3>") (direction INPUT))
+   (port ( rename addrb_2_ "addrb<2>") (direction INPUT))
+   (port ( rename addrb_1_ "addrb<1>") (direction INPUT))
+   (port ( rename addrb_0_ "addrb<0>") (direction INPUT))
+   (port ( rename rdya "rdya") (direction OUTPUT))
+   (port ( rename rdyb "rdyb") (direction OUTPUT))
+   (port ( rename rfda "rfda") (direction OUTPUT))
+   (port ( rename rfdb "rfdb") (direction OUTPUT))
+   (port ( rename douta_7_ "douta<7>") (direction OUTPUT))
+   (port ( rename douta_6_ "douta<6>") (direction OUTPUT))
+   (port ( rename douta_5_ "douta<5>") (direction OUTPUT))
+   (port ( rename douta_4_ "douta<4>") (direction OUTPUT))
+   (port ( rename douta_3_ "douta<3>") (direction OUTPUT))
+   (port ( rename douta_2_ "douta<2>") (direction OUTPUT))
+   (port ( rename douta_1_ "douta<1>") (direction OUTPUT))
+   (port ( rename douta_0_ "douta<0>") (direction OUTPUT))
+   (port ( rename doutb_7_ "doutb<7>") (direction OUTPUT))
+   (port ( rename doutb_6_ "doutb<6>") (direction OUTPUT))
+   (port ( rename doutb_5_ "doutb<5>") (direction OUTPUT))
+   (port ( rename doutb_4_ "doutb<4>") (direction OUTPUT))
+   (port ( rename doutb_3_ "doutb<3>") (direction OUTPUT))
+   (port ( rename doutb_2_ "doutb<2>") (direction OUTPUT))
+   (port ( rename doutb_1_ "doutb<1>") (direction OUTPUT))
+   (port ( rename doutb_0_ "doutb<0>") (direction OUTPUT))
+   )
+  (contents
+   (instance VCC (viewRef view_1 (cellRef VCC  (libraryRef xilinxun))))
+   (instance GND (viewRef view_1 (cellRef GND  (libraryRef xilinxun))))
+   (instance (rename async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8 "async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst/bm/mem/arch_v2/prim/3/b1/chk0/col/0/b2/mextd/arch_v2/c1/ram1/v2/d2048/by9/newSim8")
+      (viewRef view_1 (cellRef RAMB16_S9_S9 (libraryRef xilinxun)))
+      (property INIT_00 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_01 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_02 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_03 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_04 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_05 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_06 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_07 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_08 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_09 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_10 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_11 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_12 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_13 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_14 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_15 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_16 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_17 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_18 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_19 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_20 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_21 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_22 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_23 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_24 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_25 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_26 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_27 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_28 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_29 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_30 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_31 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_32 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_33 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_34 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_35 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_36 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_37 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_38 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_39 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_00 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_01 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_02 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_03 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_04 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_05 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_06 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_07 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property WRITE_MODE_A (string "WRITE_FIRST"))
+      (property INIT_A (string "000"))
+      (property SRVAL_A (string "000"))
+      (property WRITE_MODE_B (string "WRITE_FIRST"))
+      (property INIT_B (string "000"))
+      (property SRVAL_B (string "000"))
+   )
+   (net (rename N0 "Gnd")
+    (joined
+      (portRef G (instanceRef GND))
+      (portRef WEB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_8_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_9_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_10_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIPA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_8_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_9_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_10_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIPB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N1 "Vcc")
+    (joined
+      (portRef P (instanceRef VCC))
+      (portRef ENA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N2 "dina<7>")
+    (joined
+      (portRef dina_7_)
+      (portRef DIA_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N3 "dina<6>")
+    (joined
+      (portRef dina_6_)
+      (portRef DIA_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N4 "dina<5>")
+    (joined
+      (portRef dina_5_)
+      (portRef DIA_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N5 "dina<4>")
+    (joined
+      (portRef dina_4_)
+      (portRef DIA_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N6 "dina<3>")
+    (joined
+      (portRef dina_3_)
+      (portRef DIA_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N7 "dina<2>")
+    (joined
+      (portRef dina_2_)
+      (portRef DIA_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N8 "dina<1>")
+    (joined
+      (portRef dina_1_)
+      (portRef DIA_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N9 "dina<0>")
+    (joined
+      (portRef dina_0_)
+      (portRef DIA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N19 "enb")
+    (joined
+      (portRef enb)
+      (portRef ENB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N20 "wea")
+    (joined
+      (portRef wea)
+      (portRef WEA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N22 "sinita")
+    (joined
+      (portRef sinita)
+      (portRef SSRA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N23 "sinitb")
+    (joined
+      (portRef sinitb)
+      (portRef SSRB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N26 "clka")
+    (joined
+      (portRef clka)
+      (portRef CLKA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N27 "clkb")
+    (joined
+      (portRef clkb)
+      (portRef CLKB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N28 "addra<6>")
+    (joined
+      (portRef addra_6_)
+      (portRef ADDRA_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N29 "addra<5>")
+    (joined
+      (portRef addra_5_)
+      (portRef ADDRA_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N30 "addra<4>")
+    (joined
+      (portRef addra_4_)
+      (portRef ADDRA_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N31 "addra<3>")
+    (joined
+      (portRef addra_3_)
+      (portRef ADDRA_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N32 "addra<2>")
+    (joined
+      (portRef addra_2_)
+      (portRef ADDRA_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N33 "addra<1>")
+    (joined
+      (portRef addra_1_)
+      (portRef ADDRA_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N34 "addra<0>")
+    (joined
+      (portRef addra_0_)
+      (portRef ADDRA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N35 "addrb<6>")
+    (joined
+      (portRef addrb_6_)
+      (portRef ADDRB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N36 "addrb<5>")
+    (joined
+      (portRef addrb_5_)
+      (portRef ADDRB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N37 "addrb<4>")
+    (joined
+      (portRef addrb_4_)
+      (portRef ADDRB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N38 "addrb<3>")
+    (joined
+      (portRef addrb_3_)
+      (portRef ADDRB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N39 "addrb<2>")
+    (joined
+      (portRef addrb_2_)
+      (portRef ADDRB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N40 "addrb<1>")
+    (joined
+      (portRef addrb_1_)
+      (portRef ADDRB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N41 "addrb<0>")
+    (joined
+      (portRef addrb_0_)
+      (portRef ADDRB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N54 "doutb<7>")
+    (joined
+      (portRef doutb_7_)
+      (portRef DOB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N55 "doutb<6>")
+    (joined
+      (portRef doutb_6_)
+      (portRef DOB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N56 "doutb<5>")
+    (joined
+      (portRef doutb_5_)
+      (portRef DOB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N57 "doutb<4>")
+    (joined
+      (portRef doutb_4_)
+      (portRef DOB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N58 "doutb<3>")
+    (joined
+      (portRef doutb_3_)
+      (portRef DOB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N59 "doutb<2>")
+    (joined
+      (portRef doutb_2_)
+      (portRef DOB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N60 "doutb<1>")
+    (joined
+      (portRef doutb_1_)
+      (portRef DOB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N61 "doutb<0>")
+    (joined
+      (portRef doutb_0_)
+      (portRef DOB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+))))
+(design async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst (cellRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst (libraryRef test_lib))
+  (property X_CORE_INFO (string "null"))
+  (property PART (string "XC2VP20-6-ff896") (owner "Xilinx")))
+)
diff --git a/bee2-selectmap/.svn/text-base/main.ucf.svn-base b/bee2-selectmap/.svn/text-base/main.ucf.svn-base
new file mode 100644 (file)
index 0000000..59d4b9a
--- /dev/null
@@ -0,0 +1,33 @@
+######################################
+## System clock pins
+######################################
+
+NET User_Clk PERIOD=100MHz;
+
+NET Clkin_p            LOC = AP21 | IOSTANDARD = LVDS_25;
+NET Clkin_m            LOC = AN21 | IOSTANDARD = LVDS_25;
+
+######################################
+## SelectMAP interface pins
+######################################
+
+NET D_I<0>             LOC = AU9  | IOSTANDARD = LVCMOS25;
+NET D_I<1>             LOC = AV9  | IOSTANDARD = LVCMOS25;
+NET D_I<2>             LOC = AY9  | IOSTANDARD = LVCMOS25;
+NET D_I<3>             LOC = AW9  | IOSTANDARD = LVCMOS25;
+NET D_I<4>             LOC = AW34 | IOSTANDARD = LVCMOS25;
+NET D_I<5>             LOC = AY34 | IOSTANDARD = LVCMOS25;
+NET D_I<6>             LOC = AV34 | IOSTANDARD = LVCMOS25;
+NET D_I<7>             LOC = AU34 | IOSTANDARD = LVCMOS25;
+
+NET RDWR_B             LOC = AR34 | IOSTANDARD = LVCMOS25;
+NET CS_B               LOC = AT34 | IOSTANDARD = LVCMOS25;
+NET INIT_B             LOC = AR9  | IOSTANDARD = LVCMOS25;
+NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
+
+NET gpleds<1>                       LOC = AB6   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<2>                       LOC = AB7   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<3>                       LOC = AB9   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<4>                       LOC = AB10  | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<5>                       LOC = AD7   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<6>                       LOC = AF1   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
diff --git a/bee2-selectmap/.svn/text-base/main.ut.svn-base b/bee2-selectmap/.svn/text-base/main.ut.svn-base
new file mode 100644 (file)
index 0000000..8ea3a85
--- /dev/null
@@ -0,0 +1,37 @@
+-w
+-g DebugBitstream:No
+-g Binary:no
+-g CRC:Enable
+-g ConfigRate:4
+-g CclkPin:PullUp
+-g M0Pin:PullUp
+-g M1Pin:PullUp
+-g M2Pin:PullUp
+-g ProgPin:PullUp
+-g DonePin:PullUp
+-g PowerdownPin:PullUp
+-g TckPin:PullUp
+-g TdiPin:PullUp
+-g TdoPin:PullNone
+-g TmsPin:PullUp
+-g UnusedPin:PullDown
+-g UserID:0xFFFFFFFF
+-g DCMShutdown:Disable
+-g DisableBandgap:No
+-g DCIUpdateMode:AsRequired
+-g StartUpClk:CClk
+-g DONE_cycle:4
+-g GTS_cycle:5
+-g GWE_cycle:6
+-g LCK_cycle:NoWait
+-g Security:None
+-g DonePipe:No
+-g DriveDone:No
+-g Encrypt:No
+
+
+
+
+
+
+
diff --git a/bee2-selectmap/.svn/text-base/main.v.svn-base b/bee2-selectmap/.svn/text-base/main.v.svn-base
new file mode 100644 (file)
index 0000000..ff3930d
--- /dev/null
@@ -0,0 +1,429 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+
+   root my_root(User_Clk,
+                read_empty, read_enable, read_data,
+                write_full, write_enable, write_data);
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/.svn/text-base/main.xst.svn-base b/bee2-selectmap/.svn/text-base/main.xst.svn-base
new file mode 100644 (file)
index 0000000..f9a4f09
--- /dev/null
@@ -0,0 +1,4 @@
+set -tmpdir ./tmp
+set -xsthdpdir ./xst
+run
+-ifn main.prj -ifmt mixed -ofn main -ofmt NGC -p xc2vp70-6-ff1704 -top main -opt_mode Speed -opt_level 1 -iuc NO -lso main.lso -keep_hierarchy NO -rtlview Yes -glob_opt AllClockNets -read_cores YES -write_timing_constraints NO -cross_clock_analysis NO -hierarchy_separator / -bus_delimiter <> -case maintain -slice_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 -rom_style Auto -mux_extract NO -resource_sharing YES -mult_style auto -iobuf YES -max_fanout 500 -bufg 1 -register_duplication YES -register_balancing No -slice_packing No -optimize_primitives NO -tristate2logic Yes -use_clock_enable Yes -use_sync_set Yes -use_sync_reset Yes -iob auto -equivalent_register_removal YES -slice_utilization_ratio_maxmargin 5 
diff --git a/bee2-selectmap/.svn/text-base/main_counterexample_map0.v.svn-base b/bee2-selectmap/.svn/text-base/main_counterexample_map0.v.svn-base
new file mode 100644 (file)
index 0000000..7479ce1
--- /dev/null
@@ -0,0 +1,444 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds,
+   terminal
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+   reg read_enable_;
+   assign read_enable = read_enable_;
+   inout [33:0] terminal;
+   
+   always @(posedge User_Clk) begin
+     if (!read_enable && !read_empty) begin
+      read_enable_ <= 1;
+    end else begin
+      read_enable_  <= 0;
+    end
+   end
+   Maps_Bee2_Map0 map (.Clock(User_Clk),
+                       ._SW(1'b0),
+                       ._BTN(~read_enable_),
+                       .__TERMINAL_SynchronousLink_Pins(terminal));
+       
+//synthesis attribute LOC of terminal is "AT13,AR13,AV13,AU13,AW13,AY13,AL15,AL14,AV15,AU15,AY14,AY15,AM16,AL16,AP16,AN16,AR16,AT16,AV16,AU16,AL18,AL17,AM17,AN17,AR17,AP17,AU17,AT17,AW16,AW17,AN18,AM18,AT18,AR18"
+              
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/.svn/text-base/main_counterexample_map1.v.svn-base b/bee2-selectmap/.svn/text-base/main_counterexample_map1.v.svn-base
new file mode 100644 (file)
index 0000000..bc5a6ca
--- /dev/null
@@ -0,0 +1,437 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds,
+   terminal
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+   inout [33:0] terminal;
+   wire [7:0] write_data_;
+   assign write_data = write_data_ + 48;
+   
+   Maps_Bee2_Map1 map (.Clock(User_Clk),
+                       .SelectMapData(write_data_),
+                       .SelectMapWrite(write_enable),
+                       .__TERMINAL_SynchronousLink_Pins(terminal));
+       
+//synthesis attribute LOC of terminal is "C15,L16,M16,J16,K16,H16,G16,E16,F16,M18,M17,L17,K17,H17,J17,F17,G17,D16,D17,K18,L18,G18,H18,E17,E18,C18,C17,L19,M19,J19,K19,G19,H19,E19"
+              
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/.svn/text-base/makemaps.pl.svn-base b/bee2-selectmap/.svn/text-base/makemaps.pl.svn-base
new file mode 100644 (file)
index 0000000..03f9daa
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/perl
+
+`rm Map1.v`;
+`cp ../Map0.v .`;
+`cp ../main_map0.v main.v`;
+`make -f Makefile0`;
+`rm Map0.v`;
+`cp ../Map1.v .`;
+`cp ../main_map1.v main.v`;
+`make -f Makefile1`;
diff --git a/bee2-selectmap/.svn/text-base/remote_run.pl.svn-base b/bee2-selectmap/.svn/text-base/remote_run.pl.svn-base
new file mode 100644 (file)
index 0000000..b421f1f
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+
+$foo = 5;
+$f=0;
+while($f<$foo)
+{
+`echo "1234567890" > /dev/selectmap1`;
+`head -c11 /dev/selectmap2 >> transcript`;
+`echo '\n' >> transcript`;
+$f = $f+1;
+}
+
diff --git a/bee2-selectmap/.svn/text-base/root.v.svn-base b/bee2-selectmap/.svn/text-base/root.v.svn-base
new file mode 100644 (file)
index 0000000..6034216
--- /dev/null
@@ -0,0 +1,43 @@
+// megacz@cs.berkeley.edu,  public domain
+
+module root(clk,
+            read_empty, read_enable, read_data,
+            write_full, write_enable, write_data);
+
+  input clk;
+  input read_empty;
+  input write_full;
+  output read_enable;
+  output write_enable;
+  input  [7:0] read_data;
+  output [7:0] write_data;
+
+  reg read_enable_;
+  assign read_enable = read_enable_;
+  reg write_enable_;
+  assign write_enable = write_enable_;
+  reg [7:0] write_data_;
+  assign write_data = write_data_;
+
+  initial read_enable_ = 1;
+  initial write_enable_ = 0;
+
+  always @(posedge clk) begin
+
+    // if there's stuff to read and room to write, read a byte,
+    // increment it, and write it
+    if (!read_enable_ && !write_enable_ && !read_empty && !write_full) begin
+      read_enable_  <= 1;
+      write_enable_ <= 1;
+      write_data_   <= read_data + 1;
+
+    // else do nothing
+    end else begin
+      read_enable_  <= 0;
+      write_enable_ <= 0;
+
+    end
+
+  end
+
+endmodule
diff --git a/bee2-selectmap/Makefile b/bee2-selectmap/Makefile
new file mode 100644 (file)
index 0000000..a6e1717
--- /dev/null
@@ -0,0 +1,52 @@
+
+projectname = bee2-control-user-fifo
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = bee441.megacz.com
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = bee2-control-user-fifo.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+remote_run += echo "Gdkkn+vnqkc " > /dev/selectmap1;
+remote_run += head -c12 /dev/selectmap1; echo
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       rsync -zare ssh --progress --verbose build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare ssh --progress --delete --verbose ./ ${build_machine}:${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} synth XILINX=${build_machine_xilinx_path}'
+       scp ${build_machine}:${build_machine_work_dir}/main.bit build/fpga/$(bitfile)
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/Makefile_interchip0 b/bee2-selectmap/Makefile_interchip0
new file mode 100644 (file)
index 0000000..042c5a2
--- /dev/null
@@ -0,0 +1,50 @@
+
+projectname = working-bee2
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = map0.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} -f Makefile0 synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/Makefile_interchip1 b/bee2-selectmap/Makefile_interchip1
new file mode 100644 (file)
index 0000000..2d02793
--- /dev/null
@@ -0,0 +1,53 @@
+
+projectname = working-bee2
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = map1.bit
+
+remote_run  = user_unprogram 2;
+remote_run += user_program 2 $(bitfile);
+remote_run += ./remote_run.pl;
+remote_run += cat transcript;
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} -f Makefile1 synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+       scp remote_run.pl root@$(bee2_machine):
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/Makefile_userfpga b/bee2-selectmap/Makefile_userfpga
new file mode 100644 (file)
index 0000000..09dda50
--- /dev/null
@@ -0,0 +1,53 @@
+
+projectname = bee2-control-user-fifo
+
+build_machine = sting.eecs.berkeley.edu
+build_machine_xilinx_path = /opt/xilinx/ISE9.2i_lin/
+build_machine_work_dir = ~/$(projectname)
+bee2_machine = board4
+
+## you probably want to customize the stuff above this line
+
+## you probably don't want to change anything below this line
+
+xilinx =  cd $(build_machine_work_dir);
+xilinx += LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(XILINX)/bin/lin
+xilinx += XILINX=$(XILINX)
+xilinx += PATH=$$PATH:$(XILINX)/bin/lin
+xilinx += $(XILINX)/bin/lin/
+
+bitfile = bee2-control-user-fifo.bit
+
+remote_run  = user_unprogram 1;
+remote_run += user_program 1 $(bitfile);
+remote_run += ./remote_run.pl;
+remote_run += cat transcript;
+
+verilog_files = $(find . -name \*.v)
+
+run: upload build/fpga/$(bitfile)
+       ssh root@$(bee2_machine) '$(remote_run)'
+
+upload: build/fpga/$(bitfile)
+       scp build/fpga/$(bitfile) root@$(bee2_machine):
+
+build/fpga/$(bitfile): $(verilog_files)
+       mkdir -p build/fpga/
+       rsync -zare --progress --delete --verbose ./ ${build_machine_work_dir}
+       time ssh ${build_machine} 'make -C ${build_machine_work_dir} synth XILINX=${build_machine_xilinx_path}'
+       cp main.bit build/fpga/$(bitfile)
+       scp remote_run.pl root@$(bee2_machine):
+
+synth:
+       mkdir -p build/fpga/
+       echo work > main.lso
+       for A in *.v; do echo verilog work \""$$A"\"; done > main.prj
+       mkdir -p tmp
+       mkdir -p xst
+       rm -rf build/fpga/_ngo
+       $(xilinx)xst -intstyle xflow -ifn main.xst -ofn main.syr < main.xst
+       $(xilinx)ngdbuild -intstyle xflow -dd _ngo -nt timestamp -uc main.ucf -p xc2vp70-ff1704-6 main.ngc main.ngd
+       $(xilinx)map -intstyle xflow -p xc2vp70-ff1704-6 -cm speed -l -pr b -k 4 -c 100 -tx off -o main_map.ncd main.ngd main.pcf
+       $(xilinx)par -w -intstyle xflow -pl std -ol std -t 99 main_map.ncd main.ncd main.pcf
+       $(xilinx)bitgen -intstyle xflow -d -f main.ut main.ncd
+#      $(xilinx)trce -intstyle xflow -e 3 -l 3 -s 6 -xml main main.ncd -o main.twr main.pcf
diff --git a/bee2-selectmap/README.txt b/bee2-selectmap/README.txt
new file mode 100644 (file)
index 0000000..9d081a5
--- /dev/null
@@ -0,0 +1,67 @@
+Author: Tracy Wang
+
+Everything in this folder is the framework that I used to test the interchip on the Bee2. 
+
+Here's a short list of important files and their description.
+
+============
+main.v
+
+This is the *generic* top level verilog file which hooks up the selectmap FIFOs (async_fifo_* files). Then it hooks the FIFOs to the testing file, in this case in root.v. Actual test resides in root.v. 
+
+============
+main_counterexample_map0
+
+This is the main file which hooks up the counterexample Map0. So it hooks up the selectmap to BTN and SW. It also connects the interchip terminal to the right pins on Bee2.
+
+============
+main_counterexample_map1
+
+This is the main file which hooks up the counterexample Map1. It connects the counter outputs to the selectmap FIFO. 
+
+============
+
+Makefile_userfpga
+
+This is the *generic* makefile which can be invoked from the control fpga to program the testing harness automatically onto one of the user fpgas. However, it will prompt for password in several locations, which I wasn't able to bypass.
+
+===========
+
+makemaps.pl
+
+This is the perl file which I used to invoke Makefile_interchip0 and Makefile interchip1 to build the two interchip maps. This file requires customization of the Makefile file names.
+Both Makefile_interchip0 and Makefile_interchip1 will program the bit files onto the boards. Makefile_interchip1 will actually run a remote_run.pl file after everything is programmed to automatically test the unit and retrieve the results.
+
+===========
+
+How to use selectmap
+
+To input characters into selectmap:
+
+echo "<characters here>" > /dev/selectmap[1-4];
+
+To read from selectmap
+
+head -c<number of characters> /dev/selectmap[1-4];
+
+i.e. if I'm on board 2, and I program a single unit which counts every time I receive a character from the selectmap, I would do the following
+
+echo "12345" > /dev/selectmap2;
+head -c5 /dev/selectmap2;
+
+i.e. if I'm on board1, and the interchip connects to board2, I would do something like 
+
+echo "12345" > /dev/selectmap1;
+head -c5 /dev/selectmap2;
+
+===========
+
+Finally, step by step instructions on how to go from a verilog project to programming it and running it on the Bee2.
+
+1. Use RDLC to generate files from the RDL
+2. Copy all verilog files into a single flat directory on a server connected to a bee2 board (like sting)
+3. Make sure the selectmap FIFO, main*.v and Makefile* are also in that same directory.
+4. Customize the main*.v files to connect the right ports to selectmap FIFOs, and your Maps. If you have multiple Maps, make two separate main files
+5. Customize the Makefile to point to the right chip. If you are making two maps, make two Makefiles.
+6. Run Makefile. The original Makefiles will program the chips automatically.
+7. Use the above instructions to start running the tests by echoing characters into the selectmap.
diff --git a/bee2-selectmap/async_fifo_8_8_128.edn b/bee2-selectmap/async_fifo_8_8_128.edn
new file mode 100644 (file)
index 0000000..5562d7c
--- /dev/null
@@ -0,0 +1,402 @@
+(edif test (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0))
+(status (written (timeStamp 2006 2 18 19 6 14)
+   (author "Xilinx, Inc.")
+   (program "Xilinx CORE Generator" (version "Xilinx CORE Generator 7.1.04i; Cores Update # 3"))))
+   (comment "                                                                                
+      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-2005 Xilinx, Inc.                                      
+      All rights reserved.                                                      
+                                                                                
+   ")
+   (comment "Core parameters: ")
+       (comment "c_wr_response_latency = 1 ")
+       (comment "c_has_rd_data_count = 1 ")
+       (comment "c_din_width = 8 ")
+       (comment "c_has_wr_data_count = 1 ")
+       (comment "InstanceName = async_fifo_8_8_128 ")
+       (comment "c_implementation_type = 2 ")
+       (comment "c_family = virtex2p ")
+       (comment "c_has_wr_rst = 0 ")
+       (comment "c_underflow_low = 0 ")
+       (comment "c_has_meminit_file = 0 ")
+       (comment "c_has_overflow = 0 ")
+       (comment "c_preload_latency = 0 ")
+       (comment "c_dout_width = 8 ")
+       (comment "c_rd_depth = 128 ")
+       (comment "c_default_value = BlankString ")
+       (comment "c_mif_file_name = BlankString ")
+       (comment "c_has_underflow = 0 ")
+       (comment "c_has_rd_rst = 0 ")
+       (comment "c_has_almost_full = 0 ")
+       (comment "c_has_rst = 1 ")
+       (comment "c_data_count_width = 2 ")
+       (comment "c_has_wr_ack = 0 ")
+       (comment "c_wr_ack_low = 0 ")
+       (comment "c_common_clock = 0 ")
+       (comment "c_rd_pntr_width = 7 ")
+       (comment "c_has_almost_empty = 0 ")
+       (comment "c_rd_data_count_width = 8 ")
+       (comment "c_enable_rlocs = 0 ")
+       (comment "c_wr_pntr_width = 7 ")
+       (comment "c_overflow_low = 0 ")
+       (comment "c_prog_empty_type = 0 ")
+       (comment "c_optimization_mode = 0 ")
+       (comment "c_wr_data_count_width = 8 ")
+       (comment "c_preload_regs = 1 ")
+       (comment "c_dout_rst_val = 0 ")
+       (comment "c_has_data_count = 0 ")
+       (comment "c_prog_full_thresh_negate_val = 96 ")
+       (comment "c_wr_depth = 128 ")
+       (comment "c_prog_empty_thresh_negate_val = 32 ")
+       (comment "c_prog_empty_thresh_assert_val = 32 ")
+       (comment "c_has_valid = 0 ")
+       (comment "c_init_wr_pntr_val = 0 ")
+       (comment "c_prog_full_thresh_assert_val = 96 ")
+       (comment "c_use_fifo16_flags = 0 ")
+       (comment "c_has_backup = 0 ")
+       (comment "c_valid_low = 0 ")
+       (comment "c_prim_fifo_type = 512 ")
+       (comment "c_count_type = 0 ")
+       (comment "c_prog_full_type = 0 ")
+       (comment "c_memory_type = 1 ")
+   (external xilinxun (edifLevel 0)
+      (technology (numberDefinition))
+       (cell VCC (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port P (direction OUTPUT))
+               )
+           )
+       )
+       (cell GND (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port G (direction OUTPUT))
+               )
+           )
+       )
+   )
+   (external async_fifo_8_8_128_fifo_generator_v2_2_xst_1_lib (edifLevel 0)
+       (technology (numberDefinition))
+       (cell async_fifo_8_8_128_fifo_generator_v2_2_xst_1 (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port clk (direction INPUT))
+                   (port backup (direction INPUT))
+                   (port backup_marker (direction INPUT))
+                   (port ( array ( rename din "din<7:0>") 8 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh "prog_empty_thresh<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh_assert "prog_empty_thresh_assert<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_empty_thresh_negate "prog_empty_thresh_negate<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh "prog_full_thresh<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh_assert "prog_full_thresh_assert<6:0>") 7 ) (direction INPUT))
+                   (port ( array ( rename prog_full_thresh_negate "prog_full_thresh_negate<6:0>") 7 ) (direction INPUT))
+                   (port rd_clk (direction INPUT))
+                   (port rd_en (direction INPUT))
+                   (port rd_rst (direction INPUT))
+                   (port rst (direction INPUT))
+                   (port wr_clk (direction INPUT))
+                   (port wr_en (direction INPUT))
+                   (port wr_rst (direction INPUT))
+                   (port almost_empty (direction OUTPUT))
+                   (port almost_full (direction OUTPUT))
+                   (port ( array ( rename data_count "data_count<1:0>") 2 ) (direction OUTPUT))
+                   (port ( array ( rename dout "dout<7:0>") 8 ) (direction OUTPUT))
+                   (port empty (direction OUTPUT))
+                   (port full (direction OUTPUT))
+                   (port overflow (direction OUTPUT))
+                   (port prog_empty (direction OUTPUT))
+                   (port prog_full (direction OUTPUT))
+                   (port valid (direction OUTPUT))
+                   (port ( array ( rename rd_data_count "rd_data_count<7:0>") 8 ) (direction OUTPUT))
+                   (port underflow (direction OUTPUT))
+                   (port wr_ack (direction OUTPUT))
+                   (port ( array ( rename wr_data_count "wr_data_count<7:0>") 8 ) (direction OUTPUT))
+               )
+           )
+       )
+   )
+(library test_lib (edifLevel 0) (technology (numberDefinition (scale 1 (E 1 -12) (unit Time))))
+(cell async_fifo_8_8_128
+ (cellType GENERIC) (view view_1 (viewType NETLIST)
+  (interface
+   (port ( array ( rename din "din<7:0>") 8 ) (direction INPUT))
+   (port ( rename rd_clk "rd_clk") (direction INPUT))
+   (port ( rename rd_en "rd_en") (direction INPUT))
+   (port ( rename rst "rst") (direction INPUT))
+   (port ( rename wr_clk "wr_clk") (direction INPUT))
+   (port ( rename wr_en "wr_en") (direction INPUT))
+   (port ( array ( rename dout "dout<7:0>") 8 ) (direction OUTPUT))
+   (port ( rename empty "empty") (direction OUTPUT))
+   (port ( rename full "full") (direction OUTPUT))
+   (port ( array ( rename rd_data_count "rd_data_count<7:0>") 8 ) (direction OUTPUT))
+   (port ( array ( rename wr_data_count "wr_data_count<7:0>") 8 ) (direction OUTPUT))
+   )
+  (contents
+   (instance VCC (viewRef view_1 (cellRef VCC  (libraryRef xilinxun))))
+   (instance GND (viewRef view_1 (cellRef GND  (libraryRef xilinxun))))
+   (instance BU2
+      (viewRef view_1 (cellRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1 (libraryRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_lib)))
+   )
+   (net (rename N5 "din<7>")
+    (joined
+      (portRef (member din 0))
+      (portRef (member din 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N6 "din<6>")
+    (joined
+      (portRef (member din 1))
+      (portRef (member din 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N7 "din<5>")
+    (joined
+      (portRef (member din 2))
+      (portRef (member din 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N8 "din<4>")
+    (joined
+      (portRef (member din 3))
+      (portRef (member din 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N9 "din<3>")
+    (joined
+      (portRef (member din 4))
+      (portRef (member din 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N10 "din<2>")
+    (joined
+      (portRef (member din 5))
+      (portRef (member din 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N11 "din<1>")
+    (joined
+      (portRef (member din 6))
+      (portRef (member din 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N12 "din<0>")
+    (joined
+      (portRef (member din 7))
+      (portRef (member din 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N55 "rd_clk")
+    (joined
+      (portRef rd_clk)
+      (portRef rd_clk (instanceRef BU2))
+    )
+   )
+   (net (rename N56 "rd_en")
+    (joined
+      (portRef rd_en)
+      (portRef rd_en (instanceRef BU2))
+    )
+   )
+   (net (rename N58 "rst")
+    (joined
+      (portRef rst)
+      (portRef rst (instanceRef BU2))
+    )
+   )
+   (net (rename N59 "wr_clk")
+    (joined
+      (portRef wr_clk)
+      (portRef wr_clk (instanceRef BU2))
+    )
+   )
+   (net (rename N60 "wr_en")
+    (joined
+      (portRef wr_en)
+      (portRef wr_en (instanceRef BU2))
+    )
+   )
+   (net (rename N66 "dout<7>")
+    (joined
+      (portRef (member dout 0))
+      (portRef (member dout 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N67 "dout<6>")
+    (joined
+      (portRef (member dout 1))
+      (portRef (member dout 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N68 "dout<5>")
+    (joined
+      (portRef (member dout 2))
+      (portRef (member dout 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N69 "dout<4>")
+    (joined
+      (portRef (member dout 3))
+      (portRef (member dout 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N70 "dout<3>")
+    (joined
+      (portRef (member dout 4))
+      (portRef (member dout 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N71 "dout<2>")
+    (joined
+      (portRef (member dout 5))
+      (portRef (member dout 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N72 "dout<1>")
+    (joined
+      (portRef (member dout 6))
+      (portRef (member dout 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N73 "dout<0>")
+    (joined
+      (portRef (member dout 7))
+      (portRef (member dout 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N74 "empty")
+    (joined
+      (portRef empty)
+      (portRef empty (instanceRef BU2))
+    )
+   )
+   (net (rename N75 "full")
+    (joined
+      (portRef full)
+      (portRef full (instanceRef BU2))
+    )
+   )
+   (net (rename N80 "rd_data_count<7>")
+    (joined
+      (portRef (member rd_data_count 0))
+      (portRef (member rd_data_count 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N81 "rd_data_count<6>")
+    (joined
+      (portRef (member rd_data_count 1))
+      (portRef (member rd_data_count 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N82 "rd_data_count<5>")
+    (joined
+      (portRef (member rd_data_count 2))
+      (portRef (member rd_data_count 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N83 "rd_data_count<4>")
+    (joined
+      (portRef (member rd_data_count 3))
+      (portRef (member rd_data_count 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N84 "rd_data_count<3>")
+    (joined
+      (portRef (member rd_data_count 4))
+      (portRef (member rd_data_count 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N85 "rd_data_count<2>")
+    (joined
+      (portRef (member rd_data_count 5))
+      (portRef (member rd_data_count 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N86 "rd_data_count<1>")
+    (joined
+      (portRef (member rd_data_count 6))
+      (portRef (member rd_data_count 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N87 "rd_data_count<0>")
+    (joined
+      (portRef (member rd_data_count 7))
+      (portRef (member rd_data_count 7) (instanceRef BU2))
+    )
+   )
+   (net (rename N90 "wr_data_count<7>")
+    (joined
+      (portRef (member wr_data_count 0))
+      (portRef (member wr_data_count 0) (instanceRef BU2))
+    )
+   )
+   (net (rename N91 "wr_data_count<6>")
+    (joined
+      (portRef (member wr_data_count 1))
+      (portRef (member wr_data_count 1) (instanceRef BU2))
+    )
+   )
+   (net (rename N92 "wr_data_count<5>")
+    (joined
+      (portRef (member wr_data_count 2))
+      (portRef (member wr_data_count 2) (instanceRef BU2))
+    )
+   )
+   (net (rename N93 "wr_data_count<4>")
+    (joined
+      (portRef (member wr_data_count 3))
+      (portRef (member wr_data_count 3) (instanceRef BU2))
+    )
+   )
+   (net (rename N94 "wr_data_count<3>")
+    (joined
+      (portRef (member wr_data_count 4))
+      (portRef (member wr_data_count 4) (instanceRef BU2))
+    )
+   )
+   (net (rename N95 "wr_data_count<2>")
+    (joined
+      (portRef (member wr_data_count 5))
+      (portRef (member wr_data_count 5) (instanceRef BU2))
+    )
+   )
+   (net (rename N96 "wr_data_count<1>")
+    (joined
+      (portRef (member wr_data_count 6))
+      (portRef (member wr_data_count 6) (instanceRef BU2))
+    )
+   )
+   (net (rename N97 "wr_data_count<0>")
+    (joined
+      (portRef (member wr_data_count 7))
+      (portRef (member wr_data_count 7) (instanceRef BU2))
+    )
+   )
+))))
+(design async_fifo_8_8_128 (cellRef async_fifo_8_8_128 (libraryRef test_lib))
+  (property X_CORE_INFO (string "fifo_generator_v2_2, Coregen 7.1.04i_ip3"))
+  (property PART (string "xc2vp70-ff1704-7") (owner "Xilinx")))
+)
diff --git a/bee2-selectmap/async_fifo_8_8_128.v b/bee2-selectmap/async_fifo_8_8_128.v
new file mode 100644 (file)
index 0000000..ce27aa2
--- /dev/null
@@ -0,0 +1,155 @@
+/*******************************************************************************
+*     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-2005 Xilinx, Inc.                                     *
+*     All rights reserved.                                                     *
+*******************************************************************************/
+// The synopsys directives "translate_off/translate_on" specified below are
+// supported by XST, FPGA Compiler II, Mentor Graphics and Synplicity synthesis
+// tools. Ensure they are correct for your synthesis tool(s).
+
+// You must compile the wrapper file async_fifo_8_8_128.v when simulating
+// the core, async_fifo_8_8_128. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
+`timescale 1ns/1ps
+
+module async_fifo_8_8_128(
+       din,
+       rd_clk,
+       rd_en,
+       rst,
+       wr_clk,
+       wr_en,
+       dout,
+       empty,
+       full,
+       rd_data_count,
+       wr_data_count);
+
+
+input [7 : 0] din;
+input rd_clk;
+input rd_en;
+input rst;
+input wr_clk;
+input wr_en;
+output [7 : 0] dout;
+output empty;
+output full;
+output [7 : 0] rd_data_count;
+output [7 : 0] wr_data_count;
+
+// synopsys translate_off
+
+      FIFO_GENERATOR_V2_2 #(
+               0,      // c_common_clock
+               0,      // c_count_type
+               2,      // c_data_count_width
+               "BlankString",  // c_default_value
+               8,      // c_din_width
+               "0",    // c_dout_rst_val
+               8,      // c_dout_width
+               0,      // c_enable_rlocs
+               "virtex2p",     // c_family
+               0,      // c_has_almost_empty
+               0,      // c_has_almost_full
+               0,      // c_has_backup
+               0,      // c_has_data_count
+               0,      // c_has_meminit_file
+               0,      // c_has_overflow
+               1,      // c_has_rd_data_count
+               0,      // c_has_rd_rst
+               1,      // c_has_rst
+               0,      // c_has_underflow
+               0,      // c_has_valid
+               0,      // c_has_wr_ack
+               1,      // c_has_wr_data_count
+               0,      // c_has_wr_rst
+               2,      // c_implementation_type
+               0,      // c_init_wr_pntr_val
+               1,      // c_memory_type
+               "BlankString",  // c_mif_file_name
+               0,      // c_optimization_mode
+               0,      // c_overflow_low
+               0,      // c_preload_latency
+               1,      // c_preload_regs
+               512,    // c_prim_fifo_type
+               32,     // c_prog_empty_thresh_assert_val
+               32,     // c_prog_empty_thresh_negate_val
+               0,      // c_prog_empty_type
+               96,     // c_prog_full_thresh_assert_val
+               96,     // c_prog_full_thresh_negate_val
+               0,      // c_prog_full_type
+               8,      // c_rd_data_count_width
+               128,    // c_rd_depth
+               7,      // c_rd_pntr_width
+               0,      // c_underflow_low
+               0,      // c_use_fifo16_flags
+               0,      // c_valid_low
+               0,      // c_wr_ack_low
+               8,      // c_wr_data_count_width
+               128,    // c_wr_depth
+               7,      // c_wr_pntr_width
+               1)      // c_wr_response_latency
+       inst (
+               .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),
+               .RD_DATA_COUNT(rd_data_count),
+               .WR_DATA_COUNT(wr_data_count),
+               .CLK(),
+               .BACKUP(),
+               .BACKUP_MARKER(),
+               .PROG_EMPTY_THRESH(),
+               .PROG_EMPTY_THRESH_ASSERT(),
+               .PROG_EMPTY_THRESH_NEGATE(),
+               .PROG_FULL_THRESH(),
+               .PROG_FULL_THRESH_ASSERT(),
+               .PROG_FULL_THRESH_NEGATE(),
+               .RD_RST(),
+               .WR_RST(),
+               .ALMOST_EMPTY(),
+               .ALMOST_FULL(),
+               .DATA_COUNT(),
+               .OVERFLOW(),
+               .PROG_EMPTY(),
+               .PROG_FULL(),
+               .VALID(),
+               .UNDERFLOW(),
+               .WR_ACK());
+
+
+// synopsys translate_on
+
+endmodule
+
diff --git a/bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc b/bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1.ngc
new file mode 100644 (file)
index 0000000..dc18c6b
--- /dev/null
@@ -0,0 +1,3 @@
+XILINX-XDB 0.1 STUB 0.1 ASCII
+XILINX-XDM V1.4e
+$52f\7f4=7:2:3=6?>;33;?7<H]]Z^X7jnt`]`kphs480;2<5;4:66104<=8;0:95998426>1=AGZ^X7OKDSC?2?699;1<6D@_UU8B@ATE4?0;2<k47;KMTPR=X[ELSHC_TX]WLWCT@5<1<3<:;68JJUSS2YXDKRKBPU[\PMTB[AUJ_^K]T=494;423>0BB][[:QPLCZCJX]STXE\JSI]MABGSM5<1<3?k;68JJUSS2YXDKRHZLM]WLWCT@5<1<3<;;68JJUSS2YXDKRHZLM]WLWCT@VKX_H\[<783:72<?3CE\XZ5PSMD[CSKDV^C^H]G_OGDEQC;>3:5=h58:HLSQQ<wzfmTi`~{y^vkv`uo4?0;2?;47;KMTPR=x{elShc\7ftx]wlwct`Vkx\7fh|{<783:73<?3CE\XZ5psmd[`kw|pU\7fd\7fk|h^lfcdrb4?0;2<j47;KMTPR=x{elSk{cl^vkv`uo4?0;2?:47;KMTPR=x{elSk{cl^vkv`uoWhyxi\7fz36;2=61=02@D[YY4\7frne\bpjkW}byi~fPndebp`:1294:n695OTVSQQ<CMK_LS_JPPOVQ83<768h0;7AZTQWW>ACE]NU\^R^ATS>5>585;2=1CXZ_UU8gags`W{nT|cz}_qnvw4Yu4?0;2<j47;MVPUSS2moiyjQ}d^rmpwYu4?0;2<j47;MVPUSS2moiyjQ}d^rmpwYp4?0;2?=47;MVPUSS2moiyjQxr^rmpwYwd|y:Sz29:1<17>1=G\^[YY4kecwd[rtXxg~yS}bzs3]t83<768n0;7AZTQWW>ace}nU|~R~ats]q83<768n0;7AZTQWW>ace}nU|~R~ats]t83<76;13<95701224>>=AGZ^X7JFN=594;76310BB][[:EKME91=87;:754FNQWW>AOIJ5=1<3??;98JJUSS2mce0:4?>008<?IR\Y__6IAZT=594;74310DYY^ZT;FLQQG;?3:5=>57:NWWTPR=LF__N1950?3a?=<H]]Z^X7\K_ECWEZEH]G^7;7>11c9;>JSSX\^1[_QKAUC\GJSI\5=1<3?=;98LQQVR\3ndyy28:1<2f>>=G\^[YY4}d^fbpdYdg|d\7f0:4?>0`8<?IR\Y__6z|Pd`vb[firf}6<6=0>;868=56>:23=46OKDSC?4;><IMNYM1?18:CG@WG;:720MIJ]A=1=<>GCL[K78364AEFQE939i2KOH_O36;2=<>GCL[K7:364AEFQF96902KOH_L31?:8EABUJ58546OKDS@?7;><IMNYN1:18:CG@WD;=7k0MIJ]B=494;><IMNYN1814:CE62e<IEGD_YQJMQVZf>GKEFY_SK[CL89BW\HDW[OL86LNA@:8FPUXAGLD=6M=;B61?FC>3JBDENK>08;8GMINKL;9<45LHNK@A44012ICCDMJ12::?FNHAJO:9=74CIMJG@71901HDBGLE04;=>EOG@IN=:76;BJLMFC61830OEAFCD036==D@FCHI9;7;BJLMFC2>11HDBGLE7:;?FNHAJO<555LHNK@A=0?3JBDENK6739@M1=DDBK?7NBDB29@HW?<KFGFEYZJD69@V@GSMM;0Hk5KECWD[WGJWLG[XTk4DD@VCZTFEVL^@Ah4DD@VCZTFEVXOSH@i;EGAQBYUIDU\^RKA119GAGS@W[NT\CZ]<1<24>BBJ\MT^IQ_NUP?5;773MOIYJQ]D^RMPW:568:0HHLZG^PG[UHSZ595==5KECWD[WBXXG^Y090>0:FFFPAXZMU[BY\35?31?ACE]NUYHR^ATS>5>58682NNNXIPRE]SJQT;>7;;7IKMUF]TVZVI\[6;2<>4DD@VCZQUWYD_^1?1119GAGS@W^XT\CZ]<3<24>BBJ\MT[_Q_NUP?7;773MOIYJQXR^RMPW:368:0HHLZG^UQ[UHSZ5?5=?5KECWD[RTXXG^Y0;4?>028@@DROV]YS]@[R=4=6>BN>2NBB1>16:FJJ979>2NBB1<16:FJJ959>2NBB1:16:FJJ939>2NBB1818:FJJ91=87<0HD@37?58@LHF494<7IGAA=3=3>BNFH692:5KIOC?7;1<L@DJ0908;EKME939?2NBBL29>89GMKG;?3:5;6JFN@>4:2=CAGH7<394DHLA84803MCEN1<17:FJJG:46>1OECL34?58@LHE4<4<7IGAB=4==>BNFK6<6=08;EKMF919?2NDYY2?>69GKPR;97=0HB[[<3<4?AIR\595;6J@UU>7:2=CG\^79394DNWW838>3ME^X1950?58@JSS4>437IAZT@>3:==CG\^J0<07;EMVPD:5611OCXZN<2<;?AIR\H6?255KOTVB808?3ME^XL29>`9GKPRF4>0;255KOTVB828?3ME^XO2?>99GKPRE48437IAZTC>1:==CG\^I0>07;EMVPG:3611OCXZM<4<;?AIR\K6=2l5KOTVA82<7611OCXZM<6<2?@3<MDZ_U>5JN@18AKD53O>97K6<;GF@0>@CKL90JI^;;GFSA1=A]EF:7J=4GOF7?M(3:;1B<?5F139J67=N;01BBDZ\T@VF6>JN:2FD;6B@GHABH1=K]];=7A[[1^N7?ISS:?1GYY<PL59OQQ513E__?RB;;MWW00=J]QIR>6@?4:L03<5<FMK87CJM7:LFPRIUC>1EC@K]GD38K==H^LXM@BY>;Q68TDTSi2ZBBRLZSHF[f>VNFVH^_COBE29SV@g<X[ELSHC_TX37?UTHOVOF\YWPTIPFWM:768>0\_AH_DOSP\YS@[OXD1?1159SVJAXMDZ_URZGRDQK8786<2ZYCJQJMQVZ[QNUMZB7?3?;;QPLCZCJX]STXE\JSI>7:42<X[ELSHC_TX]WLWCT@5?5=;5_RNE\AHVSQV^C^H]G<783:42<X[ELSHC_TX]WLWCT@5<5=o5_RNE\AHVSQV^C^H]G_@QPAWR;87;i7]\@G^GNTQ_X\AXN_EQNSRGQP9799k1[^BIPELRW]ZROZLYCSL]\ESV?6;7e3YXDKRKBPU[\PMTB[AUJ_^K]T=1=5g=WZFMTI@^[Y^VKV@UOWHYXI_Z34?3a?UTHOVOF\YWPTIPFWMYF[ZOYX1;11e9SVJAXMDZ_URZGRDQK[DUTM[^7:7>11c9SVJAXMDZ_URZGRDQK[DUTM[^7:3?m;QPLCZCJX]STXE\JSI]MABGSM5:5=o5_RNE\AHVSQV^C^H]G_OGDEQC;97;i7]\@G^GNTQ_X\AXN_EQAEFCWA9499k1[^BIPELRW]ZROZLYCSCKHAUG?7;7e3YXDKRKBPU[\PMTB[AUEIJO[E=6=5g=WZFMTI@^[Y^VKV@UOWGOLMYK35?3g?UTHOVOF\YWPTIPFWMYIMNK_I1850?3a?UTHOVOF\YWPTIPFWMYIMNK_I1819:RQKBYA]EF:?6^]OF]EQIJX\AXN_E2?>018TWI@WO_G@RZGRDQK8486;2ZYCJQIUMN\PMTB[A692<=4PSMD[CSKDV^C^H]G<2<27>VUGNUMYABPTIPFWM:36890\_AH_GWOHZROZLYC080>5:RQKBYA]EFTXE\JSI>5>586;2ZYCJQIUMN\PMTB[A6=2<o4PSMD[CSKDV^C^H]G_@QPAWR;87;j7]\@G^DVHIYS@[OXDRO\SDPW8486i2ZYCJQIUMN\PMTB[AUJ_^K]T=0=5d=WZFMTJXBC_UJQAVNXIZYN^Y2<>0c8TWI@WO_G@RZGRDQK[DUTM[^783?n;QPLCZ@RDEU_D_K\H^CPW@TS4<4:o6^]OF]EQIJX\AXN_EQNSRGQP90=87;j7]\@G^DVHIYS@[OXDRO\SDPW8386i2ZYCJQIUMN\PMTB[AUEIJO[E=2=5d=WZFMTJXBC_UJQAVNXFLMJXH2>>0c8TWI@WO_G@RZGRDQK[KC@I]O7>3?n;QPLCZ@RDEU_D_K\H^LFCDRB4:4:m6^]OF]EQIJX\AXN_EQAEFCWA9299h1[^BIPFTNO[QNUMZBTBHINTD>6:4e<X[ELSK[CL^VKV@UOWGOLMYK36;2=5d=WZFMTJXBC_UJQAVNXFLMJXH29>09R0>TCQH>0^IWM6:PG[FJL991YHRJNT@]@KPHS494:<6\K_ECWEZEH]G^7=3??;SF\@DRFWJE^BY2=>028VAYCI]KTOB[AT=1=55=ULVNJXLQLOTLW818682XOSIO[A^ALQKR;=7;;7_JPD@VB[FIRF]6=2<<4RE]GEQGXKF_EX1950?33?WBXLH^JSNAZNU>4:0=ULVOE86\ID@68VCBE;2XXX<5\6:QJJLRF>2YBBDZM6:QLQWEB<2^R\H94U1-ecdu>3\DOI_HCOVa8QVCUW_CXEOBJ5:TBHLB43_IH56XFEV]W]UC43^OJ?6YJB79TVZGDC?1\^RMCK028SWYCI]KTOB[AT=2=55=PZVNJXLQLOTLW848682]YSIO[A^ALQKR;:7;;7Z\PD@VB[FIRF]682<>4WS]GEQGXKF_EX1:1119TVZBF\HUHCX@[<4<24>QUWMK_MRM@UOV?2;753^XTHLZN_BMVJQ:0294:<6Y]_ECWEZEH]G^7;3;4WS]FJ4b<P@FBBU#WDC"3*4&T\\H+<#?/ARAJM0=_G[IR:6V\TMKA3>^T\VMEH:5WSU]UGFd<PVID^HQFNGM5?]beW@n:<6Vkm^ObnjtQm{ybcc??;Yfn[Hoig{\n~~g`n29[wqe<iegd\7fyQjmqvzf>gkefy\7fSk{cl3a8ev\7fikVlbjbQ7_9]26=YaaoeTkh`jr`vlvZp5W;Us\7fyQ>3d9bw|hdWocmcR6P8^31<Z`nnfUlick}aumq[s4X:VrxxR?PbminahbwW\7f<T>Rv|t79aefmrxm1imnezp^obvncu;2igg?j4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%E?9o4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqYdg|d\7fSR`?012?4;Ydqf>37n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<1<`}1?<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:7<3bzt5c8gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;97Uhub:n;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrXkf\7fexRQa0123848Xpfx?46matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=3=g|2f3jd\7fnae gdl\vaYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;0?0Pcxm7e>ei|kf`#jka_sf\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j5678585Sua}499`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:56js?m6matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=1=[f\7fh<h1hbylck.efjZtcWjd\7f~"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^alqkrXWg:;<=2<>^zlv1><kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:7?3mv4`9`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:36Virc9o4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqYdg|d\7fSR`?012?0;Y\7fg{>37n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<5<`}1g<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:793Qlyn6b?fhsjea$kh`Pre]`jqt(j`dToczPtnr,fibXj`dTocz bra\flhXkg~Tob{at^]m45674<4Ttb|;8:ampgjl'noeS\7fjPcovq+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsWje~byQPn1234939kp>j7n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\gjsi|VUe<=>?<7<\|jt4:2iexobd/fgm[wbXkg~y#oga_blw[qiw'kfoSoga_blw+firf}U;??5lnu`oo*abfVxoSn`{r.`jjZei|V~d|"lcd^`jjZei|&idyczP1278gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[4Yu|:80oczmlj-dakYulViex\7f!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS?=:;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^0\vq553jd\7fnae gdl\vaYdf}x$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V9896matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQ<_sv06>ei|kf`#jka_sf\gkru'kceSn`{_ums+gjcWkceSn`{/bmvjqY3;<1hbylck.efjZtcWjd\7f~"lfn^ampZrhx&hghRlfn^amp*eh}g~T8R|{339`jqdkc&mnbR|k_blwv*dnfViexRz`p.`o`ZdnfViex"m`uov\163<kg~i`f!heo]q`Zei|{%iecQlnu]wku)edmUiecQlnu-`kphsW<Uyx><4covahn)`mgUyhRmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_716?fhsjea$kh`Pre]`jqt(j`dToczPtnr,fibXj`dTocz cnwmpZ0Xz}9j7n`{bmi,c`hXzmUhby| bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa01238484i2iexobd/fgm[wbXkg~y#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=0=7d=df}hgg"ijn^pg[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2<>2c8gkredb%licQ}d^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:783=n;blwfim(oldT~iQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^]m45674<48m6matcnh+bciW{nTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQPn1234909;:1hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$B>;=;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;0=0Pcxm64>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]3[firf}UTb=>?0=2=g|363jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZ6Xkf\7fexRQa0123858k}}?97n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m4567484Tota:2:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ?_bmvjqYXf9:;<1?1_ymq15=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>2:f\7f2:2iexobd/fgm[wbXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234949Wjsd9?5lnu`oo*abfVxoSn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k6789692Rv`r428gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>32?az17=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>0:Ze~g<80oczmlj-dakYulViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;;7Usc\7f;?;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;0>0ly408gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>34?]`}j353jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZ6Xkf\7fexRQa0123818Xpfx><6matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U;Snaznu]\j56785>5ot;=;blwfim(oldT~iQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;080Pcxm66>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]3[firf}UTb=>?0=7=[}iu=91hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrX8VidyczP_o2345:26js>>6matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U;Snaznu]\j56785<5Sua}399`jqdkc&mnbR|k_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V:846matcnh+bciW{nTocz}_qnvw4)eagUhbyQ{oq-ahaYeagUhby!lotlw[45e3jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP1^pw7==df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(kf\7fexR<<b:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-`kphsW;Uyx>64covahn)`mgUyhRmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqY4;k1hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$ob{at^1\vq5?3jd\7fnae gdl\vaYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP42`8gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}U?S\7fz<8:ampgjl'noeS\7fjPcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-`kphsW<9i7n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\1Zts;11hbylck.efjZtcWjd\7f~R~cur3,flhXkg~Txb~ bmf\flhXkg~$ob{at^40f>ei|kf`#jka_sf\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS;Q}t528gkredb%licQ}d^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=3=05=df}hgg"ijn^pg[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa0123878382iexobd/fgm[wbXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;;7>;7n`{bmi,c`hXzmUhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896?29>4covahn)`mgUyhRmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqYXf9:;<1;1419`jqdkc&mnbR|k_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|VUe<=>?<7<1`>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/O17e>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j56785:5Snw`499`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:76js?56matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=2=hpr3i2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_bmvjqYXf9:;<1?1_b{l0d=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexRm`uov\[k67896:2Rv`r5:8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;97ir8l5lnu`oo*abfV}ySn`{r.`jjZei|V~d|"lcd^`jjZei|&hxoRlfn^ampZeh}g~TSc>?01>1:Ze~g=k0oczmlj-dakYpzViex\7f!mio]`jqYsgy%i`iQmio]`jq)e{jUiecQlnu]`kphsWVd;<=>32?]{kw2?3jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;0?0ly5c8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}Uhcx`{_^l3456;;7Uhub:n;blwfim(oldT{\7fQlnup,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrXkf\7fexRQa0123868Xpfx?46matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=1=g|2f3jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczPcnwmpZYi89:;090Pcxm7e>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fSnaznu]\j56785>5Sua}499`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:36js?m6matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[firf}UTb=>?0=7=[f\7fh<h1hbylck.efjZquWjd\7f~"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^alqkrXWg:;<=2:>^zlv1><kg~i`f!heo]tvZei|{%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQlotlw[Zh789:793mv4`9`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|VidyczP_o2345:16Vrd~><4covahn)`mgU|~Rmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_111?fhsjea$kh`Pws]`jqt(j`dToczPtnr,fibXj`dTocz cnwmpZ74=2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+firf}U:S\7fz<2:ampgjl'noeSz|Pcovq+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]170=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrX:Vx\7f??5lnu`oo*abfV}ySn`{r.`jjZei|V~d|"lcd^`jjZei|&idyczP3278gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[6Yu|:80oczmlj-dakYpzViex\7f!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS9=:;blwfim(oldT{\7fQlnup,flhXkg~Txb~ bmf\flhXkg~$ob{at^6\vq553jd\7fnae gdl\swYdf}x$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?896matcnh+bciW~xTocz}/ckm[fhsW}e{#obk_ckm[fhs'je~byQ:_sv06>ei|kf`#jka_vp\gkru'kceSn`{_ums+gjcWkceSn`{/bmvjqY1;<1hbylck.efjZquWjd\7f~"lfn^ampZrhx&hghRlfn^amp*eh}g~T:R|{3`9`jqdkc&mnbRy}_blwv*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896:2>o4covahn)`mgU|~Rmats-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;:79j7n`{bmi,c`hX\7f{Uhby| bhl\gkrX|fz$najPbhl\gkr(kf\7fexRQa01238684i2iexobd/fgm[rtXkg~y#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=6=7d=df}hgg"ijn^uq[fhsz&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2:>2c8gkredb%licQxr^ampw)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:7:3=<;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.L017=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>3:Ze~g<:0oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;87ir9<5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k67896;2a{{539`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczP0^alqkrXWg:;<=2>>^azk04<kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[5Ydg|d\7fSR`?012?5;Y\7fg{?;7n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m4567484hu8<4covahn)`mgU|~Rmats]shpu6'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fS=Qlotlw[Zh789:7>3Qlyn71?fhsjea$kh`Pws]`jqtXxe\7fx="lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^2\gjsi|VUe<=>?<3<\|jt282iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234949kp?97n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V:Tob{at^]m45674:4Tota:2:ampgjl'noeSz|Pcovq[ujr{8%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ?_bmvjqYXf9:;<1=1_ymq15=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>0:f\7f2:2iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY7Wje~byQPn1234929Wjsd9?5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T<Rm`uov\[k67896?2Rv`r428gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>34?az17=df}hgg"ijn^uq[fhszVzgy~? bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\4Zeh}g~TSc>?01>6:Ze~g<80oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW9Uhcx`{_^l3456;=7Usc\7f;?;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.`pgZdnfViexR>PcnwmpZYi89:;080ly408gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+gudWkceSn`{_1]`kphsWVd;<=>36?]{kw5?3jd\7fnae gdl\swYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP02:8gkredb%licQxr^ampwYwd|y:#oga_blw[qiw'kfoSoga_blw+firf}U:?o5lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz cnwmpZ7Xz}937n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\66d<kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'je~byQ=_sv0<>ei|kf`#jka_vp\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fS>=m;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.alqkrX;Vx\7f?55lnu`oo*abfV}ySn`{r^roqv7(j`dToczPtnr,fibXj`dTocz cnwmpZ24j2iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_5]qp6><kg~i`f!heo]tvZei|{U{`x}>/ckm[fhsW}e{#obk_ckm[fhs'je~byQ:3c9`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?T~y=7;blwfim(oldT{\7fQlnup\tist9&hbbRmat^vlt*dklVhbbRmat.alqkrX>:h0oczmlj-dakYpzViex\7fQ\7fltq2+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]5[wr382iexobd/fgm[rtXkg~yS}bzs0-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_^l3456;97>;7n`{bmi,c`hX\7f{Uhby|Ppmwp5*dnfViexRz`p.`o`ZdnfViex"m`uov\[k67896929>4covahn)`mgU|~Rmats]shpu6'kceSn`{_ums+gjcWkceSn`{/bmvjqYXf9:;<1=1419`jqdkc&mnbRy}_blwvZvk}z;$nd`Pcov\pjv(jenTnd`Pcov,gjsi|VUe<=>?<5<74>ei|kf`#jka_vp\gkruWyf~\7f<!mio]`jqYsgy%i`iQmio]`jq)dg|d\7fSR`?012?1;273jd\7fnae gdl\swYdf}xT|a{|1.`jjZei|V~d|"lcd^`jjZei|&idyczP_o2345:16:90oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#C=:2:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1>1_b{l15=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\5Zeh}g~TSc>?01>3:f\7f292iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY6Wje~byQPn1234969d|~>>6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!msb]amkYdf}U:Snaznu]\j56785;5Snw`539`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,fveXj`dToczP1^alqkrXWg:;<=2>>^zlv06<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[4Ydg|d\7fSR`?012?5;e~=;1hbylck.efjZquWjd\7f~R~cur0,flhXkg~Txb~ bmf\flhXkg~$n~mPbhl\gkrX9VidyczP_o2345:56Virc8<4covahn)`mgU|~Rmats]shpu5'kceSn`{_ums+gjcWkceSn`{/cq`[goiWjd\7fS<Qlotlw[Zh789:7>3Qwos73?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^3\gjsi|VUe<=>?<3<`}04<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'kyhSoga_blw[4Ydg|d\7fSR`?012?7;Ydqf?97n`{bmi,c`hX\7f{Uhby|Ppmwp6*dnfViexRz`p.`o`ZdnfViex"l|c^`jjZei|V;Tob{at^]m45674:4Ttb|:0:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1=1cx71?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*dtkVhbbRmat^3\gjsi|VUe<=>?<5<\g|i2:2iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%i\7fnQmio]`jqY6Wje~byQPn1234929Wqey9=5lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T=Rm`uov\[k67896?2nw:2:ampgjl'noeSz|Pcovq[ujr{;%iecQlnu]wku)edmUiecQlnu-awfYeagUhbyQ>_bmvjqYXf9:;<1;1_b{l17=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(jziTnd`Pcov\5Zeh}g~TSc>?01>6:Z~hz<:0oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#o}l_ckm[fhsW8Uhcx`{_^l3456;=7ir9?5lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz bra\flhXkg~T=Rm`uov\[k67896=2Rv`r2:8gkredb%licQxr^ampwYwd|y9#oga_blw[qiw'kfoSoga_blw+firf}U;?55lnu`oo*abfV}ySn`{r^roqv4(j`dToczPtnr,fibXj`dTocz cnwmpZ74j2iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_0]qp6><kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'je~byQ=3c9`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V8T~y=7;blwfim(oldT{\7fQlnup\tist:&hbbRmat^vlt*dklVhbbRmat.alqkrX;:h0oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]0[wr402iexobd/fgm[rtXkg~yS}bzs3-amkYdf}U\7fc}!mle]amkYdf}%hcx`{_51a?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*eh}g~T8R|{399`jqdkc&mnbRy}_blwvZvk}z8$nd`Pcov\pjv(jenTnd`Pcov,gjsi|V?8n6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!lotlw[0Yu|:20oczmlj-dakYpzViex\7fQ\7fltq1+goiWjd\7fSya\7f/cng[goiWjd\7f#naznu]57g=df}hgg"ijn^uq[fhszVzgy~< bhl\gkrX|fz$najPbhl\gkr(kf\7fexR8Pru63?fhsjea$kh`Pws]`jqtXxe\7fx>"lfn^ampZrhx&hghRlfn^amp*eh}g~TSc>?01>2:16<kg~i`f!heo]tvZei|{U{`x}=/ckm[fhsW}e{#obk_ckm[fhs'je~byQPn1234949<91hbylck.efjZquWjd\7f~R~cur0,flhXkg~Txb~ bmf\flhXkg~$ob{at^]m45674:4?<6matcnh+bciW~xTocz}_qnvw7)eagUhbyQ{oq-ahaYeagUhby!lotlw[Zh789:783:?;blwfim(oldT{\7fQlnup\tist:&hbbRmat^vlt*dklVhbbRmat.alqkrXWg:;<=2:>528gkredb%licQxr^ampwYwd|y9#oga_blw[qiw'kfoSoga_blw+firf}UTb=>?0=4=`>bf|hUhcx`{<1<e?agsiVidycz31;2=`>bf|hUhcx`{<0<2<>bbj|mT~iQ\7fnup\tist9Vx7<3?7;egaqbYulVzex\7fQ\7fltq2[w:66820hhlzg^pg[uhszVzgy~?Pr=0=5==cmk\7flS\7fjPpovq[ujr{8Uy0>0>8:fffpaXzmU{by|Ppmwp5Zt;<7;37ikmuf]q`Zvi|{U{`x}>_s>6:4g<llh~kR|k_qlwvZvk}z;T~1850?3;?ace}nUyhR~ats]shpu6W{6=2<<4dd`vcZtcWyd\7f~R|30?31?ace}nUyhR~ats]q8486:2nnnxiPre]sjqtXz585=?5kecwd[wbXxg~yS\7f2<>008``droVxoS}`{r^p?0;753moiyjQ}d^rmpwYu4<4:86jjbte\vaYwf}xT~1850?31?ace}nUyhR~ats]q8386:2nnnxiPre]sjqtX\7f5:5=?5kecwd[wbXxg~ySz2>>008``droVxoS}`{r^u?6;753moiyjQ}d^rmpwYp4:4:>6jjbte\vaYwf}xT{1:1139gags`W{nT|cz}_v>6:42<llh~kR|k_qlwvZq;>3:5=?5kecwd[wbXxg~ySz29>0:8``droV}yS}`{r^roqv7X\7f5:5=55kecwd[rtXxg~yS}bzs0]t848602nnnxiPws]sjqtXxe\7fx=Ry32?3;?ace}nU|~R~ats]shpu6W~682<64dd`vcZquWyd\7f~R~cur3\s929911oio{h_vp\tkruWyf~\7f<Qx<4<2e>bbj|mT{\7fQ\7fnup\tist9V}7:7>1199gags`W~xT|cz}_qnvw4Yp4?4:46jjbte\swYwf}xT|a{|2^u?4;7?3moiyjQxr^rmpwYwd|y9Sz2>>0:8``droV}yS}`{r^roqv4X\7f585=55kecwd[rtXxg~yS}bzs3]t868602nnnxiPws]sjqtXxe\7fx>Ry34?3;?ace}nU|~R~ats]shpu5W~6>2<o4dd`vcZquWyd\7f~R~cur0\s90=87;37ikmuf]tvZvi|{U{`x}=_v>5:44<llh~kRy}_qlwvZt;87;97ikmuf]tvZvi|{Uy0<0>2:fffpaX\7f{U{by|Pr=0=57=cmk\7flSz|Ppovq[w:46880hhlzg^uq[uhszVx783?=;egaqbYpzVzex\7fQ}<4<20>bbj|mT{\7fQ\7fnup\v90=87;97ikmuf]tvZvi|{Uy0;0>2:fffpaX\7f{U{by|Pw=2=57=cmk\7flSz|Ppovq[r:66880hhlzg^uq[uhszV}7>3?=;egaqbYpzVzex\7fQx<2<26>bbj|mT{\7fQ\7fnup\s9299;1oio{h_vp\tkruW~6>2<:4dd`vcZquWyd\7f~Ry36;2=57=cmk\7flSz|Ppovq[r:16?1oec2?>79gmk:66?1oec2=>79gmk:46?1oec2;>79gmk:26?1oec29>99gmk:0294=7iga<6<4?air|5:5;6j`uu>2:2=cg|~7>394dnww86803me~x1:17:flqq:26>1ocxz36?;8`jss4>0;2:5kotv?3;3<mdz\7fu?64fhdl[bcim{k\7fc\7fQy2^0/$Fiumnoe,: >.16j[lv49?1mekaPgdlfvdrhzV|9S?Qns0;8bidkc&KGXR\K_ECWEZEH]G^T<<74fm`oo*GK\VXOSIO[A^ALQKRX9830jalck.COPZTCWMK_MRM@UOV\64?<nehgg"OCT^PG[AGSIVIDYCZP30;8bidkc&KGXR\K_ECWEZEH]G^T8<74fm`oo*GK\VXOSIO[A^ALQKRX=830jalck.COPZTCWMK_MRM@UOV\24?<nehgg"OCT^PG[AGSIVIDYCZP70;8bidkc&KGXRY]_ECWEZEH]G^T=<74fm`oo*GK\V]YSIO[A^ALQKRX:830jalck.COPZQUWMK_MRM@UOV\74?<nehgg"OCT^UQ[AGSIVIDYCZP40;8bidkc&KGXRY]_ECWEZEH]G^T9<74fm`oo*GK\V]YSIO[A^ALQKRX>830jalck.COPZQUWMK_MRM@UOV\3<=adkf`#C??9:dofim(F8;27kbmlj-M57?<nehgg"@>389ehgjl'G;?56hcbmi,J43>3ofi`f!A17;8bidkc&D:;45ilcnh+K7?12lgnae N0;:?cjedb%E>=74fm`oo*H5911m`obd/O4;?cjedb%E;55ilcnh+K>6=2lgnae WS]GEQGXKF_EXR>i;gnahn)Xf9:;>1>1119ehgjl'Vd;<=<30?3e?cjedb%Tb=>?2=3=55=adkf`#R`?010?5;7a3ofi`f!Pn1236949991m`obd/^l3454;:7;m7kbmlj-\j567:595==5ilcnh+Zh78987?3?i;gnahn)Xf9:;>1:1119ehgjl'Vd;<=<34?3e?cjedb%Tb=>?2=7=55=adkf`#R`?010?1;7a3ofi`f!Pn1236909991m`obd/^l3454;>7;m7kbmlj-\j567:5=5==5ilcnh+Zh78987;3?i;gnahn)Xf9:;?1<1f:dofim(Wg:;<>2<>g9ehgjl'Vd;<==34?d8bidkc&Ue<=><<4<e?cjedb%Tb=>?3=4=b>`kjea$Sc>?06>1:c=adkf`#R`?015?7;`<nehgg"Qa0124818a3ofi`f!Pn1233939n2lgnae _o2342:16;>0jalck.aoohic'{ns#@v`r^]m4567W[oxyaz>259ehgjl'jf`abj rez,I}iuWVd;<=?PRdqvhq75<2lgnae cminka)ulq%Ftb|P_o2347YUmz\7fgx<<;;gnahn)ddbgdh"|kx.O{kwYXf9:;?R\jstnw572<nehgg"mcklmg+wb\7f'Drd~RQa0127[Wct}e~:>95ilcnh+fjlefn$~iv Mymq[Zh789?T^h}zlu310>`kjea$oaeboe-q`})JpfxTSc>?06]Qavsk|88?7kbmlj-`hnkhl&xot"Cwos]\j5670VXn\7fxb{1308bidkc&igg`ak/sf{+H~hzVUe<=??_Ym?4;443ofi`f!lljol`*tcp&Gsc\7fQPn1224Z^h484:>95ilcnh+fjlefn$~iv Mymq[Zh788;T^h}zlu310>`kjea$oaeboe-q`})JpfxTSc>?13]Qavsk|88?7kbmlj-`hnkhl&xot"Cwos]\j566:VXn\7fxb{20;8bidkc&igg`ak/sf{+UHSZVHT<<74fm`oo*ekcdeo#\7fjw/QLWVZDX9830jalck.aoohic'{ns#]@[R^@\64?<nehgg"mcklmg+wb\7f'YD_^RLP30;8bidkc&igg`ak/sf{+UHSZVHT8<74fm`oo*ekcdeo#\7fjw/QLWVZDX=830jalck.aoohic'{ns#]@[R^@\24g<nehgg"mcklmg+wb\7f'Vd;<<;30?3b?cjedb%h`fc`d.pg|*Yi89;>0<0>a:dofim(keafci!}dy-\j566=585=l5ilcnh+fjlefn$~iv _o2350:468k0jalck.aoohic'{ns#R`?007?0;7f3ofi`f!lljol`*tcp&Ue<=?:<4<2e>`kjea$oaeboe-q`})Xf9:::1>11`9ehgjl'jf`abj rez,[k679?6?2<o4fm`oo*ekcdeo#\7fjw/^l3472;87;j7kbmlj-`hnkhl&xot"Qa01068586i2lgnae cminka)ulq%Tb=>=8=2=5f=adkf`#nbdmnf,va~(xg~ySyc\7f<1<2g>`kjea$oaeboe-q`})wf}xTx`~31?3`?cjedb%h`fc`d.pg|*vi|{U\7fa}2=>0a8bidkc&igg`ak/sf{+uhszV~f|1=11b9ehgjl'jf`abj rez,tkruW}g{090>c:dofim(keafci!}dy-sjqtX|dz793?l;gnahn)ddbgdh"|kx.rmpwYsey6=2<l4fm`oo*ekcdeo#\7fjw/qlwvZrjxV::n6hcbmi,gimjgm%yhu!\7fnup\phvX98h0jalck.aoohic'{ns#}`{r^vntZ46j2lgnae cminka)ulq%{by|Ptlr\74d<nehgg"mcklmg+wb\7f'yd\7f~Rzbp^62f>`kjea$oaeboe-q`})wf}xTx`~P50`8bidkc&igg`ak/sf{+uhszV~f|R8>d:dofim(keafci!}dy-sjqtX|dzs0=0>d:dofim(keafci!}dy-sjqtX|dzs0<0>d:dofim(keafci!}dy-sjqtX|dzs0?0>d:dofim(keafci!}dy-sjqtX|dzs0>0>d:dofim(keafci!}dy-sjqtX|dzs090>d:dofim(keafci!}dy-sjqtX|dzs080>d:dofim(keafci!}dy-sjqtX|dzs0;0>c:dofim(keafci!}dy-sjqtX|dzsS=?l;gnahn)ddbgdh"|kx.rmpwYseyrT=<m4fm`oo*ekcdeo#\7fjw/qlwvZrjxqU9=n5ilcnh+fjlefn$~iv povq[qkwpV9:o6hcbmi,gimjgm%yhu!\7fnup\phv\7fW=;h7kbmlj-`hnkhl&xot"~ats]wiu~X=8i0jalck.aoohic'{ns#}`{r^vnt}Y1:=1m`obd/bnhijb(\7f{r$Aua}_^l3456XZly~`y?=4:dofim(keafci!xry-N|jtXWg:;<<Q]erwop4433ofi`f!lljol`*qup&Gsc\7fQPn1236ZTb{|f\7f=?:4fm`oo*ekcdeo#z|w/LzlvZYi89:8S_k|umv261=adkf`#nbdmnf,sw~(EqeySR`?016\V`urd};986hcbmi,gimjgm%|~u!Bxnp\[k678<UYi~{ct007?cjedb%h`fc`d.uq|*K\7fg{UTb=>?7^Pfwpjs9;>0jalck.aoohic'~xs#@v`r^]m456?W[oxyaz>239ehgjl'jf`abj wsz,I}iuWVd;<<>PXn>3:75<nehgg"mcklmg+rt\7f'Drd~RQa0133[]i;97;986hcbmi,gimjgm%|~u!Bxnp\[k6798UYi~{ct007?cjedb%h`fc`d.uq|*K\7fg{UTb=>>2^Pfwpjs9;>0jalck.aoohic'~xs#@v`r^]m4575W[oxyaz=189ehgjl'jf`abj wsz,TKRUWKU;=45ilcnh+fjlefn${\7fv POVQ[GY6901m`obd/bnhijb(\7f{r$\CZ]_C]15<=adkf`#nbdmnf,sw~(XG^YSOQ<189ehgjl'jf`abj wsz,TKRUWKU?=45ilcnh+fjlefn${\7fv POVQ[GY2901m`obd/bnhijb(\7f{r$\CZ]_C]55d=adkf`#nbdmnf,sw~(Wg:;=82?>0c8bidkc&igg`ak/vp{+Zh788?7=3?n;gnahn)ddbgdh"y}x.]m45724;4:m6hcbmi,gimjgm%|~u!Pn12219599h1m`obd/bnhijb(\7f{r$Sc>?14>7:4g<nehgg"mcklmg+rt\7f'Vd;<<;35?3b?cjedb%h`fc`d.uq|*Yi89;=0=0>a:dofim(keafci!xry-\j566>5>5=l5ilcnh+fjlefn${\7fv _o2361:768k0jalck.aoohic'~xs#R`?037?4;7f3ofi`f!lljol`*qup&Ue<=<7<1<2g>`kjea$oaeboe-tv})wf}xTx`~30?3`?cjedb%h`fc`d.uq|*vi|{U\7fa}2>>0a8bidkc&igg`ak/vp{+uhszV~f|1<11b9ehgjl'jf`abj wsz,tkruW}g{0>0>c:dofim(keafci!xry-sjqtX|dz783?l;gnahn)ddbgdh"y}x.rmpwYsey6>2<m4fm`oo*ekcdeo#z|w/qlwvZrjx5<5=o5ilcnh+fjlefn${\7fv povq[qkwW9;i7kbmlj-`hnkhl&}yt"~ats]wiuY69k1m`obd/bnhijb(\7f{r$|cz}_uos[77e3ofi`f!lljol`*qup&zex\7fQ{mq]05g=adkf`#nbdmnf,sw~(xg~ySyc\7f_53a?cjedb%h`fc`d.uq|*vi|{U\7fa}Q:1c9ehgjl'jf`abj wsz,tkruW}g{S;?k;gnahn)ddbgdh"y}x.rmpwYseyr7<3?k;gnahn)ddbgdh"y}x.rmpwYseyr7=3?k;gnahn)ddbgdh"y}x.rmpwYseyr7>3?k;gnahn)ddbgdh"y}x.rmpwYseyr7?3?k;gnahn)ddbgdh"y}x.rmpwYseyr783?k;gnahn)ddbgdh"y}x.rmpwYseyr793?k;gnahn)ddbgdh"y}x.rmpwYseyr7:3?l;gnahn)ddbgdh"y}x.rmpwYseyrT<<m4fm`oo*ekcdeo#z|w/qlwvZrjxqU:=n5ilcnh+fjlefn${\7fv povq[qkwpV8:o6hcbmi,gimjgm%|~u!\7fnup\phv\7fW:;h7kbmlj-`hnkhl&}yt"~ats]wiu~X<8i0jalck.aoohic'~xs#}`{r^vnt}Y29j1m`obd/bnhijb(\7f{r$|cz}_uos|Z06k2lgnae lnejgZgtWVd;<==31?]`}j7f3ofi`f!cofk`[duXWg:;<>2>>b{2f>`kjea$`bifc^cp[Zh78997=3bzt0a8bidkc&fdkdmPar]\j567;585Snw`1b9ehgjl'eelenQns^]m45644;4Ttb|>a:dofim(dfmboRo|_^l3455;:7ir=n5ilcnh+ii`ajUj\7fRQa0120868Xkpe:o6hcbmi,hjankVkxSR`?011?7;Y\7fg{;j7kbmlj-okbodWhyTSc>?02>0:f\7f6k2lgnae lnejgZgtWVd;<==34?]`}j7d3ofi`f!cofk`[duXWg:;<>2;>^zlv4g<nehgg"b`gha\evYXf9:;?1:1cx3`?cjedb%gcjgl_`q\[k678:6>2Rmvo0a8bidkc&fdkdmPar]\j567;5?5Sua}1`9ehgjl'eelenQns^]m45644<4hu<m4fm`oo*jho`iTm~QPn1237909Wjsd=n5ilcnh+ii`ajUj\7fRQa0120838Xpfx:m6hcbmi,hjankVkxSR`?011?2;e~9j1m`obd/mmdmfYf{VUe<=>8<0<\g|i6i2lgnae lnejgZgtWVd;<=931?az5g=adkf`#aahib]bwZYi89:<0<0cuu3`?cjedb%gcjgl_`q\[k678>692Rmvo0a8bidkc&fdkdmPar]\j567?585Sua}1`9ehgjl'eelenQns^]m45604;4hu<m4fm`oo*jho`iTm~QPn1233959Wjsd=n5ilcnh+ii`ajUj\7fRQa0124868Xpfx:m6hcbmi,hjankVkxSR`?015?7;e~9j1m`obd/mmdmfYf{VUe<=>8<5<\g|i6k2lgnae lnejgZgtWVd;<=934?]{kw7f3ofi`f!cofk`[duXWg:;<:2;>b{2g>`kjea$`bifc^cp[Zh789=793Qlyn3`?cjedb%gcjgl_`q\[k678>6>2Rv`r0c8bidkc&fdkdmPar]\j567?5?5ot?l;gnahn)kgnchSl}P_o2342:16Virc<m4fm`oo*jho`iTm~QPn1233909Wqey=l5ilcnh+ii`ajUj\7fRQa0124838dq;30jalck.nlcleXizU\7fa}Q\7fnup\vZbnnoU{mi2?>^azk7?<nehgg"b`gha\evYseyU{by|Pr^fjbcYwim6;2Rv`r358bidkc&fdkdmPar]wiuYwf}xT~Rjffg]sea:76js946hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<1<oqq4>3ofi`f!cofk`[duX|dzT|cz}_s]gmc`Xxhn7=3Qlyn0:?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;97Usc\7f<8;gnahn)kgnchSl}Ptlr\tkruW{UoekhPp`f?5;e~:11m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1?1ltv1=>`kjea$`bifc^cp[qkwWyd\7f~R|Pdhde[ugc4;4Tota=9:dofim(dfmboRo|_uos[uhszVxThdhi_qcg878Xpfx9;6hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<3<`}7><nehgg"b`gha\evYseyU{by|Pr^fjbcYwim692a{{289ehgjl'eelenQns^vntZvi|{UySigif^rb`959Wjsd>45ilcnh+ii`ajUj\7fRzbp^rmpwYuWmcmjR~nd=1=[}iu:>1m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1=1cx0;?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;;7f~x?74fm`oo*jho`iTm~Q{mq]sjqtXzVnbjkQ\7fae>0:iss9;30jalck.nlcleXizU\7fa}Q\7fnup\vZbnnoU{mi2;>^azk7?<nehgg"b`gha\evYseyU{by|Pr^fjbcYwim6?2Rv`r358bidkc&fdkdmPar]wiuYwf}xT~Rjffg]sea:36js946hcbmi,hjankVkxSyc\7f_qlwvZtXl`lmS}ok<5<oqq4>3ofi`f!cofk`[duX|dzT|cz}_s]gmc`Xxhn793Qlyn0:?cjedb%gcjgl_`q\phvXxg~yS\7fQkigd\tdb;=7Usc\7f<8;gnahn)kgnchSl}Ptlr\tkruW{UoekhPp`f?1;e~:11m`obd/mmdmfYf{V~f|R~ats]q[aoanVzjh1;1ltv1=>`kjea$`bifc^cp[qkwWyd\7f~R|Pdhde[ugc4?4Ttb|=8:dofim(dfmboRo|_uos[uhszVxThdhi_qcg838k}}827kbmlj-okbodWhyTx`~Ppovq[rYcaolT|lj30?]`}j4>3ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn7<3Qwos04?cjedb%gcjgl_`q\phvXxg~ySzQkigd\tdb;87ir>55ilcnh+ii`ajUj\7fRzbp^rmpwYpWmcmjR~nd=2=hpr512lgnae lnejgZgtW}g{S}`{r^u\`l`aWyko0<0Pcxm1=>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc484Ttb|=7:dofim(dfmboRo|_uos[uhszV}Thdhi_qcg848dq;20jalck.nlcleXizU\7fa}Q\7fnup\sZbnnoU{mi2>>mww6<=adkf`#aahib]bwZrjxVzex\7fQx_ekebZvfl585Snw`289ehgjl'eelenQns^vntZvi|{U|Sigif^rb`949Wqey>:5ilcnh+ii`ajUj\7fRzbp^rmpwYpWmcmjR~nd=0=g|4?3ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn7>3bzt3;8bidkc&fdkdmPar]wiuYwf}xT{Rjffg]sea:46Virc?74fm`oo*jho`iTm~Q{mq]sjqtX\7fVnbjkQ\7fae>0:Z~hz;=0jalck.nlcleXizU\7fa}Q\7fnup\sZbnnoU{mi2<>b{1<>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc4:4gyy<6;gnahn)kgnchSl}Ptlr\tkruW~UoekhPp`f?0;Ydqf827kbmlj-okbodWhyTx`~Ppovq[rYcaolT|lj34?]{kw403ofi`f!cofk`[duX|dzT|cz}_v]gmc`Xxhn783mv299ehgjl'eelenQns^vntZvi|{U|Sigif^rb`929d|~956hcbmi,hjankVkxSyc\7f_qlwvZqXl`lmS}ok<4<\g|i512lgnae lnejgZgtW}g{S}`{r^u\`l`aWyko080Pxnp13>`kjea$`bifc^cp[qkwWyd\7f~RyPdhde[ugc4<4hu?64fm`oo*jho`iTm~Q{mq]sjqtX\7fVnbjkQ\7fae>6:iss:01m`obd/mmdmfYf{V~f|R~ats]t[aoanVzjh181_ymq6==adkf`#aahib]bwZrjxVzex\7fQx_ekebZvfl5<5`xz>4:dofim(zyxnabj _o2346723ofi`f!}psgnka)Xf9:;?<?;;gnahn)ux{ofci!Pn123243<nehgg"|\7frdol`*Yi89:==<:4fm`oo*twzlgdh"Qa013650=adkf`#\7f~}elmg+Zh788?:=n5ilcnh+wvumdeo#}|jlncgwqg`m;;:m6hcbmi,vutbefn$~lcPre]fjZo6901m`obd/srqahic'{kfS{ocie]j5c=adkf`#\7f~}elmg+wcflVnjxlQyamkg[l7?3ofi`f!}psgnka)r{lxTi`~{y328bidkc&~c~`ak/dnlcle(MDZ_UR@@NSGD66=adkf`#yf}mnf,aii`aj%NA]ZV_OMMV@AXa8;m7kbmlj-wlwkhl&ogcjgl/SCN[@KW\PUb>=5ilcnh+qnuefn$iaahib-`5*bh}}Ub====0:dofim(|axfci!jlnejg*e6'me~xRg>193e?cjedb%\7fd\7fc`d.gokbod'j;$hb{{_h165c=adkf`#yf}mnf,aii`aj%h="j`uu]j33473ofi`f!{hsol`*ckgnch#n< dnww[l77;;:0jalck.vkvhic'lfdkdm c3-gkprXa8;3=k5ilcnh+qnuefn$iaahib-`6*bh}}Ub?8?i;gnahn)s`{gdh"kcofk`+f4(lf\7f\7fSd991d9ehgjl'}byabj emmdmf)d:&ndyyQf80a8bidkc&~c~`ak/dnlcle(kfg{=b{{1b9ehgjl'}byabj emmdmf)dgdz9cxz>f:dofim(|axfci!ilnejg*@RDEUECC\JG308bidkc&~c~`ak/gnlcle(N\FGSCAARDE\m47b3ofi`f!{hsol`*`kgnch#_OB_GWOHZo5;2lgnae tipnka)adfmbo"m`mq3,`jssW`;;??=4fm`oo*rozdeo#kb`gha,gjkw9&ndyyQf10:16>`kjea$xe|boe-ehjank&ida}? dnww[l52:;1m`obd/ujqijb(neelen!lolr2+air|Vc<:??4fm`oo*rozdeo#kb`gha,gjkw9&ndyyQf8318bidkc&~c~`ak/gnlcle(kfg{>"j`uu]j5555;2lgnae tipnka)adfmbo"m`mq0,`jssW`;:4?<4fm`oo*rozdeo#kb`gha,gjkw:&ndyyQf3401?cjedb%\7fd\7fc`d.dokbod'jef|?!kotv\m20592lgnae tipnka)adfmbo"m`mq0,`jssW`2:i6hcbmi,pmtjgm%m`bifc.aliuYa}ef:=h5ilcnh+qnuefn$jaahib-`khvXn|fg><m4fm`oo*rjxVzex\7fQ}_ekebZvfl5:5=n5ilcnh+qkwWyd\7f~R|Pdhde[ugc484:o6hcbmi,phvXxg~yS\7fQkigd\tdb;:7;m7kbmlj-wiuYwf}xT~Rjffg]sea:56Vx\7f=n5ilcnh+qkwWyd\7f~R|Pdhde[ugc4:4:j6hcbmi,phvXxg~yS\7fQkigd\tdb;;7Uyx<m4fm`oo*rjxVzex\7fQ}_ekebZvfl5>5=k5ilcnh+qkwWyd\7f~R|Pdhde[ugc4=4T~y?l;gnahn)seyU{by|Pr^fjbcYwim6>2<h4fm`oo*rjxVzex\7fQ}_ekebZvfl5?5S\7fz>c:dofim(|dzT|cz}_s]gmc`Xxhn7:3?i;gnahn)seyU{by|Pr^fjbcYwim6=2R|{1b9ehgjl'}g{S}`{r^u\`l`aWyko0=0>c:dofim(|dzT|cz}_v]gmc`Xxhn7=3?l;gnahn)seyU{by|Pw^fjbcYwim692<h4fm`oo*rjxVzex\7fQx_ekebZvfl585S\7fz>c:dofim(|dzT|cz}_v]gmc`Xxhn7?3?i;gnahn)seyU{by|Pw^fjbcYwim682R|{1b9ehgjl'}g{S}`{r^u\`l`aWyko090>f:dofim(|dzT|cz}_v]gmc`Xxhn783Q}t0a8bidkc&~f|R~ats]t[aoanVzjh1;11g9ehgjl'}g{S}`{r^u\`l`aWyko080Pru3`?cjedb%\7fa}Q\7fnup\sZbnnoU{mi29>0d8bidkc&~f|R~ats]t[aoanVzjh181_sv2<>`kjea${}|jmnf,VDKX_[UNB<:4ftnob>oijea$~iQ}su]ef45<aghgg"|k_sqw[lhs4:4:<6gabmi,vaYu{}Uyij?<;hlahn)pzVxxxRgat=1=57=nfkf`#z|Prrv\mkrX98:0eclck.uq[wusW{olh6cjmcnh+AIR\V:o7`kbbmi,@JSSW8n0ahcmlj-GKPRX:m1fi`lck.FLQQY4l2gnaobd/EMVPZ2c3dofnae DNWW[0b<elgi`f!KOTV\2a=jmdhgg"J@UU]455=jmdhgg"J@UU]j858682gnaobd/EMVPZo;97;;7`kbbmi,@JSSW`692<>4mdoahn)CG\^Te1=1119nahdkc&NDYYQf<5<24>kbekf`#IAZT^k?1;773dofnae DNWW[l:168:0ahcmlj-GKPRXa5=5?n5bel`oo*gtqgiTjdh`_9];[44?WocmcRijndpbpjtX~;U9Su}{_0]`kwcnfz~:86cjmcnh+qkwW{kfS\7fjPeo36?hcjjea$x`~Pr`o\vaYbf820c{k}fmmte>vugnUna}zv159svjaXmdz\7fuRzgrdqk8586<2zycjQjmqvz[qnumzb7=3?;;qplcZcjx}sTxe|jsi>1:42<x{elShc\7ftx]wlwct`595=95\7frne\ahvsqV~c~h}g<5<20>vugnUna}zv_ujqavn;=7;=7}|`g^gntq\7fX|axn\7fe29:1<20>vugnUna}zv_ujqavn;>7;i7}|`g^gntq\7fX|axn\7feQnsrgqp9699k1{~biPelrw}ZrozlycSl}|esv?5;7e3yxdkRkbpu{\pmtb{aUj\7f~k}t=0=5g=wzfmTi`~{y^vkv`uoWhyxi\7fz33?3a?uthoVof|ywPtipfwmYf{zoyx1:11c9svjaXmdz\7fuRzgrdqk[dutm{~793?k;qplcZcjx}sTxe|jsi]bwvcu|5<1<3?m;qplcZcjx}sTxe|jsi]bwvcu|5<5=o5\7frne\ahvsqV~c~h}g_ogdeqc;87;i7}|`g^gntq\7fX|axn\7feQaefcwa9799k1{~biPelrw}ZrozlycSckhaug?6;7e3yxdkRkbpu{\pmtb{aUeijo{e=1=5g=wzfmTi`~{y^vkv`uoWgolmyk34?3a?uthoVof|ywPtipfwmYimnk\7fi1;11e9svjaXmdz\7fuRzgrdqk[kc`i}o7:7>11c9svjaXmdz\7fuRzgrdqk[kc`i}o7:374psmd[cskd890|\7fah_gwohZrozlyc0=0>3:rqkbYa}efTxe|jsi>2:45<x{elSk{cl^vkv`uo4;4:?6~}of]eqijX|axn\7fe2<>018twi`Wo\7fg`Rzgrdqk8186;2zycjQiumn\pmtb{a6>2<;4psmd[cskdV~c~h}g<783:45<x{elSk{cl^vkv`uo4?4:m6~}of]eqijX|axn\7feQnsrgqp9699h1{~biPftno[qnumzbTm~}jru>2:4g<x{elSk{cl^vkv`uoWhyxi\7fz32?3b?uthoVl~`aQ{hsgplZgt{lx\7f0>0>a:rqkbYa}efTxe|jsi]bwvcu|5>5=l5\7frne\bpjkW}byi~fParqfvq:268i0|\7fah_gwohZrozlycSl}|esv?2?699h1{~biPftno[qnumzbTm~}jru>5:4g<x{elSk{cl^vkv`uoWgolmyk30?3b?uthoVl~`aQ{hsgplZhboh~n0<0>a:rqkbYa}efTxe|jsi]mabgsm585=l5\7frne\bpjkW}byi~fPndebp`:468k0|\7fah_gwohZrozlycSckhaug?0;7f3yxdkRhzlm]wlwct`Vdnklzj<4<2g>vugnUmyabPtipfwmYimnk\7fi1850?3b?uthoVl~`aQ{hsgplZhboh~n0;0k;scn[wc`g|~Tic84re]`hn773{nThlzn_bmvjq:768:0~iQkauc\gjsi|5;5==5}d^fbpdYdg|d\7f0?0>0:pg[agsiVidycz33?33?wbXlh~jSnaznu>7:46<zmUomyoPcnwmp939991yhRjnt`]`kphs4?4:>6|k_ecweZeh}g~7;7>1119q`Zbf|hUhcx`{<6<6?wbXmg<0~iQ}su18vvr>3|doi\7fhcov78rdjnl?1|~Rolk79tvZekc8:0{\7fQkauc\gjsi|5:5==5xr^fbpdYdg|d\7f0<0>0:uq[agsiVidycz32?33?rtXlh~jSnaznu>0:46<\7f{UomyoPcnwmp929991|~Rjnt`]`kphs4<4:<6y}_ecweZeh}g~7:3?=;vp\`drfWje~by28:1<24>quWmk\7fmRm`uov?3;3<\7f{Unb;5xr^ppp2=\7fk;|{;=?>;Âɾ¹Ã¸ÐÄÍ´Ì°²Þ·³»g8Õǹ×Ä·ÝηÄγÅÄ\7fCDugc<2JKt<:?:G81>4}T>90:?i4ma;3064>4j3=<58ua12`95>h6;j0?7)?<a;300>{T=o0:?i4ma;3064>4j3=<585k15294?7=9rY=<7?<d;`b>455919i6:965:tW54c=83;1=7?66zQ54?74l3hj6<==191a>21>=2.:>84l2:&g0?27j2h:8=4?:7296?3fsS><6ou>3;05>41=9?0:97?;:0090?4b2;i1>i4r$03e>4273A;9>6*>388113=n9=>1<75f3g;94?=n;oh1<75f15194?=n<931<75f3dd94?=n;ok1<75f3gd94?=n9=81<75f41c94?=n;ji1<7*k6;1`f>hc=3:07d=la;29 a0=;jh0bi;51:9j7f?=83.o:7=lb:lg1?4<3`9h47>5$e497fd<fm?1?65f3b594?"c>39hn6`k5;68?l5d>3:1(i853b`8ja3==21b?n;50;&g2?5dj2do9784;h07f?6=,m<1>9o4ne794>=n:=31<7*k6;07e>hc=3;07d<;8;29 a0=:=k0bi;52:9j611=83.o:7<;a:lg1?5<3`8?:7>5$e4961g<fm?1865f25794?"c>38?m6`k5;78?l43<3:1(i8525c8ja3=>21b>9=50;&g2?43i2do9794;h1f`?6=,m<1?hm4ne794>=n;lh1<7*k6;1fg>hc=3;07d=ja;29 a0=;li0bi;52:9j7`?=83.o:7=jc:lg1?5<3`9n47>5$e497`e<fm?1865f3d594?"c>39no6`k5;78?l5b>3:1(i853da8ja3=>21b?h;50;&g2?5b<2do97>4;h1f7?6=,m<1?h:4ne795>=n;l81<7*k6;1f0>hc=3807d=j1;29 a0=;l>0bi;53:9j7`6=83.o:7=j4:lg1?2<3`9oj7>5$e497`2<fm?1965f3eg94?"c>39n86`k5;48?l5cl3:1(i853ea8ja3=821b?il50;&g2?5ck2do97?4;h1ge?6=,m<1?im4ne796>=n;m31<7*k6;1gg>hc=3907d=k8;29 a0=;mi0bi;54:9j7a1=83.o:7=kc:lg1?3<3`9o:7>5$e497ae<fm?1:65f3e694?"c>39o?6`k5;28?l5c:3:1(i853e18ja3=921b?i?50;&g2?5c;2do97<4;h1g4?6=,m<1?i=4ne797>=n;jl1<7*k6;1g7>hc=3>07d=le;29 a0=;m90bi;55:9j7fb=83.o:7=k3:lg1?0<3`9h87>5$e497f5<fm?1<65f3b094?"c>39h?6`k5;38?l5d93:1(i853b18ja3=:21b?n>50;&g2?5d;2do97=4;h1ab?6=,m<1?n=4ne790>=n;ko1<7*k6;1`7>hc=3?07d=md;29 a0=;j90bi;56:9l56`=831d?kk50;9l603=831d?km50;9l56c=831d?ol50;9l7cb=831d?l?50;9l7ge=831d?i;50;9l65g=83.o:7<?9:lg1?6<3f8;47>5$e4965?<fm?1=65`41:94?"c>3>;;6`k5;28?j27>3:1(i854158ja3=921d8=;50;&g2?27?2do97<4;n630?6=,m<18=94ne797>=h<991<7*k6;633>hc=3>07b:?2;29 a0=<9=0bi;55:9l057=83.o:7:?7:lg1?0<3f>;<7>5$e49051<fm?1;65`24694?"c>38>?6`k5;28?j42:3:1(i852418ja3=921d>8?50;&g2?42;2do97<4;n064?6=,m<1>8=4ne797>=h:=l1<7*k6;067>hc=3>07b<;e;29 a0=:<90bi;55:9l61b=83.o:7<:3:lg1?0<3f8?o7>5$e49605<fm?1;65`3g:94?"c>39m;6`k5;28?j5a>3:1(i853g58ja3=921d?k;50;&g2?5a?2do97<4;n1e0?6=,m<1?k94ne797>=h;o91<7*k6;1e3>hc=3>07b=i2;29 a0=;o=0bi;55:9l7c7=83.o:7=i7:lg1?0<3f9m<7>5$e497c1<fm?1;65m13294??d28?<6<8m{[64>45|l3886<?5118e>`<d28l1>=4>a;3a>4e=9009n7?k:0:95`<5?38j6p*>1g8112=O9;80(9>k:52`?l76?3:17d?>a;29?l74;3:17d??d;29?l7513:17dk7:18'`3<b?2do97>4;hg5>5<#l?0n;6`k5;38?lc2290/h;4j7:lg1?4<3`o?6=4+d78f3>hc=3907dk<:18'`3<b?2do97:4;hg1>5<#l?0n;6`k5;78?lc6290/h;4j7:lg1?0<3`=m6=4+d784a>hc=3:07d9k:18'`3<0m2do97?4;h5`>5<#l?0<i6`k5;08?l1e290/h;48e:lg1?5<3`=j6=4+d784a>hc=3>07d96:18'`3<0m2do97;4;h5;>5<#l?0<i6`k5;48?l10290/h;48e:lg1?1<3`;;57>5$e4955><fm?1<65f11594?"c>3;;46`k5;38?l77>3:1(i8511:8ja3=:21b==;50;&g2?7702do97=4;h330?6=,m<1==64ne790>=n9991<7*k6;33<>hc=3?07d??2;29 a0=9920bi;56:9j557=83.o:7??0:lg1?6<3`lm6=4+d78245=il<0:76gie;29 a0=99:0bi;52:9jba<72-n=6<>?;of6>6=<aoi1<7*k6;334>hc=3>07dhm:18'`3<6891eh84:;:kee?6=,m<1==>4ne792>=nn00;6)j9:g:8ja3=821bj:4?:%f5>c><fm?1=65ff783>!b12o20bi;52:9jb0<72-n=6k64ne797>=nn=0;6)j9:g:8ja3=<21bj>4?:%f5>c><fm?1965ff383>!b12o20bi;56:9jb5<72-n=6hh4ne794>=nml0;6)j9:dd8ja3=921bii4?:%f5>``<fm?1>65feb83>!b12ll0bi;53:9jag<72-n=6hh4ne790>=nmh0;6)j9:dd8ja3==21bi44?:%f5>``<fm?1:65fe183>!b12ml0bi;50:9j``<72-n=6ih4ne795>=nlm0;6)j9:ed8ja3=:21bhn4?:%f5>a`<fm?1?65fdc83>!b12ml0bi;54:9j`d<72-n=6ih4ne791>=nl00;6)j9:ed8ja3=>21d:94?::m57?6=3f>?6=44o7094?=h><0;66a>2983>>ifm3:17b?=1;29?j242900ci<50;9l575=831dn:4?::mg<?6=3fl:6=44o31b>5<#l?09?45ad483?>i5;10;6)j9:31:?kb22810c?=8:18'`3<5;01eh84=;:m173<72-n=6?=6;of6>6=<g;9>6=4+d7817<=il<0?76a=3583>!b12;927cj::498k754290/h;4=389m`0<132e98?4?:%f5>7263gn>6=54o363>5<#l?098<5ad482?>i5;o0;6)j9:362?kb22;10c?=j:18'`3<5<81eh84<;:m17a<72-n=6?:>;of6>1=<g;9h6=4+d78104=il<0>76a=3c83>!b12;>:7cj::798k775290/h;4=109m`0<732e9==4?:%f5>7763gn>6<54o32e>5<#l?09=<5ad481?>i58l0;6)j9:332?kb22:10c?>k:18'`3<5981eh84;;:m14f<72-n=6??>;of6>0=<g;:i6=4+d78154=il<0=76a=1`83>!b12;;27cj::198k77?290/h;4=189m`0<632e9=:4?:%f5>77>3gn>6?54o335>5<#l?09=45ad480?>i59<0;6)j9:33:?kb22=10c??;:18'`3<5901eh84:;:m156<72-n=6??6;of6>3=<g;896=4+d78164=il<0;76a=2183>!b12;8:7cj::098k77a290/h;4=209m`0<532e9=h4?:%f5>7463gn>6>54o33g>5<#l?09><5ad487?>i59j0;6)j9:302?kb22<10c??m:18'`3<5:81eh849;:m41?6=,m<1;95ad483?>i0;3:1(i85759m`0<632e<>7>5$e4931=il<0976a81;29 a0=?=1eh84<;:m44?6=,m<1;95ad487?>i1n3:1(i85759m`0<232e=i7>5$e4931=il<0=76a>3383>!b1289:7cj::198k457290/h;4>309m`0<632e:>k4?:%f5>4563gn>6?54o00f>5<#l?0:?<5ad480?>i6:m0;6)j9:012?kb22=10c<<l:18'`3<6;81eh84:;:m26g<72-n=6<=>;of6>3=<g88j6=4+d78274=il<0<76a=2`83>!b12;827cj::198k74?290/h;4=289m`0<632e9>:4?:%f5>74>3gn>6?54o305>5<#l?09>45ad480?>i5:<0;6)j9:30:?kb22=10c?<;:18'`3<5:01eh84:;:m166<72-n=6?<6;of6>3=<g?n1<7*k6;4`?kb22910c;l50;&g2?0d3gn>6<54o7c94?"c>3<h7cj::398k3?=83.o:78l;of6>6=<g?21<7*k6;4`?kb22=10c;950;&g2?0d3gn>6854o7494?"c>3<h7cj::798k755290/h;4=309m`0<732e9?=4?:%f5>7563gn>6<54o30e>5<#l?09?<5ad481?>i5:l0;6)j9:312?kb22:10c?<k:18'`3<5;81eh84;;:m16f<72-n=6?=>;of6>0=<g;8i6=4+d78174=il<0=76a6a;29 a0=101eh84?;:m:<?6=,m<1545ad482?>i>?3:1(i85989m`0<532e2:7>5$e49=<=il<0876a65;29 a0=101eh84;;:m:0?6=,m<1545ad486?>i>;3:1(i85989m`0<132e2>7>5$e49=<=il<0<76a>1783>!b128;>7cj::198k473290/h;4>149m`0<632e:=>4?:%f5>4723gn>6?54o031>5<#l?0:=85ad480?>i6980;6)j9:036?kb22=10c<??:18'`3<69<1eh84:;:m24c<72-n=6<?:;of6>3=<g8:n6=4+d78250=il<0<76l<a383>1<729q/=<h5b49K574<@89=7E::;h42>5<<am=1<75f4983>>i68h0;66sm3`f94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa52g=8391<7>t$03e>4523A;9>6F>379j1g<722ch<7>5;nf2>5<<uk;8;7>51;294~"69o0i56F>239K560<gk21<75rb06g>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd61o0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa5f>=8391<7>t$03e>4523A;9>6F>379j1g<722ch<7>5;nf2>5<<uk;nj7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm14394?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn<=7:182>5<7s-;:j7?=4:J267=O9:<0ci=50;9~f6g1290?6=4?{%32b?d23A;9>6F>379K00=n>80;66gk7;29?l2?2900c<>n:188yg5f<3:197>50z&25c<e>2B:>?5G1248L13<a?;1<75f4`83>>oc?3:17d:7:188k46f2900qo=n7;291?6=8r.:=k4m6:J267=O9:<0D9;4i7394?=n<h0;66gk7;29?l2?2900c<>n:188yg5fm3:197>50z&25c<e<2B:>?5G1248m37=831b8l4?::k6a?6=3`>36=44o02b>5<<uk9jj7>55;294~"69o0i86F>239K560<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo=ma;297?6=8r.:=k4l5:J267=#jo0jh6F>379jfg<722cio7>5;nf2>5<<uk9i47>53b83>5}]<>0=wl4m:36960<503826p*>1g8204=O9;80enj50;9jg`<722cjj7>5;h`3>5<<a88=6=44i004>5<<a<i1<75f5e83>>o69j0;66g>1e83>>o413:1(i85399m`0<732c8;7>5$e497==il<0:76g<6;29 a0=;11eh84=;:k01?6=,m<1?55ad480?>o4<3:1(i85399m`0<332c8?7>5$e497==il<0>76g<2;29 a0=;11eh849;:k75?6=,m<18=5ad483?>o4n3:1(i85419m`0<632c8i7>5$e4905=il<0976g<d;29 a0=<91eh84<;:k0g?6=,m<18=5ad487?>o4j3:1(i85419m`0<232c8m7>5$e4905=il<0=76g78;29 a0=0>1eh84?;:k;2?6=,m<14:5ad482?>o?=3:1(i85869m`0<532c387>5$e49<2=il<0876g73;29 a0=0>1eh84;;:k;6?6=,m<14:5ad486?>o?93:1(i85869m`0<132c3<7>5$e49<2=il<0<76g61;29 a0=191eh84?;:k;b?6=,m<15=5ad482?>o?m3:1(i85919m`0<532c3h7>5$e49=5=il<0876g7c;29 a0=191eh84;;:k;f?6=,m<15=5ad486?>o?i3:1(i85919m`0<132c357>5$e49=5=il<0<76a>1983>>i6900;66a>0c83>>i68j0;66an3;29 a0=i;1eh84?;:mb5?6=,m<1m?5ad482?>if83:1(i85a39m`0<532e2j7>5$e49e7=il<0876a6e;29 a0=i;1eh84;;:m:`?6=,m<1m?5ad486?>i>k3:1(i85a39m`0<132e2n7>5$e49e7=il<0<76anc;29 a0=ik1eh84?;:mbe?6=,m<1mo5ad482?>if13:1(i85ac9m`0<532ej47>5$e49eg=il<0876an7;29 a0=ik1eh84;;:mb2?6=,m<1mo5ad486?>if=3:1(i85ac9m`0<132ej87>5$e49eg=il<0<76sm3`:94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa7d?=83?1<7>t$03e>g2<@8897E?<6:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e;hk1<7;50;2x 47a2k>0D<<=;I302>o193:17d:n:188m0c=831b854?::m24d<722wi?ll50;794?6|,8;m6o:4H001?M74>2c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm3`a94?3=83:p(<?i:c68L4453A;8:6g91;29?l2f2900e8k50;9j0=<722e:<l4?::\7fa5a5=83?1<7>t$03e>g2<@8897E?<6:&ab?6<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo?k5;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9jn1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?k9;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9m=1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3`a?6==3:1<v*>1g8a2>N6:;1C=>84$cd96>o193:17d:n:188ma1=831b854?::m24d<722wi=nh50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7c93:197>50z&25c<e<2B:>?5G1248 g`=82c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm1b`94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg7dk3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`2fa<72;0;6=u+10d9g6=O9;80(oh52:J273=njk0;66ak1;29?xd6jj0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa7=7=83?1<7>t$03e>f?<@8897)li:228L4513`hi6=44ica94?=njm0;66gme;29?jb62900qo?l0;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th:nk4?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb0a0>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?l2;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa5f0=83>1<7>t$03e>fg<@8897E?<6:k6f?6=3`==6=44i03a>5<<gm;1<75rb0a6>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd6k00;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa5=3=83?1<7>t$03e>g2<@8897E?<6:&ab?6<a?;1<75f4`83>>o2m3:17d:7:188k46f2900qo?77;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9>l1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?7b;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9131<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3;4?6==3:1<v*>1g8a2>N6:;1C=>84$cd96>o193:17d:n:188ma1=831b854?::m24d<722wi=5?50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7?;3:197>50z&25c<e<2B:>?5G1248 g`=82c==7>5;h6b>5<<a<o1<75f4983>>i68h0;66sm16f94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg70m3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`22c<72;0;6=u+10d9g6=O9;80(oh52:J273=njk0;66ak1;29?xd6>l0;694?:1y'54`=kh1C=?<4H015?l3e2900e:850;9j54d=831dh<4?::\7fa533=8381<7>t$03e>f5<@8897)li:29K560<akh1<75`d083>>{e9>81<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f41629086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th:;84?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e9>>1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?88;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th:;:4?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb05a>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?ia;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9oi1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3e0?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e:9:1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c3ea?6==3:1<v*>1g8a0>N6:;1C=>84$cd94>o193:17d:n:188m0c=831b854?::m24d<722wi=k;50;794?6|,8;m6o:4H001?M74>2.ij7>4i7394?=n<h0;66g:e;29?l2?2900c<>n:188yg7a>3:197>50z&25c<e>2B:>?5G1248 g`=:2c==7>5;h6b>5<<am=1<75f4983>>i68h0;66sm1g:94?3=83:p(<?i:c68L4453A;8:6*mf;28m37=831b8l4?::k6a?6=3`>36=44o02b>5<<uk;m>7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm1g194?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn<k;:181>5<7s-;:j7m<;I316>"en380D<=9;h`a>5<<gm;1<75rb0g0>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo?m3;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3f3?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl>e783>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f4cf290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c3f=?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e9ln1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f4cd29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th:j=4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e:1>1<7:50;2x 47a2j20D<<=;%`e>77<@89=7dlm:188mge=831bni4?::m`5?6=3th8>44?:283>5}#98l1=>;4H001?M74>2c>n7>5;ha3>5<<gm;1<75rb234>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd4<=0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn>;j:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`20`<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm15c94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg41>3:187>50z&25c<e;2B:>?5G1248m37=831b9h4?::k7<?6=3f;;m7>5;|`11c<72=0;6=u+10d9f6=O9;80D<=9;h42>5<<a<o1<75f4983>>i68h0;66sm15`94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>o?:180>5<7s-;:j7m:;I316>"en3?0D<=9;h`a>5<<aki1<75`d083>>{e;1>1<7;50;2x 47a2j30D<<=;%`e>66<@89=7dlm:188mge=831bni4?::kaa?6=3fn:6=44}c157?6=<3:1<v*>1g8`3>N6:;1/nk48;I302>oej3:17dll:188mgb=831dh<4?::\7fa6g?=83>1<7>t$03e>g5<@8897E?<6:J71>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th94;4?:583>5}#98l1o55G1308 g`=:81C=>84ic`94?=njj0;66gmd;29?je62900qo=9f;291?6=8r.:=k4l9:J267=#jo09>6F>379jfg<722cio7>5;h`g>5<<ako1<75`d083>>{e9==1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f42?29096=4?{%32b?e43A;9>6*mf;08L4513`hi6=44oe394?=zj8?<6=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg72<3:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`225<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<;j:186>5<7s-;:j7l;;I316>N6;?1/nk4?;h42>5<<a=k1<75f5d83>>o303:17b??a;29?xd6=j0;684?:1y'54`=j=1C=?<4H015?!da291b:<4?::k7e?6=3`?n6=44i5:94?=h99k1<75rb355>5<3290;w)?>f;`0?M75:2B:?;5f6083>>o2m3:17d:7:188k46f2900qo?:a;291?6=8r.:=k4m4:J267=O9:<0(oh50:k55?6=3`>j6=44i4g94?=n<10;66a>0`83>>{e9<31<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c36<?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e9?>1<7;50;2x 47a2k>0D<<=;I302>"en3:0e;?50;9j0d<722c>i7>5;h6;>5<<g8:j6=44}c356?6==3:1<v*>1g8a0>N6:;1C=>84$cd94>o193:17d:n:188m0c=831b854?::m24d<722wi>:m50;694?6|,8;m6n64H001?!da2;;0D<=9;h`a>5<<aki1<75fbe83>>id93:17pl=6183>1<729q/=<h5b29K574<@89=7d8>:188m0c=831b854?::m24d<722wi>;?50;694?6|,8;m6o=4H001?M74>2c==7>5;h7f>5<<a=21<75`11c94?=zj;<96=4;:183\7f!76n3h87E?=2:J273=n>80;66g:e;29?l2?2900c<>n:188yg41;3:187>50z&25c<e;2B:>?5G1248m37=831b9h4?::k7<?6=3f;;m7>5;|`121<72=0;6=u+10d9f6=O9;80D<=9;h42>5<<a<o1<75f4983>>i68h0;66sm27794?2=83:p(<?i:c18L4453A;8:6g91;29?l3b2900e9650;9l55g=831vn?;7:187>5<7s-;:j7l<;I316>N6;?1b:<4?::k6a?6=3`>36=44o02b>5<<uk8>57>54;294~"69o0i?6F>239K560<a?;1<75f5d83>>o303:17b??a;29?xd5=h0;694?:1y'54`=j:1C=?<4H015?l062900e8k50;9j0=<722e:<l4?::\7fa60d=83>1<7>t$03e>g5<@8897E?<6:k55?6=3`?n6=44i5:94?=h99k1<75rb37`>5<3290;w)?>f;`0?M75:2B:?;5f6083>>o2m3:17d:7:188k46f2900qo<:d;290?6=8r.:=k4m3:J267=O9:<0e;?50;9j1`<722c?47>5;n33e?6=3th99h4?:583>5}#98l1n>5G1308L4513`<:6=44i4g94?=n<10;66a>0`83>>{e;;o1<7=50;2x 47a2j<0D<<=;%`e>7`<@89=7dlm:188mge=831do<4?::\7fa77b=83>1<7>t$03e>fg<@8897E?<6:k6f?6=3`==6=44i03a>5<<gm;1<75rb20`>5<4290;w)?>f;301>N6:;1C=>84i4`94?=nk90;66ak1;29?xd4;;0;6>4?:1y'54`=k?1C=?<4$cd96c=O9:<0eol50;9jff<722eh=7>5;|`074<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm32294?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg54>3:1?7>50z&25c<d>2B:>?5+bg81b>N6;?1bno4?::kag?6=3fi:6=44}c101?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl<3583>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f65f29086=4?{%32b?e23A;9>6*mf;0e?M74>2cin7>5;h``>5<<gm;1<75rb21:>5<3290;w)?>f;ab?M75:2B:?;5f5c83>>o0>3:17d?>b;29?jb62900qo=<8;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa76`=8391<7>t$03e>f0<@8897)li:3d8L4513`hi6=44ica94?=hk80;66sm32g94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>=k:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`006<72:0;6=u+10d9g3=O9;80(oh52g9K560<akh1<75fbb83>>id93:17pl<4383>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi?9?50;194?6|,8;m6<=:;I316>N6;?1b9o4?::k`4?6=3fn:6=44}c171?6=;3:1<v*>1g8`2>N6:;1/nk4=f:J273=njk0;66gmc;29?je62900qo<88;290?6=8r.:=k4l7:J267=#jo0?56F>379jfg<722cio7>5;h`g>5<<gm;1<75rb26:>5<4290;w)?>f;a5?M75:2.ij7<i;I302>oej3:17dll:188kf7=831vn>:7:187>5<7s-;:j7mn;I316>N6;?1b9o4?::k42?6=3`;:n7>5;nf2>5<<uk9?;7>53;294~"69o0:?85G1308L4513`?i6=44ib294?=hl80;66sm35f94?5=83:p(<?i:b48L4453-hm6?h4H015?lde2900eom50;9lg4<722wi?9m50;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:>i6=4<:183\7f!76n3;896F>239K560<a<h1<75fc183>>ic93:17pl<5083>6<729q/=<h5c79K574<,kl1>k5G1248mgd=831bnn4?::m`5?6=3th89=4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;=l1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo=:5;297?6=8r.:=k4l6:J267=#jo09j6F>379jfg<722cio7>5;na2>5<<uk9>87>54;294~"69o0hm6F>239K560<a<h1<75f7783>>o69k0;66ak1;29?xd4=:0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn>;6:180>5<7s-;:j7m9;I316>"en38m7E?<6:kaf?6=3`hh6=44ob394?=zj:?36=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg52?3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi?8j50;194?6|,8;m6n84H001?!da2;l0D<=9;h`a>5<<aki1<75`c083>>{e;<i1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f63e29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th89k4?:283>5}#98l1o;5G1308 g`=:o1C=>84ic`94?=njj0;66al1;29?xd5?l0;694?:1y'54`=k11C=?<4$cd964=O9:<0eol50;9jff<722cih7>5;na2>5<<uk9;57>52;294~"69o0h86F>239'fc<53A;8:6gmb;29?je62900qo=?8;290?6=8r.:=k4la:J267=O9:<0e8l50;9j33<722c:=o4?::mg5?6=3th9<<4?:383>5}#98l1o>5G1308 g`=;2B:?;5fbc83>>ic93:17pl<0b83>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi?=l50;194?6|,8;m6<=:;I316>N6;?1b9o4?::k`4?6=3fn:6=44}c13b?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl<0d83>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f675290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c125?6=;3:1<v*>1g8270=O9;80D<=9;h7a>5<<aj:1<75`d083>>{e;8?1<7:50;2x 47a2jk0D<<=;I302>o2j3:17d99:188m47e2900ci?50;9~f67329086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th8=54?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;8h1<7<50;2x 47a2j>0D<<=;%`e>7=O9:<0eol50;9lg4<722wi?<o50;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:286=4::183\7f!76n3i27E?=2:&ab?573A;8:6gmb;29?ldd2900eoj50;9jf`<722eo=7>5;|`05`<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm30f94?5=83:p(<?i:016?M75:2B:?;5f5c83>>od83:17bj>:188yg5593:187>50z&25c<di2B:>?5G1248m0d=831b;;4?::k25g<722eo=7>5;|`065<72:0;6=u+10d9563<@8897E?<6:k6f?6=3`i;6=44oe394?=zj:8?6=4;:183\7f!76n3ij7E?=2:J273=n=k0;66g86;29?l76j3:17bj>:188yg55;3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi??950;694?6|,8;m6no4H001?M74>2c>n7>5;h55>5<<a8;i6=44oe394?=zj:8=6=4<:183\7f!76n3;896F>239K560<a<h1<75fc183>>ic93:17pl<2`83>1<729q/=<h5c`9K574<@89=7d;m:188m20=831b=<l50;9l`4<722wi>5>50;694?6|,8;m6n64H001?!da2;;0D<=9;h`a>5<<aki1<75fbe83>>id93:17pl=8383>1<729q/=<h5c99K574<,kl1><5G1248mgd=831bnn4?::ka`?6=3fi:6=44}c15e?6=<3:1<v*>1g8a1>N6:;1C=>84i7394?=nl>0;66g;8;29?j77i3:17pl>5783>6<729q/=<h51278L4453A;8:6g:b;29?le72900ci?50;9~f60?290>6=4?{%32b?d33A;9>6F>379j24<722c?m7>5;h7f>5<<a=21<75`11c94?=zj:<26=4;:183\7f!76n3h87E?=2:J273=n>80;66g:e;29?l2?2900c<>n:188yg72;3:1?7>50z&25c<6;<1C=?<4H015?l3e2900en>50;9l`4<722wi?;;50;794?6|,8;m6n74H001?!da2=80D<=9;h`a>5<<aki1<75fbe83>>oem3:17bj>:188yg5193:187>50z&25c<d?2B:>?5+bg8a5>N6;?1bno4?::kag?6=3`ho6=44oe394?=zj:<=6=4;:183\7f!76n3i<7E?=2:&ab?2>3A;8:6gmb;29?ldd2900eoj50;9l`4<722wi?;950;794?6|,8;m6n74H001?!da2?1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f7dd290?6=4?{%32b?d43A;9>6F>379K00=#jo0;7d8>:188m0c=831b854?::m24d<722wi>i950;794?6|,8;m6n74H001?!da201C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f7?e290?6=4?{%32b?e03A;9>6*mf;12?M74>2cin7>5;h``>5<<akn1<75`d083>>{e:m21<7;50;2x 47a2j30D<<=;%`e><=O9:<0eol50;9jff<722cih7>5;h`f>5<<gm;1<75rb3`b>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:m81<7=50;2x 47a2j?0D<<=;%`e>==O9:<0eol50;9jff<722eo=7>5;|`1fg<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8<m7>54;294~"69o0h46F>239'fc<63A;8:6gmb;29?ldd2900eoj50;9lg4<722wi>nm50;194?6|,8;m6n;4H001?!da211C=>84ic`94?=njj0;66ak1;29?xd5l<0;6>4?:1y'54`=k<1C=?<4$cd9<>N6;?1bno4?::kag?6=3fn:6=44}c0``?6=;3:1<v*>1g8`1>N6:;1/nk47;I302>oej3:17dll:188ka7=831vn?mj:180>5<7s-;:j7m:;I316>"en320D<=9;h`a>5<<aki1<75`d083>>{e:jl1<7=50;2x 47a2j?0D<<=;%`e>==O9:<0eol50;9jff<722eo=7>5;|`1`5<72:0;6=u+10d9g0=O9;80(oh58:J273=njk0;66gmc;29?jb62900qo<k1;297?6=8r.:=k4l5:J267=#jo037E?<6:kaf?6=3`hh6=44oe394?=zj;nm6=4;:183\7f!76n3h87E?=2:J273=O<<1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm31494?2=83:p(<?i:c18L4453A;8:6*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`1b=<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8o57>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3fb>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:mh1<7:50;2x 47a2k90D<<=;I302>N3=2.ij7>4i7394?=n=l0;66g;8;29?j77i3:17pl=db83>1<729q/=<h5b29K574<@89=7E::;%`e>5=n>80;66g:e;29?l2?2900c<>n:188yg4cl3:187>50z&25c<e;2B:>?5G1248L13<,kl1<6g91;29?l3b2900e9650;9l55g=831vn?jj:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa756=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd4880;694?:1y'54`=j:1C=?<4H015?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk9;>7>54;294~"69o0i?6F>239K560<,kl1<6g91;29?l3b2900e9650;9l55g=831vn>><:187>5<7s-;:j7l<;I316>N6;?1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm31694?2=83:p(<?i:c18L4453A;8:6*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`040<72=0;6=u+10d9f6=O9;80D<=9;%`e>5=n>80;66g:e;29?l2?2900c<>n:188yg4a:3:187>50z&25c<e;2B:>?5G1248L13<,kl1<6g91;29?l3b2900e9650;9l55g=831vn?h<:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6c2=83>1<7>t$03e>g5<@8897E?<6:J71>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th9j84?:583>5}#98l1n>5G1308L4513A>>7)li:19j24<722c>i7>5;h6;>5<<g8:j6=44}c0e2?6=<3:1<v*>1g8a7>N6:;1C=>84H578 g`=82c==7>5;h7f>5<<a=21<75`11c94?=zj;l<6=4;:183\7f!76n3h87E?=2:J273=O<<1/nk4?;h42>5<<a<o1<75f4983>>i68h0;66sm2e194?2=83:p(<?i:b58L4453-hm6>?4H015?lde2900eom50;9jfa<722eo=7>5;|`03d<72<0;6=u+10d9g<=O9;80(oh5479K560<akh1<75fbb83>>oel3:17dlj:188ka7=831vn?7k:186>5<7s-;:j7m6;I316>"en330D<=9;h`a>5<<aki1<75fbe83>>oem3:17bj>:188yg4>03:187>50z&25c<d?2B:>?5+bg805>N6;?1bno4?::kag?6=3`ho6=44oe394?=zj;3<6=4<:183\7f!76n3i>7E?=2:&ab?><@89=7dlm:188mge=831dh<4?::\7fa6<e=83?1<7>t$03e>f?<@8897)li:89K560<akh1<75fbb83>>oel3:17dlj:188ka7=831vn?j9:187>5<7s-;:j7m8;I316>"en39:7E?<6:kaf?6=3`hh6=44icf94?=hl80;66sm28394?5=83:p(<?i:b78L4453-hm655G1248mgd=831bnn4?::mg5?6=3th95l4?:283>5}#98l1o85G1308 g`=02B:?;5fbc83>>oek3:17bj>:188yg4>:3:1?7>50z&25c<d=2B:>?5+bg8;?M74>2cin7>5;h``>5<<gm;1<75rb3;0>5<4290;w)?>f;a6?M75:2.ij764H015?lde2900eom50;9l`4<722wi>4:50;194?6|,8;m6n;4H001?!da211C=>84ic`94?=njj0;66ak1;29?xd51<0;6>4?:1y'54`=k<1C=?<4$cd9<>N6;?1bno4?::kag?6=3fn:6=44}c0:2?6=;3:1<v*>1g8`1>N6:;1/nk47;I302>oej3:17dll:188ka7=831vn?o;:187>5<7s-;:j7l<;I316>N6;?1C885+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6fd=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd5jm0;694?:1y'54`=j:1C=?<4H015?M223-hm6=5f6083>>o2m3:17d:7:188k46f2900qo<6e;290?6=8r.:=k4m3:J267=O9:<0D9;4$cd94>o193:17d;j:188m1>=831d==o50;9~f7?a290?6=4?{%32b?d43A;9>6F>379K00=#jo0;7d8>:188m0c=831b854?::m24d<722wi>l>50;694?6|,8;m6o=4H001?M74>2B?96*mf;28m37=831b9h4?::k7<?6=3f;;m7>5;|`1e4<72=0;6=u+10d9f6=O9;80D<=9;I66?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8j>7>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3c0>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e:j?1<7:50;2x 47a2k90D<<=;I302>"en3:0e;?50;9j1`<722c?47>5;n33e?6=3th9o;4?:583>5}#98l1n>5G1308L4513-hm6=5f6083>>o2m3:17d:7:188k46f2900qo<l7;290?6=8r.:=k4m3:J267=O9:<0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3a;>5<3290;w)?>f;`0?M75:2B:?;5+bg83?l062900e8k50;9j0=<722e:<l4?::\7fa6f?=83>1<7>t$03e>g5<@8897E?<6:&ab?6<a?;1<75f5d83>>o303:17b??a;29?xd5kh0;694?:1y'54`=j:1C=?<4H015?!da291b:<4?::k6a?6=3`>36=44o02b>5<<uk8i;7>54;294~"69o0i?6F>239K560<@=?0(oh50:k55?6=3`?n6=44i5:94?=h99k1<75rb3`;>5<3290;w)?>f;`0?M75:2B:?;5G449'fc<73`<:6=44i4g94?=n<10;66a>0`83>>{e9<:1<7=50;2x 47a289>7E?=2:J273=n=k0;66gl0;29?jb62900qo?6b;297?6=8r.:=k4>349K574<@89=7d;m:188mf6=831dh<4?::\7fa73e=83>1<7>t$03e>f1<@8897)li:c08L4513`hi6=44ica94?=njm0;66ak1;29?xd6j80;6?4?:1y'54`=k:1C=?<4$cd97>N6;?1bno4?::mg5?6=3th:5n4?:583>5}#98l1ol5G1308L4513`?i6=44i6494?=n98h1<75`d083>>{e;?n1<7:50;2x 47a2k?0D<<=;I302>"en380e;?50;9j`2<722c?47>5;n33e?6=3th8;>4?:483>5}#98l1o45G1308 g`=:;1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f4??29086=4?{%32b?74=2B:>?5G1248m0d=831bo=4?::mg5?6=3th84?4?:483>5}#98l1o45G1308 g`=:;1C=>84ic`94?=njj0;66gmd;29?ldb2900ci?50;9~f61e290?6=4?{%32b?d23A;9>6F>379'fc<53`<:6=44ie594?=n<10;66a>0`83>>{e;1?1<7=50;2x 47a2j?0D<<=;%`e>7`<@89=7dlm:188mge=831dh<4?::\7fa7=6=8391<7>t$03e>f3<@8897)li:3d8L4513`hi6=44ica94?=hl80;66sm18;94?2=83:p(<?i:bc8L4453A;8:6g:b;29?l112900e<?m:188ka7=831vn>9;:186>5<7s-;:j7m6;I316>"en39;7E?<6:kaf?6=3`hh6=44icf94?=njl0;66ak1;29?xd61l0;6>4?:1y'54`=9:?0D<<=;I302>o2j3:17dm?:188ka7=831vn<o>:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`2e1<72:0;6=u+10d9563<@8897E?<6:k6f?6=3`i;6=44oe394?=zj8h;6=4::183\7f!76n3h?7E?=2:J273=#jo0;7d8>:188m1g=831b9h4?::k7<?6=3f;;m7>5;|`2f7<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<o9:180>5<7s-;:j7?<5:J267=O9:<0e8l50;9jg5<722eo=7>5;|`2e2<72<0;6=u+10d9f1=O9;80D<=9;%`e>5=n>80;66g;a;29?l3b2900e9650;9l55g=831vn<o7:186>5<7s-;:j7l;;I316>N6;?1/nk4?;h42>5<<a=k1<75f5d83>>o303:17b??a;29?xd6ih0;684?:1y'54`=j=1C=?<4H015?!da291b:<4?::k7e?6=3`?n6=44i5:94?=h99k1<75rb0c`>5<2290;w)?>f;`7?M75:2B:?;5+bg83?l062900e9o50;9j1`<722c?47>5;n33e?6=3th:mh4?:483>5}#98l1n95G1308L4513-hm6=5f6083>>o3i3:17d;j:188m1>=831d==o50;9~f4g5290?6=4?{%32b?ef3A;9>6F>379j1g<722c<:7>5;h32f?6=3fn:6=44}c3b1?6=<3:1<v*>1g8`e>N6:;1C=>84i4`94?=n??0;66g>1c83>>ic93:17pl>9783>7<729q/=<h5c29K574<,kl1>6F>379jfg<722eo=7>5;|`2=0<72=0;6=u+10d9gd=O9;80D<=9;h7a>5<<a><1<75f10`94?=hl80;66sm37g94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk9<=7>55;294~"69o0h56F>239'fc<482B:?;5fbc83>>oek3:17dlk:188mgc=831dh<4?::\7fa720=8391<7>t$03e>f3<@8897)li:3d8L4513`hi6=44ica94?=hl80;66sm36g94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk;3o7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo=8d;291?6=8r.:=k4l9:J267=#jo09>6F>379jfg<722cio7>5;h`g>5<<ako1<75`d083>>{e;>i1<7;50;2x 47a2j30D<<=;%`e>66<@89=7dlm:188mge=831bni4?::kaa?6=3fn:6=44}c144?6==3:1<v*>1g8`=>N6:;1/nk4<0:J273=njk0;66gmc;29?ldc2900eok50;9l`4<722wi=io50;094?6|,8;m6n=4H001?!da2:1C=>84ic`94?=hl80;66sm36d94?3=83:p(<?i:b;8L4453-hm6>>4H015?lde2900eom50;9jfa<722cii7>5;nf2>5<<uk9<>7>55;294~"69o0h56F>239'fc<482B:?;5fbc83>>oek3:17dlk:188mgc=831dh<4?::\7fa723=83?1<7>t$03e>f?<@8897)li:228L4513`hi6=44ica94?=njm0;66gme;29?jb62900qo?nd;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c36b?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7c03:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;o<7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?k2;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3g0?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7c>3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;3m7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?72;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3;0?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7?>3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;347>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?if;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c3e3?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg7a13:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;mn7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?id;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c36`?6=:3:1<v*>1g8`7>N6:;1/nk4<;I302>oej3:17bj>:188yg72j3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;=?7>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?91;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}c10f?6=;3:1<v*>1g8`2>N6:;1/nk4=f:J273=njk0;66gmc;29?je62900qo=67;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1:=?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg5>j3:1>7>50z&25c<d<2B:>?5+bg80?M74>2cin7>5;na2>5<<uk92h7>52;294~"69o0h86F>239'fc<43A;8:6gmb;29?je62900qo=6f;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1;f?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg5?l3:1>7>50z&25c<d<2B:>?5+bg80?M74>2cin7>5;na2>5<<uk93j7>52;294~"69o0h86F>239'fc<43A;8:6gmb;29?je62900qo=61;296?6=8r.:=k4l4:J267=#jo087E?<6:kaf?6=3fi:6=44}c1:7?6=:3:1<v*>1g8`0>N6:;1/nk4<;I302>oej3:17bm>:188yg7fj3:1>7>50z&25c<d;2B:>?5+bg80?M74>2cin7>5;nf2>5<<uk;j57>52;294~"69o0h?6F>239'fc<43A;8:6gmb;29?jb62900qo?nf;296?6=8r.:=k4l3:J267=#jo087E?<6:kaf?6=3fn:6=44}r47>5<6;rT=863<b`8af>;60<0?m63>8687e>;60k0?m63>8887e>;6090?m63>8087e>;60:0?m63>6187e>;6=l0?m63>5b87e>;6=h0?m63>5887e>;6>=0?m63>6387e>;4>10==63<668g5>;4>j0in6s|b683>0}Y>:1Un:523`29fg=:;>k1nn5236`955g<uz3j6=4={_;b?85fn3;;m6s|10594?0|V8;<70=93;`g?851=3hn70=91;`a?851>3ho70=97;``?xu61h0;6>u218d91g=:90i1h<5218g91g=z{::j6=4<{<13g?b6349;j7;m;<13a?3e3ty:n44?:3y>5g4=>816=l85d09~w74f290?wS<=a:?2`<<68h16=io5bc9>72`=jl1v\7f<78:180\7f87>j3?i70?6c;7a?87>13n:7p}<a483>60|5:k=6<>n;<1b3?2f349i47?>c:?2`6<2m27:h84:e:?2`<<2m27:h:4:e:?2g`<c?27:ok4:e:?2`4<2m27:jl4:e:?2bf<2m279<=4:e:?2b`<2m27:j84:e:?2b3<c?27:j54:e:?123<2m279;;4:e:?125<2m279:<4:e:?127<2m279:>4:e:?121<2m279:84:e:?1b=<2m279j?4:e:?1b6<2m279j94:e:?1b0<2m279j;4:e:?1b2<2m279m94:e:?1gg<2m2795h4:e:?1=c<2m279m=4:e:?1e4<2m279m?4:e:?1e6<2m279o84:e:?1g3<2m279o:4:e:?1g=<2m279o44:e:?1gd<2m278;o4k7:?2f5<2m27:n?4:e:?2e2<2m27:m54:e:?2ed<2m27:mn4:e:?2e`<2m2wx=8;50;0x94302m;01<;7:4`8yv76i3:19vP>1`9>7d4=l>16?l85d69>7d2=l>16?l95d69~w34=83>pR;<4=246>gb<5:<<6ol4=24g>46f3ty:::4?:3y>51b=l816=8m5609~w33=83;3wS8:;<1a<?75>27:h>4;a:?2`0<3i27:h44;a:?2`2<3i27:oh4;a:?2gc<3i27:h<4;a:?2bd<3i27:jn4;a:?145<3i27:jh4;a:?2b0<3i27:j;4;a:?2b=<3i278m=4k1:?2f5<3i27:n?4;a:?2e2<3i27:m54;a:?2ed<3i27:mn4;a:?2e`<3i2wx>>>50;6xZ7573493=7lj;<3ea?77i27:jk4mb:\7fp530=838p1<:n:e38943f2?;0q~<ia;297~;5l10io63<00824d=::m<1ni5rs010>5<4sW;8?63<a18ag>;4?h0ih6s|23494?2|V;8=70?k3;33e>;4090io63>d58af>{t:;>1<7:t^307?87dn3;;m63<7d8aa>;6l90in6s|11f94?5esW;;h63<a387<>;4im0?463<a587<>;4il0?463<ag87<>;4j10>h63<a987<>;4i00?463<a`87<>;4ik0?463<ab87<>;60<0?463>8687<>;60k0?463>8887<>;6090?463>8087<>;60:0?463=5g87<>;5j00?463>6187<>;6=l0?463>5b87<>;6=h0?463>5887<>;6>=0?463>6387<>;5=10?463=5887<>;5=h0?463=5c87<>;5=j0?463=5e87<>;5=l0?463<6`87<>;4>10?463<6887<>;5jj0?463=b`87<>;5jk0?463=dg87<>;48?0?463=d887<>;5lh0?463=dc87<>;5lj0?463=de87<>;5ll0?463<0187<>;4880?463<0387<>;48:0?463<0587<>;48<0?463=be87<>;5j>0?463=b987<>;4>m0?46s|2dd94?4|5::?6;?4=3d5>46f3ty9>84?:5y]673<58n:6<>n;<14a?dd34;o>7lm;|q:6?6=:rT2>63<a9824d=z{;886=4;{_017>;6kl0:<l521cf9fg=:;>l1nn5rs2c0>5<4jr78m?4>0`9>7db==l16?l:54`9>7dc==l16?lh55d9>7gg=jj16?o6510f896g?2<o01>o6:4g896gf2<o01>om:4g896gd2<o01<6::4g894>02<o01<6m:4g894>>2<o01<6?:e5894>62<o01<6<:4g8973a2<o01?l6:4g894072<o01<;j:4g8943d2<o01<;n:4g8943>2<o01<8;:4g894052<o01?;7:4g8973>2<o01?;n:4g8973e2<o01?;l:4g8973c2<o01?;j:4g8960f2m=01>87:4g8960>2<o01?ll:4g897df2<o01?lm:4g897ba2<o01>>9:4g897b>2<o01?jn:4g897be2<o01?jl:4g897bc2<o01?jj:4g896672<o01>>>:4g896652<o01>><:4g896632<o01>>::4g897dc2<o01?l8:4g897d?2<o01>8k:e58yv7113:1>v3>61855>;6=:0o=6s|23594?2|V;8<70?k5;33e>;4?j0ii63>d78af>{t1<0;6?uQ949>7dd=99k0q~<jc;296~;4880==63=f2824d=z{8826=4<7z\26<=:;h<185523`590==:;k219n521e190==:9m?185521e;90==:9m=185521bg90==:9jl185521e390==:9ok185521ga90==::9:185521gg90==:9o?185521g490==:9o21855227490==::><1855227290==::?;1855227090==::?91855227690==::??185522g:90==::o8185522g190==::o>185522g790==::o<185522g590==::h>185522b`90==::0o1855228d90==::h:185522`390==::h8185522`190==::j?185522b490==::j=185522b:90==::j3185522bc90==:;>h185521c290==:9k8185521`590==:9h2185521`c90==:9hi185521`g90==z{;996=4;{_006>;4080io63=01824d=::9;1no5rs8494?4|V0<01>ol:02b?xu5ih0;6?u22ca924=::0;1h<5rs3d`>5<5s48o;7lm;<137?77i2wx5:4?:3y]=2=:;hn1==o4}r;;>5<5sW3370=ne;33e>{t98;1<7<t^032?842j3;;m6s|13g94?4|V88n70<93;33e>{t:h21<7<t=3`b>37<5;386i?4}r0bb?6=:r795:4k1:?1e6<192wx>ok50;0x97?c2kh01?m::02b?xu4>00;6hu22969ff=:;?91nn522949ff=::>i1nn5226:9ff=::>o1nn522929ff=::181nn5237;955g<5:<>6om4=242>ge<5:<=6ol4=244>gb<5;=j6om4}r0f<?6=:r79h84k1:?1`g<192wx>k?50;0x96612?;01?h7:02b?xu5no0;68u22e59f`=::m81nn522ed924=:;9<1==o4=3f0>gb<uz8i97>52z?1ff<68h16>no5609~w44c2909wS?=d:?127<68h1v\7f<>j:181\7f[77m279954>0`9~w4552909wS?<2:?123<68h1v\7f<<l:181\7f[75k279:<4>0`9~w7da2908w0<6b;`g?84>l3hh70<l6;33e>{t9::1<7<t^013?841=3;;m6s|10494?4|V8;=70<:f;33e>{t:j:1<7:t=3;a>gd<5;3o6oj4=3;b>gd<5;i<6<>n;|q26c<72;qU=?h4=347>46f3ty:594?:2y>5<>==k16=4755c9>5<3=l81v\7fnl50;ax945?2m901<ll:648940b2><01<k<:64894202><01><k:4`8964d2<h01>:7:4`896202<h01>>7:648967f2><01<7::648yv5f?3:1>v3<a7855>;4i>0:<l5rs3c`>5<5s48247j>;<0b6?063ty9o94?:4y>6<>=jm16>495bb9>6<e=jl16>l:5609>6fd=99k0q~<n5;296~;51?0o=63=b6855>{t1=0;6?uQ959>7dg=99k0q~<m2;296~;5j00:<l522b5924=z{8;?6=4={_320>;5=l0:<l5rs030>5<5sW;:?63=5e824d=z{8:m6=4={_33b>;5=00:<l5rs3a2>5<5s482o7lm;<0`<?77i2wx=9h50;1x94362m;01<;;:4`894342<h0q~<nb;296~;51m0o=63=9d855>{t9;k1<7<t^00b?840>3;;m6s|34c94?4|5:?n68l4=27`>a7<uz;9n7>52z\26g=::?:1==o4}r326?6=:rT:=?5224a955g<uz;=m7>52z?227<1927:9;4k1:\7fp5<5=839p1<o8:73894?12m;01<7::03a?xu>;3:1>vP63:?0e<<68h1v\7f<??:181\7f[7682799l4>0`9~w7cb2909w0=?3;42?84a=3;;m6s|ad83>7}Yil16?;o511c8yv5bm3:15v3<ae87e>;4il0?m63<ag87e>;4i10?m63<a887e>;4ih0?m63<ac87e>;4ij0?m63<678g5>{tn80;69?t^568Z44?3W;9=6P;3:\g6>X6::1Uh55Qf09>561=j116=4h5779>507=??16?l:5609>7d1=>816?o65ce9>7g>=kl16?o65ag9>7g>=9;=01>l7:83896d?21l01>l7:9g896d?21n01>l7:9a896d?21h01>l7:9c896d?21301<ml:64894dd2<h01<m?:64894e42><01<m9:64894e>2><01<9j:648940b2<h01<9=:64894122><01<97:648941e2><01<h<:64894c42<h01<k8:64894cf2><01<kk:64894`72><01<:j:648942e2><01<:8:4`894302><01<;;:648966?2<h01>>l:648966a2><01>?=:64896722><01>?7:648967f2<h01>?j:64896462><01><;:64896402><01><n:64894?d2><01<76:64894g52><01<o::64894?22<h0q~<<a;291~X5;h16?9;5bc9>6a`=99k01>9>:cg896152ki0q~<<8;292~X5;116?9=5bc9>714=??16>ik511c8960b2ki01>9=:cg8yv44?3:1:vP=369>76`=jk16?>k5779>6ab=99k01>8j:cg896112ki0q~<<6;292~X5;?16?>o5bc9>76?=??16>im511c896132ki01>=m:c`8yv44=3:1:vP=349>760=jk16?>;5779>6ad=99k01>9;:cg896172ki0q~<<4;292~X5;=16?><5bc9>767=??16>io511c896172ko01>9::ca8yv44;3:1:vP=329>77c=jk16??j5779>6a?=99k01>9>:ca896122ko0q~<jd;296~;48;0==63=f5824d=z{;k=6=4={<0:1?b6348i478>;|q2e5<72:q6=l:55c9>5d4=l816=l;55c9~w6032909w0=98;6b?851=3n:7p}<0683>6}:;921h<5231a91g=:;9h19o5rs353>5<5s49>i7m?;<16b?e63ty9:k4?:2y>70b=k816?8m510`8963e2j:0q~=>f;297~;4:80o=63<2586f>;4::0>n6s|27a94?5|5:?:6n?4=273>47e349?j7m?;|q12=<72:q6?9=5c09>714=98h01>:>:b28yv40<3:1?v3<338`5>;4;80:=o523229g5=z{;<j6=4<{<17=?e6349?47?>b:?002<d82wx>;k50;1x963>2j;01>;7:03a?852?3i;7p}:2;296~;40:0o=63<838ag>{t:>?1<7=t=215>f7<5:9>6<?m;<100?e73ty9::4?:2y>76`=k816?>k510`8965c2j:0q~<99;296~;4<=0h<63<448`5>{t:?h1<7=t=26g>f7<5:>h6<?m;<17f?e73ty9:i4?:2y>703=k816?8:510`896342j:0q~==5;297~;4:00>n63<268g5>;4:h0>n6s|26194?5|5:8n6n?4=20g>47e3499o7m?;|q167<72<qU>?<4=2:2>gd<5:?m6om4=3c7>46f349<j7lk;|q165<72<qU>?>4=2:2>gb<5:?o6om4=3c0>46f349<o7lm;|q15c<72<qU><h4=27:>ge<5;k96<>n;<1;1?de349<o7lk;|q15`<72<qU><k4=276>ge<5:286ol4=3c2>46f3493<7lm;|q15a<72<qU><j4=272>ge<5:286oj4=3c3>46f349<i7lm;|q15f<72<qU><m4=2:7>gd<5:>o6om4=3;e>46f349<i7lk;|q15g<72<qU><l4=2:7>gb<5:>26om4=3;f>46f349<j7lm;|q41?6=0rT98?5Q749>7g>=;016=o=5bc9>70`=jk16>nm5bb9>6c>=>816=o<511c8yv142902wS<;0:\47>;4j108;63<5e8af>;4=j0<:63=cb8af>;5km0io63>b08af>;6j90:<l5rs6094??|V;9m7S9=;<1a<?51349>57lm;<16<?11348hh7lm;<0`a?dd34;ji7??a:?2ec<ej2wx;<4?:8y]66c<V>;01>l7:27896322kh01>;;:64897eb2kh01?mi:ca894gd28:j70?nd;`a?xu083:15vP=3e9]35=:;k21?9523439fg=:;<:1;;522bd9fg=::m:1nn521`c955g<58ki6ol4}r4e>5<>sW88o6P9f:?0f=<4;2788i4mb:?00f<0>279h=4mb:?1`4<ek27:m54>0`9>5d?=jk1v\7f;k50;:xZ75e3W<n70=m8;11?85313hi70=;8;55?84c93hi70?n7;33e>;61?0in6s|21g94?2|V;:n70?75;33e>;4?=0in63>878af>{t:8:1<7:t^333?87?13;;m63<738a`>;60h0in6s|2d694?4|5;io6i?4=3d5>37<uz>o6=4={<147?de349<:7j>;|q0e1<72;q6?l<5609>7d2=99k0q~<id;297~;5l>0io63<05824d=::m91no5rs30`>5<3sW89o63>f7824d=:;1>1nn521g59fg=z{;8n6=4;{_01a>;6nh0:<l523919ff=:9oh1no5rs265>5<4s49?47j>;<17g?3e349?n7;m;|q055<72:q6?<<5d09>743==k16?<:55c9~w6272909w0=;4;7a?853:3n:7p}<3b83>6}:;:o1h<5235091g=:;=;19o5rs214>5<4s49857j>;<10a?3e3498h7;m;|q076<72:q6?>;5d09>76?==k16?>655c9~w64a2908w0=<1;f2?854=3?i70=<4;7a?xu1l3:15vP=1`9]2a=:;k218<521779fg=:9?>1==o4=266>ge<5;3:6om4=3`g>37<5:=:6oj4}r4a>5<>sW8:46P9b:?0f=<4n27::?4>0`9>715=jj16>4?5bc9>6<4=jj16?;k5bc9>535=jk1v\7f;o50;;xZ7703W<j70=m8;1f?87183;;m63<3g8ag>;51;0in63=928ag>;4>l0ih63>608af>{t>00;64uQ2048Z3?<5:h36>j4=07f>46f3498m7ll;<0:7?de348287ll;<36b?de3498n7ll;|q5<?6=1rT9=85Q699>7g>=;j16=8m511c896512ki01?7;:c`897?22ki01>9?:c`8943c2kh0q~88:18:\7f[46<2T=;63<b980f>;6=h0:<l523209ff=::0?1no522849ff=:;>:1ni5214`9fg=z{?<1<76t^330?[01349i47=n;<37<?de34;>57??a:?06`<ek2795;4mb:?034<ej2wx??l50;1x964c2m;01>=>:4`896572<h0q~=>c;297~;49l0o=63<2086f>;4:90>n6s|33094?5|5:8?6i?4=204>0d<5:8=68l4}r162?6=;r78954k1:?01f<2j2789o4:b:\7fp704=839p1>;;:e38963?2<h01>;8:4`8yv53m3:1?v3<518g5>;4==0>n63<5286f>{t;=k1<7=t=26`>a7<5:?;68l4=26e>0d<uz89n7>54z\16g=:9o?1==o4=0g7>gd<5:2?6ok4}r01<?6=<rT9>5521e5955g<5:=h6om4=0f;>gd<uz;=47>52z?21`<1927:9=4k1:\7fp644=83>pR??=;<3;f?77i27:4n4mb:?037<ej2wx=l=50;0x94g12<h01<o::e38yv73k3:1?v3>5086f>;6<l0o=63>5186f>{t9<81<7=t=074>0d<58??6i?4=075>0d<uz8;o7>54z\14f=:91;1==o4=256>gd<58296ol4}r35f?6=:r7:954k1:?221<192wx>?j50;6xZ74c34;m47??a:?0<6<em27:j44mb:\7fp51?=839p1<:k:4`8942b2<h01<:m:e38yv73=3:1?v3>46825g=:9=21h<5214;924=z{;:m6=4;{_03b>;60>0:<l523649fg=:9121no5rs32g>5<3sW8;h63>82824d=:;>>1ni521969fg=z{;8m6=4;{_01b>;6nj0:<l523979ff=:9on1no5rs32a>5<3sW8;n63>81824d=:9?l1no523679fa=z{;o86=4={<0`a?b6348m978>;|q1b`<72=q6>i95be9>6a4=jk16?=;511c897b42ki0q~<ja;296~;5l;0o=63=dd855>{t:l31<7<t=3fb>37<5;n=6i?4}r0a2?6=:r79oo491:?1fa<68h1v\7f?l;:181\7f84ej3;;m63=c8855>{t:031<7;t=3;a>ge<5;3o6ok4=3;`>a7<5;3j6om4=3c2>37<uz=m6=4={_5e?85e03237p}8d;296~X0l278n5476:\7fp3f<72;qU;n523c:9<0=z{>h1<7<t^6`896d?21>0q~9n:181\7f[1f349i476<;|q4=?6=:rT<563<b98;6>{t?10;6?uQ799>7g>=081v\7f:950;0xZ21<5:h365>4}r0a5?6=:r79o;491:?1f=<68h1v\7f?ok:181\7f84>i3n:70<n0;42?xu5m>0;6?u22ef924=::m91h<5rs3g6>5<5s48ho7j>;<0e3?063ty8;:4?:3y>73`=l816?;m5be9~w64?2909w0<76;`g?855i3n:7p}=e183>7}::m;1h<522g0924=z{:;26=4<{<12e?b6349:i7;m;<12`?3e3ty94h4?:3y>775=l816>5>5be9~w6?22909w0=;b;f2?85713hi7p}<b083>7}:;k21m8523`;924=z{:h96=4={<1a<?g1349jm78>;|q0f<<72;q6?oo5d09>7g>=j91v\7f>l8:181\7f85fn3<:70=m8;c`?xu4j?0;6?u23`g924=:;k21ml5rs2`7>5<5s49i47o7;<1bg?063ty8n84?:3y>7db=>816?o65a89~w6d42909w0=m8;c4?85fj3<:7p}<b183>7}:;k21m9523`:924=z{8i<6=4<{<3`f?3e34;ho7;m;<3`=?b63ty:o94?:2y>5f>==k16=n85d09>5f?==k1v\7f<m>:180\7f87d;3n:70?l6;7a?87d=3?i7p}>e183>7}:9jn1h<521e;924=z{8hn6=4<{<3`4?b634;h?7;m;<3`6?3e3ty:no4?:2y>5ge=l816=n>55c9>5g`==k1v\7f<ln:180\7f87dm3<:70?md;f2?87ek3;:n6s|1bc94?4|58io68l4=0a`>a7<uz;on7>52z?2gc<1927:nk4k1:\7fp5a`=838p1<j8:73894ee2m;0q~?kc;296~;6l80==63>c38g5>{t9mn1<7<t=0f0>37<58i>6i?4}r3ga?6=:r7:o54k1:?2`0<192wx=;;50;0x94022m;01<;7:b28yv7013:1?v3>7e86f>;6?l0>n63>7c8g5>{t9><1<7=t=05b>0d<58=36i?4=05a>0d<uz;<?7>53z?230<c927:;54:b:?232<2j2wx=4<50;0x941a2m;01<6m:738yv7083:1?v3>738g5>;6?<0>n63>7586f>{t9?n1<7=t=04f>a7<58=968l4=052>0d<uz;=o7>53z?2<5<1927::k4k1:?22`<69k1v\7f<9l:181\7f870n3?i70?8e;f2?xu60m0;6?u2193924=:9>;1h<5rs0;2>5<5s4;3578>;<34`?b63ty:4h4?:3y>5=5=>816=::5d09~w4>a2909w0?75;42?870?3n:7p}>9183>7}:9>k1h<52195924=z{8h86=4={<3a7?b634;j:7m?;|q2a`<72:q6=k<55c9>5c5==k16=k>5d09~w4ce2908w0?jf;7a?87bl3n:70?i0;7a?xu6m10;6>u21dc9`4=:9ln19o521da91g=z{;:<6=4={<3e0?b6348;<78>;|q2a0<72:q6=h95d09>5`g==k16=h755c9~w4c52908w0?j3;f2?87b?3?i70?j6;7a?xu6m80;6>u21g7924=:9l>1h<521d1954d<uz;m=7>52z?2b1<2j27:j>4k1:\7fp654=838p1<h9:73894c12m;0q~<?6;296~;6nl0==63>f38g5>{t:991<7<t=0d;>37<58o26i?4}r030?6=:r7:jl491:?2af<c92wx>=;50;0x94ca2m;01<hl:738yv372909w0=83;`f?850:3n:7p}=7083>6}::?:1:<5231;9g4=:;921=<l4}r0;7?6=:r79494l1:?11`<192wx?;>50;0x960>2?;01>8>:e38yv7e<3:1>v3>998g5>;6i10==6s|26;94?4|5;?26;?4=35b>f7<uz9287>52z?133<192788:4k1:\7fp7<6=838p1>:>:e3896?62kh0q~=92;296~;4>:0o=63<6`855>{t;1i1<7<t=21;>a7<5:2o6ol4}r1;=?6=;r78?=4k1:?05g<ej279;l4md:\7fp72?=838p1>9n:e38961e2?;0q~<k4;291~;5l>0o=63=d98aa>;5l<0io63=db855>;5l?0io6s|37:94?c|5;2?6ol4=240>gd<5;2=6ol4=35`>gd<5;=36ol4=35f>gd<5;2;6ol4=3:1>gd<5:<36<>n;<151?de349==7lk;<152?dd349=;7lj;<04e?de3ty94<4?:3y>60b=>816>5<5c09~w6>b2909w0=<d;f2?85?n3hi7p}=e083>7}::m:1h<522g1924=z{;=m6=4={<06g?063483<7m>;|q0<2<72;q6?:o5bd9>7=4=l81v\7f?9k:181\7f842j3<:70<8e;a2?xu5?k0;6?u226a9g4=::<k1:<5rs3a1>5<4s48247lm;<0:g?dd348h57??a:\7fp6g5=838p1?ln:02b?84d03<:7p}>b683>7}:9h;1h<521`g924=z{;h;6=4={<0`1?06348i;7??a:\7fp7=>=838p1><l:e38971?2kn0q~?m6;296~;61l0o=63>ab855>{t9=<1<7=t=06b>0d<58>i68l4=064>a7<uz83j7>52z?063<c92794?4md:\7fp6f5=83>p1?77:ca897?02kh01?7l:cf897ef28:j7p}<8783>7}:;>k1no5236f9`4=z{8nj6=4={<3``?e734;om7j>;|q1ag<72;q6?=>5609>6c4=99k0q~?m8;296~;6i=0o=63>b1855>{t:l81<7<t=3ae>a7<5;l?6;?4}r77>5<5s493=7j>;<1;6?db3ty8:o4?:3y>73e=l816?;j5609~w7`72909w0=?5;42?84a?3;;m6s|39c94?4|5:9?6i?4=2:a>gd<uz8m57>52z?1`=<ej278<=4>0`9~w7c12909w0<k8;f2?84c13<:7p}<7983>7}:;?i1nn523619`4=z{83o6=4<{<3:b?b634;j=7;m;<3b6?3e3ty9484?:3y>60`=>816>585c09~w4d22909w0?6b;f2?87fi3<:7p}=9183>7}::1>1ni5233;9`4=z{:336=4={<167?b6349257lm;|q1e`<72;q6>4l5d09>6<`=>81v\7f>7l:181\7f852j3n:70=6d;`a?xu41;0;6?u23569`4=:;091no5rs2;5>5<5s49?j7j>;<1:3?de3ty9jo4?:5y>6a>=jm16>i;5bc9>754=99k01?j9:c`8yv5>i3:1>v3<568g5>;41k0in6s|38g94?4|5:?n6i?4=2;e>gd<uz8j57>52z?1fg<192795?4k1:\7fp14<72;q6?5<5bc9>7=3=l81v\7f?98:181\7f84203<:70<88;f2?xu50>0;6?u2273924=:;9h1h<5rs3:;>5<5s48=>78>;<13a?b63ty:n<4?:2y>5g7=l816=l:5c19>5d3=98h0q~<79;296~;5>:0==63<108g5>{t:h=1<7<t=3`:>37<5;3?6i?4}r0;e?6=:r79:9491:?051<c92wx?=j50;1x966a2m;01>?=:4`896762<h0q~=>3;297~;49>0>n63<148g5>;4910>n6s|29`94?4|5:;<6i?4=346>37<uz>n6=4={<147?dd349<87j>;|q053<72;q6>;85609>74>=l81v\7f?6l:181\7f840k3ho70=>d;f2?xu5?;0;6?u230`9g4=:;8k1=<l4}r0;`?6=:r79;h4md:?065<c92wx9;4?:3y>73`=jj16?:>5d09~w0>=838p1>8i:cg8960b2m;0q~;8:181\7f851n3ho70=81;f2?xu213:1>v3<818g5>;4?m0in6s|21394?4|58l?6n>4=322>a7<uz;3o7>52z?23c<d827:4n4k1:\7fp0f<72;q6?:j5bd9>72e=l81v\7f9l50;0x961c2kn01>9i:e38yv3f2909w0=8e;f2?850l3hh7p}:5;296~;4>o0in63<3`8g5>{t=:0;6?u23969`4=:;181ni5rs5d94?4|5:=86oj4=256>a7<uz;jh7>53z?2=c<69k16=4k5c19>5db=l81v\7f<;i:180\7f87293;:n63>518`4>;6=o0o=6s|1e:94?5|58ii6n>4=0a`>47e34;o47j>;|q2`5<72:q6=n>510`894da2j:01<j?:e38yv7c:3:1?v3>c2825g=:9j81o=521e09`4=z{8n?6=4<{<3`2?76j27:o84l0:?2`1<c92wx=i850;1x94e?2j:01<m6:03a?87c>3n:7p}>8`83>6}:9>n1o=5216g954d<582j6i?4}r3;6?6=;r7:;?4>1c9>527=k916=5<5d09~w4>32908w0?85;32f>;6?=0h<63>858g5>{t91<1<7=t=05;>47e34;<;7m?;<3;2?b63ty:454?:2y>52g=k916=:l510`894>?2m;0q~?if;297~;6n;0h<63>f2825g=:9ol1h<5rs0d4>5<4s4;n;7?>b:?2a3<d827:j:4k1:\7fp5c?=839p1<kn:03a?87b13i;70?i9;f2?xu6nk0;6>u21df954d<58oh6n>4=0da>a7<uz;mh7>53z?2ac<d827:j=4>1c9>5cb=l81v\7f<;k:180\7f873l3i;70?;e;32f>;6=m0o=6s|14`94?5|58>j6n>4=06a>47e34;>n7j>;|q226<72:q6=89510`894312j:01<8<:e38yv7193:1?v3>55825g=:9<91o=521739`4=z{ji1<7=t=21:>47e349847m?;<10f?e63ty85:4?:2y>75e=98h01>>m:b2896?02j;0q~=69;297~;48o0:=o5231g9g5=:;031o<5rs2;a>5<4s49:>7?>b:?054<d82785o4l1:\7fp7<b=839p1>?::03a?856<3i;70=6d;a2?xu41o0;6>u23059g5=:;821=<l4=2;e>f7<uz93n7>53z?05`<69k16?<j5c19>7=d=k81v\7f>6k:180\7f85593;:n63<218`4>;40m0h=6s|39d94?5|5:8?6<?m;<117?e73493j7m>;|q0=4<72:q6??9510`896412j:01>7>:b38yv5>;3:1?v3<288`4>;4:h0:=o523819g4=z{8ki6=4<{<3:f?e734;2o7?>b:?2eg<c92wx=l750;1x94??2j:01<76:03a?87f13n:7p}>ag83>6}:9h;1o=521`0954d<58km6i?4}|`272<7280;6=u+10d9f<=O9;80D<=9;n`;>5<<uz9h=7>52z\0g4=:9;:1hi5rs2`g>5<5sW9ih63>218g=>{t;m81<7<t^2f1?87583on7p}<f883>7}Y;o301<<?:034?xu4k;0;6?uQ3b0894472mo0q~?<f;296~X6;o16=?>5459~w6`e2909wS=ib:?265<69h1v\7f>hj:181\7f[5am27:>=4>299~w6b32909wS=k4:?265<a82wx>8;50;0xZ73234;9<7oj;|q0g1<72;qU?n:4=003>`6<uz>;57>52z\74<=:9;:1=>=4}r1eg?6=:rT8jn521329577<uz;8i7>52z\27`=:9;:18>5rs2ge>5<5sW9nj63>21824a=z{:io6=4={_1``>;6:90n56s|3c`94?4|V:hi70?=0;f1?xu4jl0;6?uQ3cg894472mk0q~=k6;296~X4l?16=?>5f39~w6`c2909wS=id:?265<6::1v\7f>o>:181\7f[5f927:>=4m7:\7fp7ge=838pR>ll;<314?b?3ty8oh4?:3y]7fc<588;6ho4}r1eb?6=:rT8jk52132957?<uz9o97>52z\0`0=:9;:1j<5rs2ae>5<5sW9hj63>218ff>{t;m:1<7<t^2f3?87583oh7p}<d683>7}Y;m=01<<?:g18yv5en3:1>vP<bg9>576=lk1v\7f>j7:181\7f[5c027:>=4i4:\7fp7f6=838pR>m?;<314?bd3ty9<54?:2y]65g<V;:370?<7;`;?xu4l80;6?uQ3e3894472ln0q~:?8;296~X38116=?>51208yv27>3:1>vP;079>576=9::0q~:?5;296~X38<16=?>513d8yv27<3:1>vP;059>576=9;o0q~:?3;296~X38:16=?>513f8yv27:3:1>vP;039>576=9;i0q~:?1;296~X38816=?>513`8yv2783:1>vP;019>576=9;k0q~<:4;296~X5==16=?>59`9~w7352909wS<:2:?265<>02wx>8?50;0xZ73634;9<778;|q115<72;qU>8>4=003><0<uz8?j7>52z\10c=:9;:1585rs36f>5<5sW8?i63>218:0>{t:=n1<7<t^36g?87583387p}=4b83>7}Y:=i01<<?:808yv5a03:1>vP<f99>576=98<0q~=i6;296~X4n?16=?>51068yv5a=3:1>vP<f49>576=9890q~=i4;296~X4n=16=?>51008yv5a;3:1>vP<f29>576=98;0q~=i2;296~X4n;16=?>51028yv5a93:1>vP<f09>576=99l0q~=i0;296~X4n916=?>511g8yv5dk3:1>vP<cb9>576=m11v\7f>mn:181\7f[5di27:>=4j6:\7fp7f?=838pR>m6;<314?c23ty8o54?:3y]7f><588;6h:4}r1`3?6=:rT8o:521329a6=z{:i=6=4={_1`2>;6:90n>6s|3b794?4|V:i>70?=0;g2?xu5<k0;6?uQ25`894472>l0q~<;9;296~X5<016=?>57e9~w72?2909wS<;8:?265<0k2wx>9950;0xZ72034;9<79m;|q103<72;qU>984=003>2g<uz8?97>52z\100=:9;:1;45rs367>5<5sW8?863>2184<>{t:=91<7<t^360?87583=<7p}<ee83>7}Y;ln01<<?:02:?xu4mk0;6?uQ3d`8944728:<7p}<e`83>7}Y;lk01<<?:025?xu4m00;6?uQ3d;8944728:>7p}<e983>7}Y;l201<<?:027?xu4m>0;6?uQ3d58944728:87p}<e783>7}Y;l<01<<?:021?xu4m<0;6?uQ3d78944728::7p}<e283>7}Y;l901<<?:gd8yv5b:3:1>vP<e39>576=nl1v\7f>k>:181\7f[5b927:>=4id:\7fp7`6=838pR>k?;<314?`d3ty8hk4?:3y]7a`<588;6kl4}r1ga?6=:rT8hh521329bd=z{:no6=4={_1g`>;6:90m56s|3e`94?4|V:ni70?=0;d4?xu4lh0;6?uQ3ec894472o<0q~=k9;296~X4l016=?>5f49~yk>b<3:1=vF>239~j=c2290:wE?=2:\7fm<`0=83;pD<<=;|l;a2<72;qC=?<4}o:f<?6=9rB:>?5rn9d2>5<>sA;9>6sa8dc94?4|@8897p`7eb83>4}O9;80qc6jd;296~N6:;1vb5kj:182\7fM75:2we4hh50;0xL4453td3j?4?:3yK574<ug2m?7>51zJ267=zf1l>6=4>{I316>{i0o<1<7?tH001?xh?n10;6?uG1308yk>ai3:1=vF>239~j=`e2909wE?=2:\7fm<cb=83;pD<<=;|l;b`<728qC=?<4}o:eb?6=9rB:>?5rn823>5<6sA;9>6sa91394?7|@8897p`60383>4}O9;80qc7?3;295~N6:;1vb4>;:182\7fM75:2we5=;50;0xL4453td2<;4?:3yK574<ug3;;7>52zJ267=zf0:36=4={I316>{i1931<7<tH001?xh>8h0;6?uG1308yk?7j3:1>vF>239~j<6d2909wE?=2:\7fm=5b=838pD<<=;|l:4`<72;qC=?<4}o;3b?6=:rB:>?5rn833>5<5sA;9>6sa90394?4|@8897p`61383>7}O9;80qc7>3;296~N6:;1vb4?;:181\7fM75:2we5<;50;0xL4453td2=;4?:3yK574<ug3:;7>52zJ267=zf0;36=4={I316>{i1831<7<tH001?xh>9h0;6?uG1308yk?6j3:1>vF>239~j<7d2909wE?=2:\7fm=4b=83;pD<<=;|l:5`<728qC=?<4}o;2b?6=9rB:>?5rn803>5<6sA;9>6sa93394?7|@8897p`62383>4}O9;80qc7=3;295~N6:;1vb4<;:181\7fM75:2we5?;50;0xL4453td2>;4?:3yK574<ug39;7>52zJ267=zf0836=4={I316>{i1;31<7<tH001?xh>:h0;6?uG1308yk?5j3:1>vF>239~j<4d290:wE?=2:\7fm=7b=83;pD<<=;|l:6`<728qC=?<4}o;1b?6=9rB:>?5rn813>5<6sA;9>6sa92394?7|@8897p`63383>4}O9;80qc7<3;295~N6:;1vb4=;:182\7fM75:2we5>;50;3xL4453td2?;4?:0yK574<ug38;7>51zJ267=zf0936=4>{I316>{i1:31<7?tH001?xh>;h0;6<uG1308yk?4j3:1=vF>239~j<5d290:wE?=2:\7fm=6b=83;pD<<=;|l432<728qC=?<4}o54f?6=9rB:>?5rn65`>5<6sA;9>6sa76f94?7|@8897p`87d83>4}O9;80qc98f;295~N6:;1vb:6?:182\7fM75:2Bo<6sa79394?7|@8897p`88283>4}O9;80qc974;295~N6:;1vb:6::182\7fM75:2we;5850;3xL4453td<4:4?:0yK574<ug=347>51zJ267=zf>2j6=4>{I316>{i?1h1<7?tH001?xh00m0;6<uG1308La6<ug=3i7>51zJ267=zf>3;6=4>{I316>{i?0;1<7?tH001?Mb73td<5?4?:0yK574<ug=2?7>51zJ267=zf>3>6=4>{I316>Nc82we;4950;3xL4453td<544?:0yK574<ug=2m7>51zJ267=zf>3m6=4>{I316>{i?h:1<7?tH001?xh0i80;6<uG1308yk1f:3:1=vF>239~j2g4290:wE?=2:\7fm3d2=83;pD<<=;If3?xh0i<0;6<uG1308yk1f>3:1=vF>239K`5=zf>ki6=4>{I316>{i?ho1<7?tH001?xh0j90;6<uG1308yk1e93:1=vF>239~j2d5290:wE?=2:Jg4>{i?k91<7?tH001?xh0j=0;6<uG1308yk1e=3:1=vF>239~j2d0290:wE?=2:Jg4>{i?kh1<7?tH001?xh0jj0;6<uG1308yk1el3:1=vF>239~j2da290:wE?=2:\7fm3f4=83;pD<<=;|l4g6<728qC=?<4}o5`2?6=9rB:>?5Gd19~j2e?290:wE?=2:\7fm3fg=83;pD<<=;|l4gg<728qC=?<4}o5`g?6=9rB:>?5rn6ag>5<6sA;9>6sa7bg94?7|@8897p`8cg83>4}O9;80qc9k0;295~N6:;1vb:j>:182\7fM75:2Bo<6sa7e094?7|@8897p`8d283>4}O9;80qc9k4;295~N6:;1vb:j::182\7fM75:2we;i850;3xL4453td<h:4?:0yK574<ug=o47>51zJ267=zf>n26=4>{I316>{i?mk1<7?tH001?xh0lk0;6<uG1308yk1ck3:1=vF>239~j2bc290:wE?=2:\7fm3ac=83;pD<<=;|l4`c<728qC=?<4}o5f4?6=9rB:>?5rn6g2>5<6sA;9>6sa7d094?7|@8897p`8e283>4}O9;80qc9j4;295~N6:;1vb:k::182\7fM75:2we;h850;3xL4453td<i:4?:0yK574<ug=n47>51zJ267=zf>o26=4>{I316>{i?lk1<7?tH001?xh0mk0;6<uG1308yk1bk3:1=vF>239~j2cc290:wE?=2:\7fm3`c=83;pD<<=;|l4ac<728qC=?<4}o5e4?6=9rB:>?5rn6d2>5<6sA;9>6sa7g094?7|@8897p`8f283>4}O9;80qc9i4;295~N6:;1vb:h::182\7fM75:2we;k850;3xL4453td<j:4?:0yK574<ug=m47>51zJ267=Ol91vb:h6:182\7fM75:2we;ko50;3xL4453td<jo4?:0yK574<ug=mo7>51zJ267=zf>lo6=4>{I316>{i?oo1<7?tH001?xh0no0;6<uG1308yk>783:1=vF>239~j=66290:wE?=2:\7fm<54=83;pD<<=;|l;46<728qC=?<4}o:30?6=9rB:>?5rn926>5<6sA;9>6sa81494?7|@8897p`70683>4}O9;80qc6?8;295~N6:;1vb5>6:182\7fM75:2we4=o50;3xL4453td3<o4?:0yK574<ug2;o7>51zJ267=zf1:o6=4>{I316>{i09o1<7?tH001?xh?8o0;6<uG1308yk>683:1=vF>239~j=76290:wE?=2:\7fm<44=83;pD<<=;|l;56<728qC=?<4}o:20?6=9rB:>?5rn936>5<6sA;9>6sa80494?7|@8897p`71683>4}O9;80qc6>8;295~N6:;1vb5?6:182\7fM75:2we4<o50;3xL4453td3=o4?:0yK574<ug2:o7>51zJ267=zf1;o6=4>{I316>{i08o1<7?tH001?xh?9o0;6<uG1308yk>583:1=vF>239~j=46290:wE?=2:\7fm<74=83;pD<<=;|l;66<728qC=?<4}o:10?6=9rB:>?5rn906>5<6sA;9>6Fk0:\7fm<70=83;pD<<=;If3?xh?:>0;6<uG1308yk>483:1=vF>239K`5=zf19:6=4>{I316>{i0:81<7?tH001?xh?;:0;6<uG1308yk>4<3:1=vF>239~j=52290:wE?=2:\7fm<60=83;pD<<=;|l;72<728qC=?<4}o:0<?6=9rB:>?5rn91:>5<6sA;9>6sa82c94?7|@8897p`73c83>4}O9;80qc6<c;295~N6:;1vb5=k:182\7fM75:2we4>k50;3xL4453td3?k4?:0yK574<ug2?<7>51zJ267=zf1>:6=4>{I316>{i0=81<7?tH001?xh?<:0;6<uG1308yk>3<3:1=vF>239~j=22290:wE?=2:\7fm<10=83;pD<<=;|l;02<728qC=?<4}o:7<?6=9rB:>?5rn96:>5<6sA;9>6sa85c94?7|@8897p`74c83>4}O9;80qc6;c;295~N6:;1vb5:k:182\7fM75:2we49k50;3xL4453td38k4?:0yK574<ug2><7>51zJ267=zf1?:6=4>{I316>{i0<81<7?tH001?xh?=:0;6<uG1308yk>2<3:1=vF>239~j=32290:wE?=2:\7fm<00=83;pD<<=;|l;12<728qC=?<4}o:6<?6=9rB:>?5rn97:>5<6sA;9>6sa84c94?7|@8897p`75c83>4}O9;80qc6:c;295~N6:;1vb5;k:182\7fM75:2we48k50;3xL4453td39k4?:0yK574<ug2=<7>51zJ267=zf1<:6=4>{I316>{i0?81<7?tH001?xh?>:0;6<uG1308yk>1<3:1=vF>239~j=02290:wE?=2:\7fm<30=83;pD<<=;|l;22<728qC=?<4}o:5<?6=9rB:>?5rn94:>5<6sA;9>6sa87c94?7|@8897p`76c83>4}O9;80qc69c;295~N6:;1vb58k:182\7fM75:2we4;k50;3xL4453td3:k4?:0yK574<ug2<<7>51zJ267=zf1=:6=4>{I316>{i0>81<7?tH001?xh??:0;6<uG1308yk>0<3:1=vF>239~j=12290:wE?=2:\7fm<20=83;pD<<=;|l;32<728qC=?<4}o:4<?6=9rB:>?5rn95:>5<6sA;9>6sa86c94?7|@8897p`77c83>4}O9;80qc68c;295~N6:;1vb59k:182\7fM75:2we4:k50;3xL4453td3;k4?:0yK574<ug23<7>51zJ267=zf12:6=4>{I316>{i0181<7?tH001?Mb73td34>4?:0yK574<ug2387>51zJ267=Ol91vb56::182\7fM75:2we45850;3xL4453td34:4?:0yK574<ug2347>51zJ267=zf1226=4>{I316>{i01k1<7?tH001?xh?0k0;6<uG1308yk>?k3:1=vF>239K`5=zf12o6=4>{I316>{i01o1<7?tH001?xh?0o0;6<uG1308yk>>83:1=vF>239~j=?6290:wE?=2:Jg4>{i0081<7?tH001?xh?1:0;6<uG1308yk>><3:1=vF>239~j=?2290:wE?=2:\7fm<<0=83;pD<<=;|l;=2<728qC=?<4}o::<?6=9rB:>?5rn9;:>5<6sA;9>6sa88c94?7|@8897p`79c83>4}O9;80qc66c;295~N6:;1vb57k:182\7fM75:2we44k50;3xL4453td35k4?:0yK574<ug2j<7>51zJ267=zf1k:6=4>{I316>{i0h81<7?tH001?xh?i:0;6<uG1308yk>f<3:1=vF>239~j=g2290:wE?=2:\7fm<d0=83;pD<<=;|l;e2<728qC=?<4}o:b<?6=9rB:>?5rn9c:>5<6sA;9>6sa8`c94?7|@8897p`7ac83>4}O9;80qc6nc;295~N6:;1vb5ok:182\7fM75:2we4lk50;3xL4453td3mk4?:0yK574<ug2i<7>51zJ267=zf1h:6=4>{I316>{i0k81<7?tH001?xh?j:0;6<uG1308yk>e<3:1=vF>239~j=d2290:wE?=2:\7fm<g0=83;pD<<=;|l;f2<728qC=?<4}o:a<?6=9rB:>?5rn9`:>5<6sA;9>6sa8cc94?7|@8897p`7bc83>4}O9;80qc6mc;295~N6:;1vb5lk:182\7fM75:2we4ok50;3xL4453td3nk4?:0yK574<ug2h<7>51zJ267=zf1i:6=4>{I316>{i0j81<7?tH001?xh?k:0;6<uG1308yk>d<3:1=vF>239~j=e2290:wE?=2:\7fm<f0=83;pD<<=;|l;g2<728qC=?<4}o:`<?6=9rB:>?5rn9a:>5<6sA;9>6sa8bc94?7|@8897p`7cc83>4}O9;80qc6lc;295~N6:;1vb5mk:182\7fM75:2we4nk50;3xL4453td3ok4?:0yK574<ug2o<7>51zJ267=zf1n:6=4>{I316>{i0m81<7?tH001?xh?l:0;6<uG1308yk>c<3:1=vF>239~j=b2290:wE?=2:\7fm<a0=83;pD<<=;|l;`2<728qC=?<4}o:g<?6=9rB:>?5rn9f:>5<6sA;9>6sa8ec94?7|@8897p`7dc83>4}O9;80qc6kc;295~N6:;1vb5jk:182\7fM75:2we4ik50;3xL4453td3hk4?:0yK574<ug2n<7>51zJ267=zf1o:6=4>{I316>{zutJKOvok4;44<3gaj<wKLOu?}ABS\7fxFG
\ No newline at end of file
diff --git a/bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn b/bee2-selectmap/async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst.edn
new file mode 100644 (file)
index 0000000..4c68cbb
--- /dev/null
@@ -0,0 +1,576 @@
+(edif test (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0))
+(status (written (timeStamp 2006 2 18 19 6 6)
+   (author "Xilinx, Inc.")
+   (program "Xilinx CORE Generator" (version "Xilinx CORE Generator 7.1.04i; Cores Update # 3"))))
+   (comment "                                                                                
+      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-2005 Xilinx, Inc.                                      
+      All rights reserved.                                                      
+                                                                                
+   ")
+   (comment "Core parameters: ")
+       (comment "c_reg_inputsb = 0 ")
+       (comment "c_reg_inputsa = 0 ")
+       (comment "c_has_ndb = 0 ")
+       (comment "c_has_nda = 0 ")
+       (comment "c_ytop_addr = 1024 ")
+       (comment "c_has_rfdb = 0 ")
+       (comment "c_has_rfda = 0 ")
+       (comment "c_ywea_is_high = 1 ")
+       (comment "c_yena_is_high = 1 ")
+       (comment "InstanceName = async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst ")
+       (comment "c_yhierarchy = hierarchy1 ")
+       (comment "c_yclka_is_rising = 1 ")
+       (comment "c_family = virtex2p ")
+       (comment "c_ysinita_is_high = 1 ")
+       (comment "c_ybottom_addr = 0 ")
+       (comment "c_width_b = 8 ")
+       (comment "c_width_a = 8 ")
+       (comment "c_sinita_value = 0000 ")
+       (comment "c_sinitb_value = 00 ")
+       (comment "c_limit_data_pitch = 18 ")
+       (comment "c_write_modeb = 0 ")
+       (comment "c_write_modea = 0 ")
+       (comment "c_has_rdyb = 0 ")
+       (comment "c_yuse_single_primitive = 0 ")
+       (comment "c_has_rdya = 0 ")
+       (comment "c_addra_width = 7 ")
+       (comment "c_addrb_width = 7 ")
+       (comment "c_has_limit_data_pitch = 0 ")
+       (comment "c_default_data = 0000 ")
+       (comment "c_pipe_stages_b = 0 ")
+       (comment "c_yweb_is_high = 1 ")
+       (comment "c_yenb_is_high = 1 ")
+       (comment "c_pipe_stages_a = 0 ")
+       (comment "c_yclkb_is_rising = 1 ")
+       (comment "c_yydisable_warnings = 1 ")
+       (comment "c_enable_rlocs = 0 ")
+       (comment "c_ysinitb_is_high = 1 ")
+       (comment "c_has_web = 0 ")
+       (comment "c_has_default_data = 1 ")
+       (comment "c_has_wea = 1 ")
+       (comment "c_has_sinitb = 1 ")
+       (comment "c_has_sinita = 1 ")
+       (comment "c_has_dinb = 0 ")
+       (comment "c_has_dina = 1 ")
+       (comment "c_ymake_bmm = 0 ")
+       (comment "c_has_enb = 1 ")
+       (comment "c_has_ena = 0 ")
+       (comment "c_mem_init_file = mif_file_16_1 ")
+       (comment "c_depth_b = 128 ")
+       (comment "c_depth_a = 128 ")
+       (comment "c_has_doutb = 1 ")
+       (comment "c_has_douta = 0 ")
+       (comment "c_yprimitive_type = 4kx4 ")
+   (external xilinxun (edifLevel 0)
+      (technology (numberDefinition))
+       (cell VCC (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port P (direction OUTPUT))
+               )
+           )
+       )
+       (cell GND (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port G (direction OUTPUT))
+               )
+           )
+       )
+       (cell RAMB16_S9_S9 (cellType GENERIC)
+           (view view_1 (viewType NETLIST)
+               (interface
+                   (port WEA (direction INPUT))
+                   (port ENA (direction INPUT))
+                   (port SSRA (direction INPUT))
+                   (port CLKA (direction INPUT))
+                   (port (rename DIA_0_ "DIA<0>") (direction INPUT))
+                   (port (rename DIA_1_ "DIA<1>") (direction INPUT))
+                   (port (rename DIA_2_ "DIA<2>") (direction INPUT))
+                   (port (rename DIA_3_ "DIA<3>") (direction INPUT))
+                   (port (rename DIA_4_ "DIA<4>") (direction INPUT))
+                   (port (rename DIA_5_ "DIA<5>") (direction INPUT))
+                   (port (rename DIA_6_ "DIA<6>") (direction INPUT))
+                   (port (rename DIA_7_ "DIA<7>") (direction INPUT))
+                   (port (rename DOA_0_ "DOA<0>") (direction OUTPUT))
+                   (port (rename DOA_1_ "DOA<1>") (direction OUTPUT))
+                   (port (rename DOA_2_ "DOA<2>") (direction OUTPUT))
+                   (port (rename DOA_3_ "DOA<3>") (direction OUTPUT))
+                   (port (rename DOA_4_ "DOA<4>") (direction OUTPUT))
+                   (port (rename DOA_5_ "DOA<5>") (direction OUTPUT))
+                   (port (rename DOA_6_ "DOA<6>") (direction OUTPUT))
+                   (port (rename DOA_7_ "DOA<7>") (direction OUTPUT))
+                   (port (rename ADDRA_0_ "ADDRA<0>") (direction INPUT))
+                   (port (rename ADDRA_1_ "ADDRA<1>") (direction INPUT))
+                   (port (rename ADDRA_2_ "ADDRA<2>") (direction INPUT))
+                   (port (rename ADDRA_3_ "ADDRA<3>") (direction INPUT))
+                   (port (rename ADDRA_4_ "ADDRA<4>") (direction INPUT))
+                   (port (rename ADDRA_5_ "ADDRA<5>") (direction INPUT))
+                   (port (rename ADDRA_6_ "ADDRA<6>") (direction INPUT))
+                   (port (rename ADDRA_7_ "ADDRA<7>") (direction INPUT))
+                   (port (rename ADDRA_8_ "ADDRA<8>") (direction INPUT))
+                   (port (rename ADDRA_9_ "ADDRA<9>") (direction INPUT))
+                   (port (rename ADDRA_10_ "ADDRA<10>") (direction INPUT))
+                   (port (rename DIPA_0_ "DIPA<0>") (direction INPUT))
+                   (port (rename DOPA_0_ "DOPA<0>") (direction OUTPUT))
+                   (port WEB (direction INPUT))
+                   (port ENB (direction INPUT))
+                   (port SSRB (direction INPUT))
+                   (port CLKB (direction INPUT))
+                   (port (rename DIB_0_ "DIB<0>") (direction INPUT))
+                   (port (rename DIB_1_ "DIB<1>") (direction INPUT))
+                   (port (rename DIB_2_ "DIB<2>") (direction INPUT))
+                   (port (rename DIB_3_ "DIB<3>") (direction INPUT))
+                   (port (rename DIB_4_ "DIB<4>") (direction INPUT))
+                   (port (rename DIB_5_ "DIB<5>") (direction INPUT))
+                   (port (rename DIB_6_ "DIB<6>") (direction INPUT))
+                   (port (rename DIB_7_ "DIB<7>") (direction INPUT))
+                   (port (rename DOB_0_ "DOB<0>") (direction OUTPUT))
+                   (port (rename DOB_1_ "DOB<1>") (direction OUTPUT))
+                   (port (rename DOB_2_ "DOB<2>") (direction OUTPUT))
+                   (port (rename DOB_3_ "DOB<3>") (direction OUTPUT))
+                   (port (rename DOB_4_ "DOB<4>") (direction OUTPUT))
+                   (port (rename DOB_5_ "DOB<5>") (direction OUTPUT))
+                   (port (rename DOB_6_ "DOB<6>") (direction OUTPUT))
+                   (port (rename DOB_7_ "DOB<7>") (direction OUTPUT))
+                   (port (rename ADDRB_0_ "ADDRB<0>") (direction INPUT))
+                   (port (rename ADDRB_1_ "ADDRB<1>") (direction INPUT))
+                   (port (rename ADDRB_2_ "ADDRB<2>") (direction INPUT))
+                   (port (rename ADDRB_3_ "ADDRB<3>") (direction INPUT))
+                   (port (rename ADDRB_4_ "ADDRB<4>") (direction INPUT))
+                   (port (rename ADDRB_5_ "ADDRB<5>") (direction INPUT))
+                   (port (rename ADDRB_6_ "ADDRB<6>") (direction INPUT))
+                   (port (rename ADDRB_7_ "ADDRB<7>") (direction INPUT))
+                   (port (rename ADDRB_8_ "ADDRB<8>") (direction INPUT))
+                   (port (rename ADDRB_9_ "ADDRB<9>") (direction INPUT))
+                   (port (rename ADDRB_10_ "ADDRB<10>") (direction INPUT))
+                   (port (rename DIPB_0_ "DIPB<0>") (direction INPUT))
+                   (port (rename DOPB_0_ "DOPB<0>") (direction OUTPUT))
+               )
+           )
+       )
+   )
+(library test_lib (edifLevel 0) (technology (numberDefinition (scale 1 (E 1 -12) (unit Time))))
+(cell async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst
+ (cellType GENERIC) (view view_1 (viewType NETLIST)
+  (interface
+   (port ( rename dina_7_ "dina<7>") (direction INPUT))
+   (port ( rename dina_6_ "dina<6>") (direction INPUT))
+   (port ( rename dina_5_ "dina<5>") (direction INPUT))
+   (port ( rename dina_4_ "dina<4>") (direction INPUT))
+   (port ( rename dina_3_ "dina<3>") (direction INPUT))
+   (port ( rename dina_2_ "dina<2>") (direction INPUT))
+   (port ( rename dina_1_ "dina<1>") (direction INPUT))
+   (port ( rename dina_0_ "dina<0>") (direction INPUT))
+   (port ( rename dinb_7_ "dinb<7>") (direction INPUT))
+   (port ( rename dinb_6_ "dinb<6>") (direction INPUT))
+   (port ( rename dinb_5_ "dinb<5>") (direction INPUT))
+   (port ( rename dinb_4_ "dinb<4>") (direction INPUT))
+   (port ( rename dinb_3_ "dinb<3>") (direction INPUT))
+   (port ( rename dinb_2_ "dinb<2>") (direction INPUT))
+   (port ( rename dinb_1_ "dinb<1>") (direction INPUT))
+   (port ( rename dinb_0_ "dinb<0>") (direction INPUT))
+   (port ( rename ena "ena") (direction INPUT))
+   (port ( rename enb "enb") (direction INPUT))
+   (port ( rename wea "wea") (direction INPUT))
+   (port ( rename web "web") (direction INPUT))
+   (port ( rename sinita "sinita") (direction INPUT))
+   (port ( rename sinitb "sinitb") (direction INPUT))
+   (port ( rename nda "nda") (direction INPUT))
+   (port ( rename ndb "ndb") (direction INPUT))
+   (port ( rename clka "clka") (direction INPUT))
+   (port ( rename clkb "clkb") (direction INPUT))
+   (port ( rename addra_6_ "addra<6>") (direction INPUT))
+   (port ( rename addra_5_ "addra<5>") (direction INPUT))
+   (port ( rename addra_4_ "addra<4>") (direction INPUT))
+   (port ( rename addra_3_ "addra<3>") (direction INPUT))
+   (port ( rename addra_2_ "addra<2>") (direction INPUT))
+   (port ( rename addra_1_ "addra<1>") (direction INPUT))
+   (port ( rename addra_0_ "addra<0>") (direction INPUT))
+   (port ( rename addrb_6_ "addrb<6>") (direction INPUT))
+   (port ( rename addrb_5_ "addrb<5>") (direction INPUT))
+   (port ( rename addrb_4_ "addrb<4>") (direction INPUT))
+   (port ( rename addrb_3_ "addrb<3>") (direction INPUT))
+   (port ( rename addrb_2_ "addrb<2>") (direction INPUT))
+   (port ( rename addrb_1_ "addrb<1>") (direction INPUT))
+   (port ( rename addrb_0_ "addrb<0>") (direction INPUT))
+   (port ( rename rdya "rdya") (direction OUTPUT))
+   (port ( rename rdyb "rdyb") (direction OUTPUT))
+   (port ( rename rfda "rfda") (direction OUTPUT))
+   (port ( rename rfdb "rfdb") (direction OUTPUT))
+   (port ( rename douta_7_ "douta<7>") (direction OUTPUT))
+   (port ( rename douta_6_ "douta<6>") (direction OUTPUT))
+   (port ( rename douta_5_ "douta<5>") (direction OUTPUT))
+   (port ( rename douta_4_ "douta<4>") (direction OUTPUT))
+   (port ( rename douta_3_ "douta<3>") (direction OUTPUT))
+   (port ( rename douta_2_ "douta<2>") (direction OUTPUT))
+   (port ( rename douta_1_ "douta<1>") (direction OUTPUT))
+   (port ( rename douta_0_ "douta<0>") (direction OUTPUT))
+   (port ( rename doutb_7_ "doutb<7>") (direction OUTPUT))
+   (port ( rename doutb_6_ "doutb<6>") (direction OUTPUT))
+   (port ( rename doutb_5_ "doutb<5>") (direction OUTPUT))
+   (port ( rename doutb_4_ "doutb<4>") (direction OUTPUT))
+   (port ( rename doutb_3_ "doutb<3>") (direction OUTPUT))
+   (port ( rename doutb_2_ "doutb<2>") (direction OUTPUT))
+   (port ( rename doutb_1_ "doutb<1>") (direction OUTPUT))
+   (port ( rename doutb_0_ "doutb<0>") (direction OUTPUT))
+   )
+  (contents
+   (instance VCC (viewRef view_1 (cellRef VCC  (libraryRef xilinxun))))
+   (instance GND (viewRef view_1 (cellRef GND  (libraryRef xilinxun))))
+   (instance (rename async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8 "async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst/bm/mem/arch_v2/prim/3/b1/chk0/col/0/b2/mextd/arch_v2/c1/ram1/v2/d2048/by9/newSim8")
+      (viewRef view_1 (cellRef RAMB16_S9_S9 (libraryRef xilinxun)))
+      (property INIT_00 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_01 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_02 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_03 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_04 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_05 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_06 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_07 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_08 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_09 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_0F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_10 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_11 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_12 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_13 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_14 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_15 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_16 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_17 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_18 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_19 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_1F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_20 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_21 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_22 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_23 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_24 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_25 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_26 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_27 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_28 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_29 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_2F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_30 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_31 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_32 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_33 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_34 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_35 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_36 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_37 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_38 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_39 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3A (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3B (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3C (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3D (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3E (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INIT_3F (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_00 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_01 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_02 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_03 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_04 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_05 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_06 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property INITP_07 (string "0000000000000000000000000000000000000000000000000000000000000000"))
+      (property WRITE_MODE_A (string "WRITE_FIRST"))
+      (property INIT_A (string "000"))
+      (property SRVAL_A (string "000"))
+      (property WRITE_MODE_B (string "WRITE_FIRST"))
+      (property INIT_B (string "000"))
+      (property SRVAL_B (string "000"))
+   )
+   (net (rename N0 "Gnd")
+    (joined
+      (portRef G (instanceRef GND))
+      (portRef WEB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_8_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_9_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRA_10_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIPA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_8_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_9_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef ADDRB_10_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+      (portRef DIPB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N1 "Vcc")
+    (joined
+      (portRef P (instanceRef VCC))
+      (portRef ENA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N2 "dina<7>")
+    (joined
+      (portRef dina_7_)
+      (portRef DIA_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N3 "dina<6>")
+    (joined
+      (portRef dina_6_)
+      (portRef DIA_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N4 "dina<5>")
+    (joined
+      (portRef dina_5_)
+      (portRef DIA_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N5 "dina<4>")
+    (joined
+      (portRef dina_4_)
+      (portRef DIA_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N6 "dina<3>")
+    (joined
+      (portRef dina_3_)
+      (portRef DIA_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N7 "dina<2>")
+    (joined
+      (portRef dina_2_)
+      (portRef DIA_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N8 "dina<1>")
+    (joined
+      (portRef dina_1_)
+      (portRef DIA_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N9 "dina<0>")
+    (joined
+      (portRef dina_0_)
+      (portRef DIA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N19 "enb")
+    (joined
+      (portRef enb)
+      (portRef ENB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N20 "wea")
+    (joined
+      (portRef wea)
+      (portRef WEA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N22 "sinita")
+    (joined
+      (portRef sinita)
+      (portRef SSRA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N23 "sinitb")
+    (joined
+      (portRef sinitb)
+      (portRef SSRB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N26 "clka")
+    (joined
+      (portRef clka)
+      (portRef CLKA (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N27 "clkb")
+    (joined
+      (portRef clkb)
+      (portRef CLKB (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N28 "addra<6>")
+    (joined
+      (portRef addra_6_)
+      (portRef ADDRA_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N29 "addra<5>")
+    (joined
+      (portRef addra_5_)
+      (portRef ADDRA_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N30 "addra<4>")
+    (joined
+      (portRef addra_4_)
+      (portRef ADDRA_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N31 "addra<3>")
+    (joined
+      (portRef addra_3_)
+      (portRef ADDRA_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N32 "addra<2>")
+    (joined
+      (portRef addra_2_)
+      (portRef ADDRA_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N33 "addra<1>")
+    (joined
+      (portRef addra_1_)
+      (portRef ADDRA_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N34 "addra<0>")
+    (joined
+      (portRef addra_0_)
+      (portRef ADDRA_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N35 "addrb<6>")
+    (joined
+      (portRef addrb_6_)
+      (portRef ADDRB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N36 "addrb<5>")
+    (joined
+      (portRef addrb_5_)
+      (portRef ADDRB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N37 "addrb<4>")
+    (joined
+      (portRef addrb_4_)
+      (portRef ADDRB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N38 "addrb<3>")
+    (joined
+      (portRef addrb_3_)
+      (portRef ADDRB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N39 "addrb<2>")
+    (joined
+      (portRef addrb_2_)
+      (portRef ADDRB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N40 "addrb<1>")
+    (joined
+      (portRef addrb_1_)
+      (portRef ADDRB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N41 "addrb<0>")
+    (joined
+      (portRef addrb_0_)
+      (portRef ADDRB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N54 "doutb<7>")
+    (joined
+      (portRef doutb_7_)
+      (portRef DOB_7_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N55 "doutb<6>")
+    (joined
+      (portRef doutb_6_)
+      (portRef DOB_6_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N56 "doutb<5>")
+    (joined
+      (portRef doutb_5_)
+      (portRef DOB_5_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N57 "doutb<4>")
+    (joined
+      (portRef doutb_4_)
+      (portRef DOB_4_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N58 "doutb<3>")
+    (joined
+      (portRef doutb_3_)
+      (portRef DOB_3_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N59 "doutb<2>")
+    (joined
+      (portRef doutb_2_)
+      (portRef DOB_2_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N60 "doutb<1>")
+    (joined
+      (portRef doutb_1_)
+      (portRef DOB_1_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+   (net (rename N61 "doutb<0>")
+    (joined
+      (portRef doutb_0_)
+      (portRef DOB_0_ (instanceRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst_bm_mem_arch_v2_prim_3_b1_chk0_col_0_b2_mextd_arch_v2_c1_ram1_v2_d2048_by9_newSim8))
+    )
+   )
+))))
+(design async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst (cellRef async_fifo_8_8_128_fifo_generator_v2_2_xst_1_blkmemdp_v6_2_xst (libraryRef test_lib))
+  (property X_CORE_INFO (string "null"))
+  (property PART (string "XC2VP20-6-ff896") (owner "Xilinx")))
+)
diff --git a/bee2-selectmap/main.ucf b/bee2-selectmap/main.ucf
new file mode 100644 (file)
index 0000000..59d4b9a
--- /dev/null
@@ -0,0 +1,33 @@
+######################################
+## System clock pins
+######################################
+
+NET User_Clk PERIOD=100MHz;
+
+NET Clkin_p            LOC = AP21 | IOSTANDARD = LVDS_25;
+NET Clkin_m            LOC = AN21 | IOSTANDARD = LVDS_25;
+
+######################################
+## SelectMAP interface pins
+######################################
+
+NET D_I<0>             LOC = AU9  | IOSTANDARD = LVCMOS25;
+NET D_I<1>             LOC = AV9  | IOSTANDARD = LVCMOS25;
+NET D_I<2>             LOC = AY9  | IOSTANDARD = LVCMOS25;
+NET D_I<3>             LOC = AW9  | IOSTANDARD = LVCMOS25;
+NET D_I<4>             LOC = AW34 | IOSTANDARD = LVCMOS25;
+NET D_I<5>             LOC = AY34 | IOSTANDARD = LVCMOS25;
+NET D_I<6>             LOC = AV34 | IOSTANDARD = LVCMOS25;
+NET D_I<7>             LOC = AU34 | IOSTANDARD = LVCMOS25;
+
+NET RDWR_B             LOC = AR34 | IOSTANDARD = LVCMOS25;
+NET CS_B               LOC = AT34 | IOSTANDARD = LVCMOS25;
+NET INIT_B             LOC = AR9  | IOSTANDARD = LVCMOS25;
+NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
+
+NET gpleds<1>                       LOC = AB6   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<2>                       LOC = AB7   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<3>                       LOC = AB9   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<4>                       LOC = AB10  | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<5>                       LOC = AD7   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
+NET gpleds<6>                       LOC = AF1   | IOSTANDARD = LVCMOS18 | DRIVE = 24;
diff --git a/bee2-selectmap/main.ut b/bee2-selectmap/main.ut
new file mode 100644 (file)
index 0000000..8ea3a85
--- /dev/null
@@ -0,0 +1,37 @@
+-w
+-g DebugBitstream:No
+-g Binary:no
+-g CRC:Enable
+-g ConfigRate:4
+-g CclkPin:PullUp
+-g M0Pin:PullUp
+-g M1Pin:PullUp
+-g M2Pin:PullUp
+-g ProgPin:PullUp
+-g DonePin:PullUp
+-g PowerdownPin:PullUp
+-g TckPin:PullUp
+-g TdiPin:PullUp
+-g TdoPin:PullNone
+-g TmsPin:PullUp
+-g UnusedPin:PullDown
+-g UserID:0xFFFFFFFF
+-g DCMShutdown:Disable
+-g DisableBandgap:No
+-g DCIUpdateMode:AsRequired
+-g StartUpClk:CClk
+-g DONE_cycle:4
+-g GTS_cycle:5
+-g GWE_cycle:6
+-g LCK_cycle:NoWait
+-g Security:None
+-g DonePipe:No
+-g DriveDone:No
+-g Encrypt:No
+
+
+
+
+
+
+
diff --git a/bee2-selectmap/main.v b/bee2-selectmap/main.v
new file mode 100644 (file)
index 0000000..ff3930d
--- /dev/null
@@ -0,0 +1,429 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+
+   root my_root(User_Clk,
+                read_empty, read_enable, read_data,
+                write_full, write_enable, write_data);
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/main.xst b/bee2-selectmap/main.xst
new file mode 100644 (file)
index 0000000..f9a4f09
--- /dev/null
@@ -0,0 +1,4 @@
+set -tmpdir ./tmp
+set -xsthdpdir ./xst
+run
+-ifn main.prj -ifmt mixed -ofn main -ofmt NGC -p xc2vp70-6-ff1704 -top main -opt_mode Speed -opt_level 1 -iuc NO -lso main.lso -keep_hierarchy NO -rtlview Yes -glob_opt AllClockNets -read_cores YES -write_timing_constraints NO -cross_clock_analysis NO -hierarchy_separator / -bus_delimiter <> -case maintain -slice_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 -rom_style Auto -mux_extract NO -resource_sharing YES -mult_style auto -iobuf YES -max_fanout 500 -bufg 1 -register_duplication YES -register_balancing No -slice_packing No -optimize_primitives NO -tristate2logic Yes -use_clock_enable Yes -use_sync_set Yes -use_sync_reset Yes -iob auto -equivalent_register_removal YES -slice_utilization_ratio_maxmargin 5 
diff --git a/bee2-selectmap/main_counterexample_map0.v b/bee2-selectmap/main_counterexample_map0.v
new file mode 100644 (file)
index 0000000..7479ce1
--- /dev/null
@@ -0,0 +1,444 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds,
+   terminal
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+   reg read_enable_;
+   assign read_enable = read_enable_;
+   inout [33:0] terminal;
+   
+   always @(posedge User_Clk) begin
+     if (!read_enable && !read_empty) begin
+      read_enable_ <= 1;
+    end else begin
+      read_enable_  <= 0;
+    end
+   end
+   Maps_Bee2_Map0 map (.Clock(User_Clk),
+                       ._SW(1'b0),
+                       ._BTN(~read_enable_),
+                       .__TERMINAL_SynchronousLink_Pins(terminal));
+       
+//synthesis attribute LOC of terminal is "AT13,AR13,AV13,AU13,AW13,AY13,AL15,AL14,AV15,AU15,AY14,AY15,AM16,AL16,AP16,AN16,AR16,AT16,AV16,AU16,AL18,AL17,AM17,AN17,AR17,AP17,AU17,AT17,AW16,AW17,AN18,AM18,AT18,AR18"
+              
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/main_counterexample_map1.v b/bee2-selectmap/main_counterexample_map1.v
new file mode 100644 (file)
index 0000000..bc5a6ca
--- /dev/null
@@ -0,0 +1,437 @@
+`timescale 1ps / 1ps
+
+//  Copyright (c) 2005-2006, Regents of the University of California
+//  All rights reserved.
+//
+//  Redistribution and use in source and binary forms, with or without modification,
+//  are permitted provided that the following conditions are met:
+//
+//      - Redistributions of source code must retain the above copyright notice,
+//          this list of conditions and the following disclaimer.
+//      - Redistributions in binary form must reproduce the above copyright
+//          notice, this list of conditions and the following disclaimer
+//          in the documentation and/or other materials provided with the
+//          distribution.
+//      - Neither the name of the University of California, Berkeley nor the
+//          names of its contributors may be used to endorse or promote
+//          products derived from this software without specific prior
+//          written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+//----------------------------------------------------------------------------
+// user_fifo.v
+//----------------------------------------------------------------------------
+
+`timescale 1ps / 1ps
+
+module user_fifo
+  (
+   // FIFO interface ports
+   WrFifo_Din,                  // Write FIFO data-in
+   WrFifo_WrEn,                 // Write FIFO write enable
+   WrFifo_Full,                 // Write FIFO full
+   WrFifo_WrCnt,                // Write FIFO write count
+   RdFifo_Dout,                 // Read FIFO data-out
+   RdFifo_RdEn,                 // Read FIFO read enable
+   RdFifo_Empty,                // Read FIFO empty
+   RdFifo_RdCnt,                // Read FIFO read count
+   User_Rst,                    // User reset
+   User_Clk,                    // User clock
+   Sys_Rst,                     // System clock reset
+   Sys_Clk,                     // 100MHz system clock for CCLK generation
+
+   // SelectMAP interface ports
+   D_I,                         // Data bus input
+   D_O,                         // Data bus output
+   D_T,                         // Data bus tristate enable
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK                         // CCLK output
+   );
+
+   // FIFO interface ports
+   input [0:7]         WrFifo_Din;
+   input               WrFifo_WrEn;
+   output              WrFifo_Full;
+   output [0:7]        WrFifo_WrCnt;
+   output [0:7]        RdFifo_Dout;
+   input               RdFifo_RdEn;
+   output              RdFifo_Empty;
+   output [0:7]        RdFifo_RdCnt;
+   input               User_Rst;
+   input               User_Clk;
+   input               Sys_Rst;
+   input               Sys_Clk;
+
+   // SelectMAP protocol ports
+   input [0:7]         D_I;
+   output [0:7]        D_O;
+   output [0:7]        D_T;
+   input               RDWR_B;
+   input               CS_B;
+   output              INIT_B;
+   output              CCLK;
+
+   //   ____        __ _       _ _   _                   //
+   //  |  _ \  ___ / _(_)_ __ (_) |_(_) ___  _ __  ___   //
+   //  | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __|  //
+   //  | |_| |  __/  _| | | | | | |_| | (_) | | | \__ \  //
+   //  |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/  //
+   //                                                    //
+
+   //----------------------------------------------------------------------------
+   // Signal definitions
+   //----------------------------------------------------------------------------
+   // Write FIFO signals
+   wire [0:7]          WrFifo_Dout;
+   wire                WrFifo_Empty;
+   wire                WrFifo_RdEn;
+   wire [0:7]          WrFifo_RdCnt;
+   wire [0:7]          WrFifo_RdCnt_int;
+   wire [0:7]          WrFifo_WrCnt_int;
+
+   // Read FIFO signals
+   wire [0:7]          RdFifo_Din;
+   wire                RdFifo_Full;
+   wire                RdFifo_WrEn;
+   wire [0:7]          RdFifo_WrCnt;
+   wire [0:7]          RdFifo_WrCnt_int;
+   wire [0:7]          RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // IO Registers
+   //----------------------------------------------------------------------------
+   reg                 CCLK;
+
+   reg [0:7]           D_I_reg;    // synthesis attribute iob of D_I_reg is true;
+   reg [0:7]           D_O_reg;    // synthesis attribute iob of D_O_reg is true;
+   reg                 RDWR_B_reg; // synthesis attribute iob of RDWR_B_reg is true;
+   reg                 CS_B_reg;   // synthesis attribute iob of CS_B_reg is true;
+   reg                 INIT_B_reg; // synthesis attribute iob of INIT_B_reg is true;
+
+   // Outputs
+   assign              D_O = D_O_reg;
+   assign              INIT_B = INIT_B_reg;
+
+   // Inputs
+   always @( posedge Sys_Clk )
+     begin
+        D_I_reg    <= D_I;
+        RDWR_B_reg <= RDWR_B;
+        CS_B_reg   <= CS_B;
+     end
+
+   //----------------------------------------------------------------------------
+   // Generate CCLK and associated reset
+   //----------------------------------------------------------------------------
+   reg                SYNC_done;
+   reg                SYNC_done_dly;
+   reg                CS_B_reg_dly;
+
+   always @( posedge Sys_Clk )
+     begin
+        CS_B_reg_dly <= CS_B_reg;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done <= 1'b0;
+        else if (RDWR_B_reg && ~CS_B_reg)
+          SYNC_done <= 1'b1;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          SYNC_done_dly <= 1'b0;
+        else
+          SYNC_done_dly <= SYNC_done;
+     end
+
+   always @( posedge Sys_Clk )
+     begin
+        if (Sys_Rst)
+          CCLK <= 1'b0;
+        else if (~CS_B_reg && CS_B_reg_dly && CCLK)
+          CCLK <= 1'b1;
+        else
+          CCLK <= ~CCLK;
+     end
+
+   //   _____ ___ _____ ___        //
+   //  |  ___|_ _|  ___/ _ \ ___   //
+   //  | |_   | || |_ | | | / __|  //
+   //  |  _|  | ||  _|| |_| \__ \  //
+   //  |_|   |___|_|   \___/|___/  //
+   //                              //
+   // Write FIFO:  The write is with respect to the user.  The user writes data to this
+   //              FIFO and the control side of SelectMAP reads the data.
+   //
+   // Read FIFO:  The read is with respect to the user.  The user reads data sent from the
+   //             control side of SelectMAP.
+   //
+
+   //----------------------------------------------------------------------------
+   // Read FIFO
+   //----------------------------------------------------------------------------
+   assign RdFifo_WrEn = SYNC_done_dly && ~RDWR_B_reg && ~CS_B_reg && ~RdFifo_Full && CCLK;
+   assign RdFifo_Din = D_I_reg;
+
+   async_fifo_8_8_128 RdFifo( .din( RdFifo_Din ),
+                  .dout( RdFifo_Dout ),
+                  .rd_clk( User_Clk ),
+                  .rd_en( RdFifo_RdEn ),
+                  .wr_clk( Sys_Clk ),
+                  .wr_en( RdFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( RdFifo_Empty ),
+                  .full( RdFifo_Full ),
+                  .rd_data_count( RdFifo_RdCnt_int ),
+                  .wr_data_count( RdFifo_WrCnt_int ) );
+
+   assign RdFifo_WrCnt = 8'd129 - RdFifo_WrCnt_int;
+   assign RdFifo_RdCnt = RdFifo_RdCnt_int;
+
+   //----------------------------------------------------------------------------
+   // Write FIFO
+   //----------------------------------------------------------------------------
+   assign WrFifo_RdEn = SYNC_done_dly && RDWR_B_reg && ~CS_B_reg && ~WrFifo_Empty && CCLK;
+
+   async_fifo_8_8_128 WrFifo( .din( WrFifo_Din ),
+                  .dout( WrFifo_Dout ),
+                  .rd_clk( Sys_Clk ),
+                  .rd_en( WrFifo_RdEn ),
+                  .wr_clk( User_Clk ),
+                  .wr_en( WrFifo_WrEn ),
+                  .rst( User_Rst ),
+                  .empty( WrFifo_Empty ),
+                  .full( WrFifo_Full ),
+                  .rd_data_count( WrFifo_RdCnt_int ),
+                  .wr_data_count( WrFifo_WrCnt_int ) );
+
+   assign WrFifo_WrCnt = 8'd129 - WrFifo_WrCnt_int;
+   assign WrFifo_RdCnt = WrFifo_RdCnt_int;
+
+   //   ____       _           _   __  __    _    ____    //
+   //  / ___|  ___| | ___  ___| |_|  \/  |  / \  |  _ \   //
+   //  \___ \ / _ \ |/ _ \/ __| __| |\/| | / _ \ | |_) |  //
+   //   ___) |  __/ |  __/ (__| |_| |  | |/ ___ \|  __/   //
+   //  |____/ \___|_|\___|\___|\__|_|  |_/_/   \_\_|      //
+   //                                                     //
+
+   //----------------------------------------------------------------------------
+   // SelectMAP control outputs
+   //----------------------------------------------------------------------------
+   wire [0:7] DataCnt = RDWR_B_reg ? WrFifo_RdCnt : RdFifo_WrCnt;
+
+   assign     D_T    = {8{(~RDWR_B & ~CS_B)}}; // stop driving if master is sending
+
+   always @( posedge Sys_Clk )
+     begin
+        D_O_reg    <= CS_B_reg ? DataCnt : WrFifo_Dout;
+        INIT_B_reg <= WrFifo_Empty;
+     end
+
+   //----------------------------------------------------------------------------
+
+endmodule
+
+
+module main
+  (
+   // User clock ports
+   Clkin_p,
+   Clkin_m,
+   
+   // SelectMAP interface ports
+   D,                           // Data bus
+   RDWR_B,                      // Read/write signal
+   CS_B,                        // Chip select
+   INIT_B,                      // Initialization/interrupt signal
+   CCLK,                        // Local CCLK output
+   gpleds,
+   terminal
+   );
+
+   // User clock/reset ports
+   input                       Clkin_p;
+   input                       Clkin_m;
+  
+   // SelectMAP protocol ports
+   inout [0:7]                 D;
+   input                      RDWR_B;
+   input                      CS_B;
+   output                     INIT_B;
+   output                      CCLK;
+   output [6:1] gpleds;
+
+
+   // Wires
+   wire                        CCLK_int;
+   
+   wire [0:31]                 LoopData;
+   wire [0:31]                 LoopDataW;
+   wire                       LoopEmpty;
+   wire                       LoopFull;
+
+   wire [0:7]                  D_I;
+   wire [0:7]                  D_O;
+   wire [0:7]                  D_T;
+
+   wire                        User_Clk;
+   wire                        User_Rst;
+
+   reg  [6:1]                  gpleds_reg;
+
+   // synthesis attribute tig of activate_r is yes; 
+   wire   activate_r;
+   // synthesis attribute tig of activate_a is yes; 
+   wire   activate_a;
+
+   wire [7:0] write_data;
+   wire       write_enable;
+   wire       write_full;
+
+   wire [7:0] read_data;
+   wire       read_empty;
+   wire [7:0] read_wire;
+
+   reg  [7:0] write_reg;
+   reg  [7:0] read_reg;
+   wire read_enable;
+   inout [33:0] terminal;
+   wire [7:0] write_data_;
+   assign write_data = write_data_ + 48;
+   
+   Maps_Bee2_Map1 map (.Clock(User_Clk),
+                       .SelectMapData(write_data_),
+                       .SelectMapWrite(write_enable),
+                       .__TERMINAL_SynchronousLink_Pins(terminal));
+       
+//synthesis attribute LOC of terminal is "C15,L16,M16,J16,K16,H16,G16,E16,F16,M18,M17,L17,K17,H17,J17,F17,G17,D16,D17,K18,L18,G18,H18,E17,E18,C18,C17,L19,M19,J19,K19,G19,H19,E19"
+              
+
+   // IO buffers
+   OBUF obuf_cclk( .I( CCLK_int ),
+                   .O( CCLK )
+                   );
+   
+   IOBUF iobuf_d0( .I( D_O[0] ),
+                   .IO( D[0] ),
+                   .O( D_I[0] ),
+                   .T( D_T[0] )
+                   );
+   
+   IOBUF iobuf_d1( .I( D_O[1] ),
+                   .IO( D[1] ),
+                   .O( D_I[1] ),
+                   .T( D_T[1] )
+                   );
+   
+   IOBUF iobuf_d2( .I( D_O[2] ),
+                   .IO( D[2] ),
+                   .O( D_I[2] ),
+                   .T( D_T[2] )
+                   );
+   
+   IOBUF iobuf_d3( .I( D_O[3] ),
+                   .IO( D[3] ),
+                   .O( D_I[3] ),
+                   .T( D_T[3] )
+                   );
+   
+   IOBUF iobuf_d4( .I( D_O[4] ),
+                   .IO( D[4] ),
+                   .O( D_I[4] ),
+                   .T( D_T[4] )
+                   );
+   
+   IOBUF iobuf_d5( .I( D_O[5] ),
+                   .IO( D[5] ),
+                   .O( D_I[5] ),
+                   .T( D_T[5] )
+                   );
+   
+   IOBUF iobuf_d6( .I( D_O[6] ),
+                   .IO( D[6] ),
+                   .O( D_I[6] ),
+                   .T( D_T[6] )
+                   );
+   
+   IOBUF iobuf_d7( .I( D_O[7] ),
+                   .IO( D[7] ),
+                   .O( D_I[7] ),
+                   .T( D_T[7] )
+                   );
+
+   // Clock buffer and reset
+   IBUFGDS_LVDS_25 diff_usrclk_buf( .I( Clkin_p ),
+                                    .IB( Clkin_m ), 
+                                    .O( User_Clk )
+                                    );
+
+   wire [0:3] rst;
+   
+   FD rst0( .D( 1'b0 ),
+            .Q( rst[0] ),
+            .C( User_Clk )
+            );
+   defparam rst0.INIT = 1'b1;
+
+   FD rst1( .D( rst[0] ),
+            .Q( rst[1] ),
+            .C( User_Clk )
+            );
+   defparam rst1.INIT = 1'b1;
+
+   FD rst2( .D( rst[1] ),
+            .Q( rst[2] ),
+            .C( User_Clk )
+            );
+   defparam rst2.INIT = 1'b1;
+
+   FD rst3( .D( rst[2] ),
+            .Q( rst[3] ),
+            .C( User_Clk )
+            );
+   defparam rst3.INIT = 1'b1;
+
+   assign   User_Rst = |rst;
+
+
+   // FIFO module instantiation
+   user_fifo test_fifo( 
+                        .WrFifo_Din( write_data ),
+                       .WrFifo_WrEn( write_enable ),
+                       .WrFifo_Full( write_full ),
+                        .WrFifo_WrCnt(  ),
+                       .RdFifo_Dout( read_data ),
+                       .RdFifo_RdEn( read_enable ),
+                       .RdFifo_Empty( read_empty ),
+                        .RdFifo_RdCnt(  ),
+                       .User_Rst( User_Rst ),
+                       .User_Clk( User_Clk ),
+                       .Sys_Rst( User_Rst ),
+                       .Sys_Clk( User_Clk ),                        
+                       .D_I( D_I ),
+                       .D_O( D_O ),
+                       .D_T( D_T ),                         
+                       .RDWR_B( RDWR_B ),
+                       .CS_B( CS_B ),
+                       .INIT_B( INIT_B ),
+                        .CCLK( CCLK_int )
+                        );
+   
+endmodule
diff --git a/bee2-selectmap/makemaps.pl b/bee2-selectmap/makemaps.pl
new file mode 100644 (file)
index 0000000..03f9daa
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/perl
+
+`rm Map1.v`;
+`cp ../Map0.v .`;
+`cp ../main_map0.v main.v`;
+`make -f Makefile0`;
+`rm Map0.v`;
+`cp ../Map1.v .`;
+`cp ../main_map1.v main.v`;
+`make -f Makefile1`;
diff --git a/bee2-selectmap/remote_run.pl b/bee2-selectmap/remote_run.pl
new file mode 100644 (file)
index 0000000..b421f1f
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+
+$foo = 5;
+$f=0;
+while($f<$foo)
+{
+`echo "1234567890" > /dev/selectmap1`;
+`head -c11 /dev/selectmap2 >> transcript`;
+`echo '\n' >> transcript`;
+$f = $f+1;
+}
+
diff --git a/bee2-selectmap/root.v b/bee2-selectmap/root.v
new file mode 100644 (file)
index 0000000..6034216
--- /dev/null
@@ -0,0 +1,43 @@
+// megacz@cs.berkeley.edu,  public domain
+
+module root(clk,
+            read_empty, read_enable, read_data,
+            write_full, write_enable, write_data);
+
+  input clk;
+  input read_empty;
+  input write_full;
+  output read_enable;
+  output write_enable;
+  input  [7:0] read_data;
+  output [7:0] write_data;
+
+  reg read_enable_;
+  assign read_enable = read_enable_;
+  reg write_enable_;
+  assign write_enable = write_enable_;
+  reg [7:0] write_data_;
+  assign write_data = write_data_;
+
+  initial read_enable_ = 1;
+  initial write_enable_ = 0;
+
+  always @(posedge clk) begin
+
+    // if there's stuff to read and room to write, read a byte,
+    // increment it, and write it
+    if (!read_enable_ && !write_enable_ && !read_empty && !write_full) begin
+      read_enable_  <= 1;
+      write_enable_ <= 1;
+      write_data_   <= read_data + 1;
+
+    // else do nothing
+    end else begin
+      read_enable_  <= 0;
+      write_enable_ <= 0;
+
+    end
+
+  end
+
+endmodule
diff --git a/campus.png b/campus.png
new file mode 100644 (file)
index 0000000..b307515
Binary files /dev/null and b/campus.png differ
diff --git a/contrib/bubblesort.fleet b/contrib/bubblesort.fleet
new file mode 100644 (file)
index 0000000..4dc8913
--- /dev/null
@@ -0,0 +1,249 @@
+// bubblesort.fleet
+// Author: Thomas Kho <tkho@eecs.berkeley.edu>
+
+#import edu.berkeley.fleet.ships
+
+// 20 elements in memory
+#memory { 1, 2, 6, 1, 3, 9, 4, 4, 7, 1,
+          9, 4, 7, 6, 1, 2, 3, 0, 9, 3 }
+
+#ship memread      : MemoryReadShip   // ports: addr, stride, count, data, done
+#ship memwrite     : MemoryWriteShip  // ports: addr, stride, count, data, done
+
+#ship halt         : HaltShip         // ports: in
+#ship fetch        : FetchShip        // ports: codebag, release, revoke, done
+#ship tokensource  : TokenSourceShip  // ports: out
+#ship bitbucket    : BitBucketShip    // ports: token, data
+#ship debug        : DebugShip        // ports: token, data
+#ship counter      : HomeworkCounter  // ports: load, zero, positive, ask
+#ship itercnt      : HomeworkCounter  // ports: load, zero, positive, ask
+
+#ship max          : ArithmeticShip   // ports: A, B, cmd, out
+#ship min          : ArithmeticShip   // ports: A, B, cmd, out
+
+#ship dup1         : DuplicatorShip   // ports: in, out1, out2, out3, out4
+#ship dup2         : DuplicatorShip   // ports: in, out1, out2, out3, out4
+
+#ship tokenfifo    : TokenFifo        // ports: in, out
+#ship donecodebag  : FifoShip         // ports: in, out
+
+#ship nextcodebag  : FifoShip         // ports: in, out
+#ship exitcodebag  : FifoShip         // ports: in, out
+
+// first, load itercnt counter
+{
+  fetch.done -> bitbucket.token
+
+  move+ack itercnt.load -> fetch.release
+  itercnt.load -[*]-> ()
+
+  itercnt.positive -[*]-> nextcodebag.out
+  itercnt.zero -> exitcodebag.out
+  // use tokens from itercnt to trigger delivery of the correct codebag
+  triggered move nextcodebag.out -[*]-> fetch.codebag
+  triggered move exitcodebag.out -[*]-> fetch.codebag
+  CLEANUP -> exitcodebag.in
+
+  FETCH_NEXT -> fetch.codebag
+  19 -> itercnt.load
+} -> fetch.codebag
+nop+ack itercnt.load -> fetch.release
+
+FETCH_NEXT: { // itercnt loaded
+  fetch.done -> bitbucket.token
+
+  LOOP_BODY -> nextcodebag.in
+  tokensource.out -> itercnt.ask
+  tokensource.out -> fetch.release
+}
+
+LOOP_BODY: {
+  fetch.done -> bitbucket.token
+
+  // donecodebag.in is called after one iteration of sort
+  FETCH_NEXT -> donecodebag.in
+  tokensource.out -> fetch.release
+  SORT_ONCE -> fetch.codebag
+}
+
+CLEANUP: {
+  fetch.done -> bitbucket.token
+
+  nop+ack exitcodebag.out -> tokenfifo.in
+  nop+ack nextcodebag.out -> tokenfifo.in
+  nop+ack itercnt.positive -> tokenfifo.in
+  nextcodebag.out -> bitbucket.data
+  tokenfifo.out -[2]-> bitbucket.token
+  tokenfifo.out -> halt.in
+}
+
+SORT_ONCE: {
+  fetch.done -> bitbucket.token
+
+  0 -> memread.addr
+  1 -> memread.stride
+  20 -> memread.count
+  memread.done -> bitbucket.token
+
+  // in-place sorting
+  0 -> memwrite.addr
+  1 -> memwrite.stride
+  20 -> memwrite.count
+  memwrite.done -> bitbucket.token
+
+  // clear standing moves at inboxes that will ack
+  nop+ack dup1.in -> tokenfifo.in
+  nop+ack dup2.in -> tokenfifo.in
+  nop+ack max.A -> tokenfifo.in
+  nop+ack max.B -> tokenfifo.in
+  nop+ack max.cmd -> tokenfifo.in
+  nop+ack min.A -> tokenfifo.in
+  nop+ack min.B -> tokenfifo.in
+  nop+ack min.cmd -> tokenfifo.in
+  nop+ack memwrite.data -> tokenfifo.in
+  nop+ack counter.load -> tokenfifo.in
+  tokenfifo.out -[9]-> bitbucket.token
+  tokenfifo.out -> fetch.release
+
+  {
+    fetch.done -> bitbucket.token
+
+    move+ack counter.load -> fetch.release
+    counter.load -[*]-> () // restore standing move
+    19 -> counter.load // load N - 1 into counter
+
+    { // on counter load, seed pipeline
+      fetch.done -> bitbucket.token
+
+      tokensource.out -[3]-> counter.ask
+    } -> fetch.codebag
+
+    // send first memread.data to dup2.in
+    memread.data -> dup2.in
+
+    // counting pipeline: min.out -> memwrite.data
+    triggered move min.out -[*]-> memwrite.data
+    accept+ack memwrite.data -[*]-> counter.ask
+    counter.positive -[*]-> min.out
+
+    // standing commands on min, max ships
+    copy min.cmd -[*]-> ()
+    "MIN ZERO ZERO" -> min.cmd
+    copy max.cmd -[*]-> ()
+    "MAX ZERO ZERO" -> max.cmd
+
+    // pipelines: dup1 -> max, dup2 -> max, dup1 -> min, dup2 -> min
+    triggered move dup1.out1 -[*]-> max.A
+    accept+ack max.A -[*]-> dup1.out1
+    triggered move dup2.out1 -[*]-> max.B
+    accept+ack max.B -[*]-> dup2.out1
+    triggered move dup1.out2 -[*]-> min.A
+    accept+ack min.A -[*]-> dup1.out2
+    triggered move dup2.out2 -[*]-> min.B
+    accept+ack min.B -[*]-> dup2.out2
+
+    // pipeline: max.out -> dup2.in
+    triggered move max.out -[*]-> dup2.in
+    accept+ack dup2.in -[*]-> max.out
+
+    // pipeline: memread.data -> dup1.in
+    triggered move memread.data -[*]-> dup1.in
+    accept+ack dup1.in -[*]-> memread.data
+
+    // seed the above 6 pipelines
+    tokensource.out -[3]-> dup1.out1
+    tokensource.out -[3]-> dup1.out2
+    tokensource.out -[3]-> dup2.out1
+    tokensource.out -[3]-> dup2.out2
+    tokensource.out -[3]-> memread.data
+    tokensource.out -[2]-> max.out // also seeded with first data
+
+    // ignore dup[12].out[03]
+    dup1.out3 -[*]-> bitbucket.data
+    dup1.out0 -[*]-> bitbucket.data
+    dup2.out3 -[*]-> bitbucket.data
+    dup2.out0 -[*]-> bitbucket.data
+
+    // setup exit condition
+    counter.zero -[2]-> bitbucket.token
+    counter.zero -> fetch.release
+
+    { // after N-1 writes
+      fetch.done -> bitbucket.token
+
+      // once we're done with N-1 writes, we can flush the last one
+      // by comparing with MAXINT
+      999 -> dup1.in
+      tokensource.out -> min.out
+      counter.zero -> fetch.release // trigger next codebag
+    } -> fetch.codebag
+
+    { // cleanup codebag
+      fetch.done -> bitbucket.token
+
+      // clear outbox standing moves
+      nop+ack dup1.out0 -> tokenfifo.in
+      nop+ack dup1.out3 -> tokenfifo.in
+      nop+ack dup2.out0 -> tokenfifo.in
+      nop+ack dup2.out3 -> tokenfifo.in
+      nop+ack counter.positive -> tokenfifo.in
+      nop+ack min.out -> tokenfifo.in
+
+      // get rid of tokens
+      triggered nop+ack memread.data -[4]-> tokenfifo.in // 3 + flush
+      triggered nop+ack max.out -[3]-> tokenfifo.in
+      triggered nop+ack dup1.out1 -[3]-> tokenfifo.in
+      triggered nop+ack dup1.out2 -[3]-> tokenfifo.in
+      triggered nop+ack dup2.out1 -[3]-> tokenfifo.in
+      triggered nop+ack dup2.out2 -[3]-> tokenfifo.in
+
+      // this, paired with MAXINT at port B, will kill standing copy
+      0 -> max.A
+      0 -> min.A
+      max.out -> bitbucket.data
+      min.out -> bitbucket.data
+
+      // restore unacked inbox standing moves
+      nop+ack memwrite.data -> tokenfifo.in
+      memwrite.data -[*]-> ()
+      nop+ack dup1.in -> tokenfifo.in
+      dup1.in -[*]-> ()
+      nop+ack dup2.in -> tokenfifo.in
+      dup2.in -[*]-> ()
+      nop+ack max.A -> tokenfifo.in
+      max.A -[*]-> ()
+      nop+ack min.A -> tokenfifo.in
+      min.A -[*]-> ()
+      nop+ack max.B -> tokenfifo.in
+      max.B -[*]-> ()
+      nop+ack min.B -> tokenfifo.in
+      min.B -[*]-> ()
+      nop+ack max.cmd -> tokenfifo.in
+      max.cmd -[*]-> ()
+      nop+ack min.cmd -> tokenfifo.in
+      min.cmd -[*]-> ()
+
+      tokenfifo.out -[33]-> bitbucket.token
+      tokenfifo.out -> fetch.release
+    } -> fetch.codebag
+
+    {
+      fetch.done -> bitbucket.token
+
+      // standing copy is gone, so get rid of this last cmd
+      0 -> max.A
+      0 -> min.A
+      0 -> max.B
+      0 -> min.B
+
+      // probably lax on the sequencing here
+      max.out -> bitbucket.data
+      min.out -> bitbucket.data
+
+      // "function calls" return with a continuation
+      tokensource.out -> fetch.release
+      donecodebag.out -> fetch.codebag
+    } -> fetch.codebag
+  } -> fetch.codebag
+}
+
diff --git a/contrib/demo.f0 b/contrib/demo.f0
new file mode 100644 (file)
index 0000000..84dcd4a
--- /dev/null
@@ -0,0 +1,15 @@
+
+main(a,b -> x,y) =
+  alu    :: Alu2
+  debug  :: Debug
+  fifo1  :: Fifo
+  fifo2  :: Fifo
+
+  { 0, 1 } --> fifo1.in
+  
+  fifo1.out --> fifo1.in, fifo1.in
+  fifo1.out --> fifo1.in, fifo1.in
+  fifo1.out --> debug.in
+  fifo1.out --> debug.in
+  fifo1.out --> debug.in
+  fifo1.out --> debug.in
diff --git a/contrib/demo.fleet b/contrib/demo.fleet
new file mode 100644 (file)
index 0000000..8f8c514
--- /dev/null
@@ -0,0 +1,14 @@
+#ship debug    : Debug
+#ship iscratch : Iscratch
+
+BOB:             sendto iscratch.inCBD;
+iscratch.inCBD:  [*] take, deliver;
+debug.in:        [*] take, deliver;
+
+BOB: {
+  12:           sendto debug.in;
+  13:           sendto debug.in;
+  14:           sendto debug.in;
+  BOB:          sendto iscratch.inCBD;
+}
+
diff --git a/contrib/f0/Compile.lhs b/contrib/f0/Compile.lhs
new file mode 100644 (file)
index 0000000..5c1bbb8
--- /dev/null
@@ -0,0 +1,83 @@
+\begin{code}
+module Compile where
+import SBP
+import Types
+import Util
+import Fleet
+
+-- assumption: 
+--   within a block that has data going both to and from a ship,
+--   the last datum leaving the ship must leave after all arriving
+--   datums have arrived
+
+getBoxes :: Bool -> Expr -> [Port]
+getBoxes True  (Move 1 s d)    = [s]
+getBoxes True  (Copy 1 s d)    = [s]
+getBoxes inb   (Decl d e)      = getBoxes inb e
+getBoxes inb   (Par es)        = concatMap (getBoxes inb) es
+getBoxes True  (Seq es)        = getBoxes True  $ last es
+getBoxes False (Seq es)        = getBoxes False $ head es
+getBoxes True  (While p o i e) = [cbdPort] -- FIXME
+getBoxes False (While p o i e) = [] -- FIXME
+getBoxes _ _                   = []
+
+cbdPort = ShipPort "mem" "inCBD"
+
+compile :: Expr -> [Inst]
+compile (Literal 0 lit d)  = [ ILiteral lit d, (accept d) {m_count=0} ]
+compile (Literal 1 lit d)  = [ ILiteral lit d, (accept d)             ]
+compile (Literal n lit d)  = [ ILiteral lit d, (accept d) {m_count=n} ]
+compile (Decl d e)         = compile e
+compile (Par e)            = concatMap compile e
+compile (Move 1 s d)       = [ (move s) { m_dest=(Just d) }, (accept d) ]
+compile (Copy 1 s d)       = [ (copy s) { m_dest=(Just d) }, (accept d) ]
+compile (While p op i e)   = think ++ [IBagDef "WHILECODEBAG" $ think ++ (compile e) ]
+ where
+  think        = [
+                   ILiteralBag "WHILECODEBAG" (ShipPort "choice" "in2"),
+                   (move p) { m_dataIn=False, m_dest=(Just (ShipPort "ifalu" "in1")) },
+                   (move (ShipPort "ifalu" "out")) { m_dest = (Just (ShipPort "choice" ("in."++(swapPort op)))) },
+                   ILiteral    i       (ShipPort "ifalu"  "in2"),
+                   ILiteral    1       (ShipPort "ifalu"  "inOp"),
+                   ILiteral    0       (ShipPort "choice" "in1"),  -- FIXME
+                   accept (ShipPort "ifalu" "in1"),
+                   accept (ShipPort "ifalu" "in2"),
+                   accept (ShipPort "ifalu" "inOp"),
+                   accept (ShipPort "choice" "in1"),
+                   accept (ShipPort "choice" "in2"),
+                   accept (ShipPort "choice" "in"),
+                   (move (ShipPort "choice" "out1")) { m_dest = Just cbdPort },
+                   (dismiss (ShipPort "choice" "out2")),
+                   (accept cbdPort)
+                 ]
+  swapPort Lt  = "swapIfNegative"
+  swapPort Gt  = "swapIfPositive"
+  swapPort Leq = "swapIfNonPositive"
+  swapPort Geq = "swapIfNonNegative"
+  swapPort Eq  = "swapIfZero"
+  swapPort Neq = "swapIfNonZero"
+compile (Seq [a])          = compile a
+compile (Seq (a:b:rest))   = (compile a)++(bridge (getBoxes True a) (uniq (getBoxes False b)))++(compile $ Seq (b:rest))
+ where
+  bridge :: [Port] -> [Port] -> [Inst]
+  bridge [] _         = []
+  bridge _  []        = []
+  bridge obs (ib:ibs) = notifyFromOutboxes ++ waitForOutboxNotifications ++ notifyInboxes ++ waitForInboxNotifications
+   where
+    notifyFromOutboxes         = map (\ob -> notify ob ib) obs
+    waitForOutboxNotifications = [ (wait ib) { m_count=(length obs) } ]
+    notifyInboxes              = map (notify ib) ibs
+    waitForInboxNotifications  = map wait ibs
+
+getdecls (Decl d e) = ["#ship mem : Memory", "#ship choice : Choice", "#ship ifalu : Alu2" ] ++
+                      map (\(n,t) -> ("#ship " ++ n ++ " : " ++ t)) d
+getdecls (Seq es)   = concatMap getdecls es
+getdecls (Par es)   = concatMap getdecls es
+getdecls _          = []
+
+compileDef (Def s _ _ e) =
+    "// " ++ s ++ "\n" ++
+    (join "\n" $ getdecls e)++"\n"++
+    (join "\n" $ map show (compile e))
+\end{code}
\ No newline at end of file
diff --git a/contrib/f0/Fleet.lhs b/contrib/f0/Fleet.lhs
new file mode 100644 (file)
index 0000000..2432f80
--- /dev/null
@@ -0,0 +1,76 @@
+\begin{code}
+module Fleet where
+import SBP
+import Util
+
+itake  box = IMove { m_count=1, m_recycle=False, m_tokenIn=False, m_dataIn=True,
+                     m_latch=True, m_dataOut=False, m_tokenOut=False, m_dest=Nothing,
+                     m_pump=box }
+move   box = (itake box){ m_dataOut=True }
+copy   box = (move box){ m_dataIn=False }
+send   box = (move box){ m_dataIn=False, m_latch=False }
+notify box dest = IMove { m_count=1, m_recycle=False, m_tokenIn=False, m_dataIn=False,
+                          m_latch=False, m_dataOut=False, m_tokenOut=True, m_dest=(Just dest),
+                          m_pump=box }
+wait box = IMove { m_count=1, m_recycle=False, m_tokenIn=True, m_dataIn=False,
+                   m_latch=False, m_dataOut=False, m_tokenOut=False, m_dest=Nothing,
+                   m_pump=box }
+dismiss box = IMove { m_count=1, m_recycle=False, m_tokenIn=False, m_dataIn=True,
+                      m_latch=False, m_dataOut=False, m_tokenOut=False, m_dest=Nothing,
+                      m_pump=box }
+accept box = move box
+
+-- Port ------------------------------------------------------------------------------
+data Port = ShipPort String String
+          | IdPort   String
+ deriving (Eq, Ord)
+
+instance Show Port where
+ show (ShipPort a b) = a++"."++b
+ show (IdPort a)     = a
+
+instance FromTree Port where
+ fromTree (Tree "Port" [s] _)   = IdPort (fromTree s)
+ fromTree (Tree "Port" [a,b] _) = ShipPort (fromTree a) (fromTree b)
+ fromTree t = error (show t)
+
+type PortBox = Port
+data Inst =
+    IKill        PortBox Int
+  | ILiteral     Int           PortBox
+  | ILiteralBag  String        PortBox
+  | IBagDef      String        [Inst]
+  | IMove   { m_pump :: PortBox ,
+              m_dest     :: Maybe PortBox ,
+              m_count    :: Int ,
+              m_recycle  :: Bool ,
+              m_tokenIn  :: Bool ,
+              m_dataIn   :: Bool ,
+              m_latch    :: Bool ,
+              m_dataOut  :: Bool ,
+              m_tokenOut :: Bool }
+
+showCount 0 True  = "[*r] "
+showCount 0 False = "[*] "
+showCount 1 _     = ""
+showCount n True  = "["++(show n)++"r] "
+showCount n False = "["++(show n)++"] "
+
+instance Show Inst where
+ show (IKill bb count)  = (show bb)++": "++(showCount count False)++" kill;"
+ show (ILiteral lit bb) = (show lit)++": sendto "++(show bb)++";"
+ show (ILiteralBag bagname bb) = bagname++": sendto "++(show bb)++";"
+ show (IBagDef bagname is) = bagname++": {\n  "++(join "" $ map (\i -> (show i)++"\n  ") is)++"}\n"
+ show m@(_)             = (show $ m_pump m) ++
+                         ": "++
+                         (showCount (m_count m) $ m_recycle m) ++
+                         (join ", " $ showrest m)++
+                         ";"
+                           where
+                             showrest m = wait++takelatch++out++ack
+                              where
+                               wait      = if m_tokenIn m then ["wait"] else []
+                               takelatch = if m_dataIn m then (if m_latch m then ["take"] else ["dismiss"]) else []
+                               out       = if m_dataOut m then (case m_dest m of { Nothing -> ["deliver"]; (Just j) -> ["sendto "++(show j)] }) else []
+                               ack       = if m_tokenOut m then (case m_dest m of (Just j) -> ["notify "++(show j)]) else []
+\end{code}
\ No newline at end of file
diff --git a/contrib/f0/Main.lhs b/contrib/f0/Main.lhs
new file mode 100644 (file)
index 0000000..f81a0b9
--- /dev/null
@@ -0,0 +1,36 @@
+\begin{code}
+
+{-
+ next step:
+
+  - Transform code involving standing moves into two sequential
+    blocks: setup and teardown.  Then establish proper sequencing
+    between them.  The teardown block consists only of kills.
+
+  - Implement sequencing.
+-}
+
+module Main
+where
+import SBP
+import Types
+import Util
+import Fleet
+import Compile
+
+main = do t <- parseFile "src/edu/berkeley/fleet/f0/f0.g" "contrib/demo.f0"
+          putStrLn ""
+          putStrLn $ show $ coalesceFlatHeadlessNodes t
+          putStrLn ""
+          putStrLn $ join "\n\n" $ map show $ ((fromTree $ coalesceFlatHeadlessNodes t) :: [Def])
+          putStrLn ""
+          compiled <- return $ join "\n\n" $ map compileDef $ ((fromTree $ coalesceFlatHeadlessNodes t) :: [Def])
+          putStrLn $ compiled
+          writeFile "compiled.fleet" ("// compiled with f0\n\n"++compiled++"\n")
+          putStrLn ""
+
+\end{code}
+
+
+
+
diff --git a/contrib/f0/Types.lhs b/contrib/f0/Types.lhs
new file mode 100644 (file)
index 0000000..be42cb2
--- /dev/null
@@ -0,0 +1,95 @@
+\begin{code}
+module Types where
+import SBP
+import Util
+import Fleet
+
+-- Def ------------------------------------------------------------------------------
+data Def = Def String [String] [String] Expr
+  deriving Eq
+instance Show Def where
+ show (Def name inp outp exprs) =
+     name ++ "(" ++ (commify inp) ++ " -> " ++ (commify outp) ++ ") =\n   " ++ (indent (show exprs))
+  where
+   commify x = join "," x
+instance FromTree Def where
+  fromTree (Tree "Def" [name,inp,outp,es] _) =
+     Def (fromTree name) (fromTree inp) (fromTree outp) (fromTree es)
+  fromTree (Tree "Def" q _) = error $ show q
+
+
+
+-- Expr ------------------------------------------------------------------------------
+data Op = Lt | Gt | Leq | Geq | Eq | Neq
+ deriving (Show,Eq)
+instance FromTree Op where
+  fromTree (Tree s _ _) =
+   case s of
+    "==" -> Eq
+    "!=" -> Neq
+    ">=" -> Geq
+    "<=" -> Leq
+    ">"  -> Gt
+    "<"  -> Lt
+
+data Expr  = Seq     [Expr] 
+           | Par     [Expr]
+           | Decl    [(String,String)] Expr
+           | Move    Int Port Port
+           | Copy    Int Port Port
+           | Literal Int Int  Port
+           | While   Port Op Int Expr
+           | Nop
+  deriving (Show,Eq)
+{-
+instance Show Expr where
+ show (Decl shipName shipType) = shipName ++ " :: " ++ shipType
+ show (Seq  exprs)             = join " ;; " $ map (\x -> "{ "++x++" }") $ map show exprs
+ show (Par  [expr])            = show expr
+ show (Par  exprs)             = "{ " ++ (join "\n   " $ map show exprs) ++ " }"
+ show (Move 0 source dest)      = (show source) ++ " -[*]-> " ++ (show dest)
+ show (Move 1 source dest)      = (show source) ++ " --> " ++ (show dest)
+ show (Move count source dest)      = (show source) ++ " -["++(show count)++"]-> " ++ (show dest)
+ show (Literal 0 i dest)   = (show i) ++ " -[*]-> " ++ (show dest)
+ show (Literal 1 i dest)   = (show i) ++ " --> " ++ (show dest)
+ show (Literal count i dest)   = (show i) ++ " -["++(show count)++"]-> " ++ (show dest)
+-}
+
+instance FromTree Expr where
+  fromTree (Tree "Exprs" [(Tree _ decls _), sequents] _) = Decl declist (seq $ map par $ fromTree sequents)
+   where
+         declist = map (\(Tree "::" [shipName,shipType] _) -> ((fromTree shipName), (fromTree shipType))) decls
+         seq []  = Nop
+         seq [x] = x
+         seq x   = Seq x
+         par []  = Nop
+         par [x] = x
+         par x   = Par x
+  fromTree (Tree arrow [source,dests] _) | (arrow=="-->" || arrow=="+->") =
+   case source of
+    (Tree "{" [Tree _ is _] _) -> Par $ concatMap (\d -> map (\(Tree i _ _) -> Literal 1 (read i) d) is) dest
+    (Tree i [] _)              -> rep' dest $ \d -> Literal 1 (read i) d
+    source                     -> case dests of
+                                    (Tree ";" [Tree _ d _] _)      -> rep' dest $ \d -> mc 1 (fromTree source) d
+                                    (Tree "," [Tree _ (d:ds) _] _) ->
+                                       Par $
+                                         ((mc 1 (fromTree source) (fromTree d)):
+                                          (map (\d' -> Copy 1 (fromTree source) d') (map fromTree ds)))
+   where
+    mc = if arrow=="-->" then Move else Copy
+    dest = case dests of
+             (Tree ";" [Tree _ d _] _) -> map fromTree d
+    rep' []   _ = error "nop"
+    rep' [x]  f = f x
+    rep' list f = Par $ map f list
+
+--  fromTree (Tree "-["     [(Tree i [] _),(Tree c [] _),dest] _) = Literal (read c) (read i)            (fromTree dest)
+--  fromTree (Tree "-["     [source,(Tree c [] _),dest] _)        = Move    (read c) (fromTree source)   (fromTree dest)
+--  fromTree (Tree "-[*]->" [(Tree i [] _),dest] _)               = Literal 0        (read i)            (fromTree dest)
+--  fromTree (Tree "-[*]->" [source,dest] _)                      = Move    0        (fromTree source)   (fromTree dest)
+  fromTree (Tree "while" [(Tree "Cond" [port, op, (Tree i _ _)] _), e] _) =
+      While (fromTree port) (fromTree op) (read i) (fromTree e)
+  fromTree other = error  $ (show other)
+
+
+\end{code}
\ No newline at end of file
diff --git a/contrib/f0/Util.lhs b/contrib/f0/Util.lhs
new file mode 100644 (file)
index 0000000..f178fc5
--- /dev/null
@@ -0,0 +1,32 @@
+\begin{code}
+module Util where
+import SBP
+import List(sort)
+
+indent []       = []
+indent ('\n':q) = "\n  "++(indent q)
+indent (a:b)    = a:(indent b)
+
+join c []    = ""
+join c [x]   = x
+join c (x:y) = x++c++(join c y)
+
+class FromTree a where
+ fromTree  :: Tree   -> a
+class FromTrees a where
+ fromTrees :: [Tree] -> a
+instance FromTree a => FromTree [a] where
+ fromTree (Tree _ c _) = map fromTree c
+instance FromTree  String where
+  fromTree  (Tree h c _) = h++(concatMap fromTree c)
+instance FromTrees String where
+  fromTrees ts           = concatMap (fromTree :: Tree -> String) ts
+
+uniq l = rmdups $ sort l
+ where
+  rmdups []                     = []
+  rmdups [x]                    = [x]
+  rmdups (x:y:rest) | x==y      = rmdups (x:rest)
+                    | otherwise = x:(rmdups (y:rest))
+
+\end{code}
\ No newline at end of file
diff --git a/contrib/f0/f0.g b/contrib/f0/f0.g
new file mode 100644 (file)
index 0000000..f5c1912
--- /dev/null
@@ -0,0 +1,41 @@
+s               = ws! (Def+/ws) ws!
+
+Def = Id "(" (Id+/comma) "->" (Id+/comma) ")" "=" Exprs /ws
+
+Exprs =
+  Exprs:: Decl */ ws
+          ws!
+          ((Expr +/ ws) +/ semicolons)
+
+Decl = Id   ^"::" ShipName  /ws
+
+Expr = "{" Exprs "}"        /ws
+     | (Literal|Port)     ^"-->"              Ports /ws
+     | (Literal|Port)     ^"+->"              Ports /ws
+     | (Literal|Port) ws! ^"-[" Int "]->" ws! Ports
+     | (Literal|Port)     ^"-[*]->"           Ports /ws
+     | ^"while" Cond Expr /ws
+//   | "if" "then" "else"
+
+CondOp = ^"==" | ^"!=" | ^">" | ^">=" | ^"<" | ^"<="
+Cond   = Cond:: Port CondOp Int /ws
+
+Ports    = ";":: Port +/ semicolon
+         > ",":: Port +/ comma
+Port     = "Port":: Id
+         | "Port":: Id "." Id
+
+Literal  = Int | ^"{" Int +/ comma "}" /ws
+Int      = [\-0-9]++
+ShipName = "":: [A-Z] [a-zA-Z0-9_]*
+Id       = "":: [a-z] [a-zA-Z0-9_]*
+
+Comment    = "//" (~eol)* eol!
+           | "/*" (any* &~ (any*! "*/" any*!)) "*/"
+ws         = (wsc | Comment)* -> ~wsc
+eol        = [\r\n]
+wsc        = [\r\n ] | \{ | \}
+comma      = ws! "," ws!
+semicolon  = ws! ";" ws!
+semicolons = ws! ";;" ws!
+any        = ~[]
diff --git a/contrib/flow-control-example.fleet b/contrib/flow-control-example.fleet
new file mode 100644 (file)
index 0000000..d1c23be
--- /dev/null
@@ -0,0 +1,48 @@
+#import edu.berkeley.fleet.ships
+
+//#ship math        : ArithmeticShip
+#ship helper      : FifoShip
+#ship source      : FifoShip
+#ship dest        : FifoShip
+#ship halt        : HaltShip
+#ship fetch       : FetchShip
+#ship tokensource : TokenSourceShip
+
+// NOTE: "accept" is a synonym for "move" it is less confusing in the case
+//       of inboxes, but is otherwise identical
+
+//"foo" -> math.din
+
+//////////////////////////////////////////////////////////////////////////////
+// The following three instructions simply produce one hundred "3"s
+// and put them into fifo "a".  Ignore the switch-fabric clogging
+// issue here; this is just setup for the rest of the code.
+
+                 3                -> helper.in
+            copy helper.out  -[10]-> source.in
+         discard helper.out       -> ()
+
+
+//////////////////////////////////////////////////////////////////////////////
+// set up a counting move of 10 items from source.out to dest.in, but require
+// flow control tokens (10 items is too many to send at once)
+
+ triggered move  source.out -[10]-> dest.in
+
+
+//////////////////////////////////////////////////////////////////////////////
+// The next instruction tears down the "default" standing move on dest.in
+// and uses the resulting tokens to prime source.out's pump.  Once that
+// has been kicked off, any subsequent incoming items will generate tokens
+// which are sent back to the source outbox
+
+          nop+ack dest.in     -[3]-> source.out
+       accept+ack dest.in     -[7]-> source.out
+       accept     dest.in     -[3]-> source.out
+          nop+ack dest.in         -> fetch.release    // then release the fetch
+           accept dest.in     -[*]-> ()               // and return the fabric to normal
+
+{ tokensource.out -> halt.in }    -> fetch.codebag    // termination codebag
+
+
+
diff --git a/contrib/fpga-demo.fa b/contrib/fpga-demo.fa
new file mode 100644 (file)
index 0000000..0bebb85
--- /dev/null
@@ -0,0 +1,16 @@
+#include "contrib/demo.ships"
+
+// your solution goes here
+
+12: sendto debug.data;
+debug.data: [*] take, deliver;
+
+0: sendto alu2.op;
+1: sendto alu2.a;
+1: sendto alu2.b;
+
+alu2.a:   [*] take, deliver;
+alu2.b:   [*] take, deliver;
+alu2.op:  [*] take, deliver;
+
+alu2.out: take, sendto debug.data;
diff --git a/contrib/ps3-1b.fleet b/contrib/ps3-1b.fleet
new file mode 100644 (file)
index 0000000..cf44f85
--- /dev/null
@@ -0,0 +1,52 @@
+// Problem 1 (Amir)
+//
+// Two Fifo ships contain the same number of elements. Send a combined 
+// sequence to the Debug ship such that each pair of elements is in 
+// increasing order.
+//
+// Hint: look at the ship file that defines the Alu2 ship
+//
+// Author: Amir Kamil
+//
+// Unlike the Alu2 version, no flow control/sequencing is necessary.
+
+
+#import edu.berkeley.fleet.ships
+#ship alu          : Alu2b
+#ship debug        : Debug
+#ship fifo1        : Fifo
+#ship fifo2        : Fifo
+
+#expect 1
+#expect 2
+#expect 3
+#expect 9
+#expect 8
+#expect 11
+
+// for debugging; your solution must work with any
+// set of numbers
+
+1:          sendto fifo1.in;
+3:          sendto fifo1.in;
+8:          sendto fifo1.in;
+fifo1.in:   [*] take, deliver;
+2:          sendto fifo2.in;
+9:          sendto fifo2.in;
+11:         sendto fifo2.in;
+fifo2.in:   [*] take, deliver;
+
+// your solution goes here
+
+fifo1.out:  [*] nop;
+            (*) take, sendto alu.in1.min;
+            (*) sendto alu.in1.max;
+            kill;
+fifo2.out:  [*] take, sendto alu.in2;
+alu.in1:    [*] take, deliver;
+alu.in2:    [*] nop;
+            (*) take, deliver;
+            (*) deliver;
+            kill;
+alu.out:    [*] take, sendto debug.in;
+debug.in:   [*] take, deliver;
diff --git a/contrib/sort.fleet b/contrib/sort.fleet
new file mode 100644 (file)
index 0000000..e22f3a3
--- /dev/null
@@ -0,0 +1,107 @@
+// A bubble sort implementation.
+// This only works for 6 input elements. To change the number of input
+// elements, modify the counts in the lines marked below.
+// Author: Amir Kamil <kamil@cs.berkeley.edu>
+// Date:   7/16/07
+
+#import edu.berkeley.fleet.ships
+#ship alu          : Alu2b
+#ship blu          : Alu2b
+#ship debug        : Debug
+#ship fifo1        : Fifo
+#ship fifo2        : Fifo
+#ship fifo3        : Fifo
+#ship mem          : Memory
+
+#expect 1
+#expect 2
+#expect 3
+#expect 9
+#expect 8
+#expect 11
+
+// for debugging; the solution should work with any set of numbers
+
+9:          sendto fifo1.in;
+1:          sendto fifo1.in;
+3:          sendto fifo1.in;
+11:         sendto fifo1.in;
+2:          sendto fifo1.in;
+8:          sendto fifo1.in;
+
+// basic setup
+
+fifo1.in:   [*] take, deliver;
+fifo2.in:   [*] take, deliver;
+debug.in:   [*] take, deliver;
+alu.in1:    [*] take, deliver;
+alu.in2:    [*] take, deliver;
+blu.in1:    [*] take, deliver;
+blu.in2:    [*] take, deliver;
+fifo3.out:  [*] wait, take, sendto mem.inCBD;
+mem.inCBD:  [*] take, deliver;
+
+// one loop iteration
+// this code needs flow control
+
+ITER: {
+  fifo1.out:  take, sendto alu.in1.max;
+              sendto blu.in1.min;
+              [*] nop;
+              (*) take, sendto alu.in2;
+              (*) sendto blu.in2;
+              kill*;
+  alu.out:    [*] nop;
+              (*) take, sendto alu.in1.max;
+              (*) sendto blu.in1.min;
+              kill;
+  blu.out:    [5] take, sendto fifo2.in; // count = num - 1
+              notify fifo3.out;
+}
+
+// iteration cleanup
+
+END: {
+  0:          sendto alu.in2; // flush
+  0:          sendto blu.in2; // flush
+  fifo1.out:  kill;
+              kill;
+  alu.out:    kill;
+              kill;
+              sendto fifo2.in;
+              dismiss;
+  blu.out:    dismiss;
+  fifo2.out:  [6] take, sendto fifo1.in; // count = num
+              notify fifo3.out;
+}
+
+// overall control
+
+SENDDONE:   sendto fifo3.in;
+ITER:       sendto fifo2.in;
+END:        sendto fifo2.in;
+fifo2.out:  wait;
+            [*] nop;
+            (6) take, sendto fifo3.in;   // count = num
+            (6) sendto fifo2.in;         // count = num
+            (6) take, sendto fifo3.in;   // count = num
+            (6) sendto fifo2.in;         // count = num
+            kill*;
+fifo3.in:   take, deliver, notify fifo2.out;
+            [12] take, deliver;          // count = 2 * num
+            notify fifo3.out;
+            
+// send done cbd into fifo3
+
+SENDDONE: {
+  DONE:       sendto fifo3.in;
+  fifo2.out:  [2] dismiss;
+              notify fifo3.out;
+  fifo3.in:   take, deliver;
+}
+
+// done cbd
+
+DONE: {
+  fifo1.out:  [6] take, sendto debug.in; // count = num
+}
diff --git a/doc/archman.bib b/doc/archman.bib
new file mode 100644 (file)
index 0000000..b0433e1
--- /dev/null
@@ -0,0 +1,9 @@
+\bibitem{ies02}
+  Sutherland, Ivan, {\it UCB-IES02: Fleet -- A One Instruction Computer }\\
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies02-FLEET-A.Once.Instruction.Computer.pdf}
+\bibitem{ies14}
+  Sutherland, Ivan, {\it UCB-IES14: The Fleet Definition}\\
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies14-Fleet.Definition.pdf}
+\bibitem{ies44}
+  Sutherland, Ivan, {\it UCB-IES44: The Fleet Definition}\\
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies44-Fleet.Definition.pdf}
diff --git a/doc/archman.tex b/doc/archman.tex
new file mode 100644 (file)
index 0000000..7019dd8
--- /dev/null
@@ -0,0 +1,661 @@
+\documentclass[10pt,oneside]{article}
+\reversemarginpar 
+\usepackage[titles]{tocloft}
+\usepackage{emp}
+\usepackage{amsmath}
+\DeclareGraphicsRule{*}{mps}{*}{}
+
+\newcommand{\footnoteremember}[2]{
+  \footnote{#2}
+  \newcounter{#1}
+  \setcounter{#1}{\value{footnote}}
+} \newcommand{\footnoterecall}[1]{
+  \footnotemark[\value{#1}]
+}
+
+\ifx\pdftexversion\undefined
+\usepackage[dvips]{graphicx}
+\DeclareGraphicsExtensions{.eps}\else
+\usepackage[pdftex]{graphicx}
+\DeclareGraphicsExtensions{.pdf,.png,.mps,.mp}
+\usepackage{epstopdf}
+\fi
+\usepackage{palatino}
+\usepackage{wrapfig}
+\usepackage{epsfig}
+\usepackage{verbatim}
+\usepackage{parskip}
+\usepackage{register}
+\usepackage{bytefield}
+\usepackage[colorlinks=true, pdfstartview=FitV, linkcolor=blue, citecolor=blue, urlcolor=blue]{hyperref}
+\renewcommand{\ttdefault}{cmtt}
+\title{The FleetTwo Architecture Manual\\{\normalsize A Programmer's View of FleetTwo}}
+\begin{document}
+\maketitle
+
+\begin{thebibliography}{[GDG01]}
+\bibitem[IES02]{ies02}
+  Sutherland, Ivan,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies02-FLEET-A.Once.Instruction.Computer.pdf}{\it UCB-IES02: Fleet -- A One Instruction Computer}
+\bibitem[IES14]{ies14}
+  Sutherland, Ivan,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies14-Fleet.Definition.pdf}{\it UCB-IES14: The Fleet Definition}
+\bibitem[AM17]{am17}
+  Megacz, Adam,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/adam.megacz/am17-The.Choice.Ship.pdf}{\it UCB-AM17: The Choice Ship}
+\bibitem[IES44]{ies44}
+  Sutherland, Ivan,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies44-Fleet.Definition.pdf}{\it UCB-IES44: The Fleet Definition}
+\bibitem[AM25]{am25}
+  Megacz, Adam,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/adam.megacz/am25.pdf}{\it UCB-AM25: Opcode Ports}
+\bibitem[AM27]{am27}
+  Megacz, Adam,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/adam.megacz/am27.pdf}{\it UCB-AM27: Bypass Paths}
+\bibitem[IES31]{ies31}
+  Sutherland, Ivan,
+  \href{http://research.cs.berkeley.edu/class/fleet/docs/people/ivan.e.sutherland/ies31-Some.SHIPs.pdf}{\it UCB-IES31: Some Ships}
+\bibitem[MS68]{WheelOfReincarnation}
+  Myer, T. and Sutherland, Ivan, {\it On the Design of Display Processors}
+  Communications of the ACM, Vol 11, No. 6, June 1968 .
+\end{thebibliography}
+
+\vspace{1cm}
+\begin{abstract}
+This manual attempts to detail all those aspects of Fleet which are
+visible to a software programmer or compiler backend.
+
+This document assumes that the reader is broadly familiar with the
+Fleet architecture and the motivation behind it.  For a far better
+introduction to these topics, the reader is referred to \cite{ies02}
+\cite{ies14} and \cite{ies44}.  Please bear in mind that many of the
+details in these documents have been changed, but they still serve as
+the authoritative introduction to the architecture.  After reviewing
+these introductory papers, the reader is invited to digest this
+architecture manual for the latest information on the details
+necessary to write software and compilers for Fleet.
+\end{abstract}
+
+
+%\vfill
+%\fbox{\parbox{5in}{\footnotesize
+%\begin{center}
+%The software described in this memo may be obtained using
+%\href{http://www.darcs.net/}{\tt darcs}, with the command:
+%
+%{\tt darcs get http://research.cs.berkeley.edu/class/fleet/repos/fleet/}
+%\end{center}
+%}}
+
+\pagebreak
+\tableofcontents
+
+\pagebreak
+\section{Introduction (from \cite{ies02})}
+
+During the past two and a half years, the Fleet architecture has gone
+through massive changes and improvements.  Nonetheless, the
+fundamental vision remains unchanged.  As Sutherland writes in the
+original Berkeley Fleet description \cite{ies02},
+
+{\it
+When computers were new, logic and storage were expensive and wires
+were relatively cheap.  Early computer designers avoided using logic
+wherever possible but were not greatly concerned with communication.
+They made design choices consistent with the costs of the day.  My
+favorite example is the jump instruction.  Early designers put jump
+instructions at the end of each block of code to avoid the expense of
+storing the address of the next block while executing the present one.
+
+Today's chip fabrication methods invert the older cost balance.  In
+today's integrated circuits logic and memory are now almost free but
+communication costs dominate chip area, energy consumption and delay.
+In spite of these changes in the stuff from which we make computers,
+vestiges of the past remain in many of today's common microprocessor
+designs.  For example, jump instructions still appear at the end of
+each basic block of code in spite of the need to pre-fetch the next
+block while executing this one.  It seems better today to store a
+pointer to the next block and the length of the current block early in
+each block of code.
+
+Instead of following the path of history, I'd like to listen carefully
+to what modern chip structures have to teach about how one might build
+a modern computer.  I see three major lessons.  First, simplicity can
+reduce cost.  Second, moving data will consume most of the time,
+energy and chip area of a modern computer. And third, the low cost of
+logic makes concurrency available if we can figure out how to use it.
+
+\begin{itemize}
+
+\item {\bf Simplicity}: The Fleet architecture seeks simplicity by treating
+      all processing devices alike...
+
+\item {\bf Communication}: The Fleet architecture seeks to control the
+      cost of communication by putting it under direct programmer
+      control.  Thus Fleet avoids instructions like {\sc ADD} or {\sc STORE} that
+      include concealed communication to and from a register file...
+
+\item {\bf Concurrency}: The Fleet architecture assumes concurrency
+      nearly everywhere...
+
+\item {\bf Asynchrony}: This provides enormous flexibility for
+      implementers to improve the performance or reduce the cost of
+      the processing devices in a Fleet system.  -- Synchronous
+      implementations both of ships and of the switch fabric are
+      possible provided they use validity or occupancy bits to achieve
+      the arbitrary delays required at sources and destinations...
+
+\end{itemize}
+}
+
+
+\pagebreak
+\section{The Programmer's View of The Ship-Fabric Interface}
+
+The role of the Fleet switch fabric is to carry {\it packets} from
+{\it sources} to {\it destinations}.
+
+A packet consists of a {\it path} and a {\it payload}.  The path is
+some string of bits which tells the switch fabric how to route from
+the desired source to the desired destination.  The distinction
+between a {\it path} and a {\it destination} is extremely important!
+The payload is either a {\it token} or a {\it data item}.  If the
+payload is a data item, it includes one machine word of data.
+
+The diagram below represents a {\it programmer's} conceptual view of
+the interface between ships and the switch fabric.  Actual
+implementation circuitry may differ substantially.  Sources and
+destinations which can send and receive only tokens -- not data items
+-- are drawn as dashed lines.
+
+\vspace{0.3cm}
+\begin{center}
+\epsfig{file=ports,width=4in}
+\end{center}
+\vspace{0.3cm}
+
+The term {\it port} refers to an interface to the ship, the {\it
+  dock} connecting it to the switch fabric, and the corresponding
+sources and destinations on the switch fabric.
+
+Each dock consists of a {\it data latch}, which is as wide as a
+single machine word and a {\it pump}, which is a circular fifo of
+instruction-width latches.  The values in the instruction fifo
+control the data latch, as future chapters will explain.
+
+Note that the pump in each dock has a destination of its own, and
+that there is no buffering fifo guarding this destination.  Note that
+all other destinations are guarded by a buffering fifo; the size of
+this fifo is exposed to the software programmer so she can avoid
+deadlock.
+
+
+\pagebreak
+\section{Data Formats}
+
+\subsection{Path (12 bits)}
+
+These bits appear physically within the switch fabric. \footnote{In
+  the Sun Labs implementation, these bits have ``address bit
+  timing.''}  The {\tt T} bit is the ``tokenhood'' bit; if set, this
+packet represents a token\footnote{In the Sun Labs
+  implementation, this bit inhibits the switch fabric data latches
+  from firing.}
+
+{\tt\footnotesize
+\begin{bytefield}{49}
+  \bitheader[b]{37,47,48}\\
+  \bitbox{1}{T} 
+  \bitbox{11}{Path} 
+  \bitbox[l]{37}{} 
+\end{bytefield}
+}
+
+\subsection{Data Word In Memory (37 bits)}
+
+A word of data is 37 bits wide.
+
+{\tt\footnotesize
+\begin{bytefield}{49}
+  \bitheader[b]{0,36}\\
+  \bitbox[r]{12}{}
+  \bitbox{37}{Data Word} 
+\end{bytefield}
+}
+
+\subsection{Packet In Flight (49 bits)}
+
+{\tt\footnotesize
+\begin{bytefield}{49}
+  \bitheader[b]{0,36,37,47,48}\\
+  \bitbox{1}{T} 
+  \bitbox{11}{Path} 
+  \bitbox{37}{Data Word} 
+\end{bytefield}
+}
+
+\subsection{Instruction In Memory (37 bits)}
+
+An instruction must be no wider than a memory word.  The next section
+explains the bits in greater detail.  The {\tt Instruction Path} is
+the path which the instruction itself will take in order to arrive at
+the desired pump destination.  The {\it Data/Token Path} is placed on
+any packet inserted into the switch fabric as a result of executing
+the instruction.
+
+{\tt\tiny
+\begin{bytefield}{49}
+  \bitheader[b]{0,6,7,17,18-26,36}\\
+  \bitbox[r]{12}{}
+  \bitbox{11}{Instruction Path}
+  \bitbox{1}{1} 
+  \bitbox{1}{Ti} 
+  \bitbox{1}{Di} 
+  \bitbox{1}{Dc} 
+  \bitbox{1}{Do} 
+  \bitbox{1}{To} 
+  \bitbox{1}{Ig} 
+  \bitbox{1}{Rq} 
+  \bitbox{11}{Data/Token Path} 
+  \bitbox{7}{Count} 
+\end{bytefield}
+}
+
+\subsection{Instruction Packet In Flight (49 bits)}
+
+Note that Fleet simply copies the {\tt Instruction Path} field, bit
+for bit, into the packet {\tt Path} field in order to ``dispatch'' an
+instruction.
+
+{\tt\tiny
+\begin{bytefield}{49}
+  \bitheader[b]{0,6,7,17,18-25,37,47,48}\\
+  \bitbox[r]{1}{0} 
+  \bitbox{11}{Instruction Path}
+  \bitbox{11}{Instruction Path}
+  \bitbox{1}{1} 
+  \bitbox{1}{Ti} 
+  \bitbox{1}{Di} 
+  \bitbox{1}{Dc} 
+  \bitbox{1}{Do} 
+  \bitbox{1}{To} 
+  \bitbox{1}{Ig} 
+  \bitbox{1}{Rq} 
+  \bitbox{11}{Data/Token Path} 
+  \bitbox{7}{Count} 
+\end{bytefield}
+}
+
+\setlength{\bitwidth}{5mm}
+\pagebreak
+
+\section{Instruction Formats}
+\begin{wrapfigure}{R}{2in}
+\epsfig{file=locations,width=2in}
+\vspace{-0.4in}
+\end{wrapfigure}
+Within the pump's instruction fifo, there are two points of particular
+interest.  The first point is the {\it insertion point}, which is the
+point in the ring where new instructions enter from the switch fabric.
+The other point of interest is the {\it execution point}, which is the
+point in the ring where instructions other than {\tt kill} and {\tt
+  unclog} are performed.
+
+The programmer may assume that the insertion point is the immediate
+successor of the execution point.
+
+\vspace{0.3cm}
+{\bf Kill}
+\addcontentsline{toc}{subsection}{Kill}
+
+{\tt
+\begin{bytefield}{26}
+  \bitheader[b]{0,6,7,20-25}\\
+  \bitbox{1}{0} 
+  \bitbox{1}{0} 
+  \bitbox{1}{1} 
+  \bitbox{1}{0} 
+  \bitbox{1}{1} 
+  \bitbox{14}{don't care}
+  \bitbox{7}{Count} 
+\end{bytefield}}
+When a {\tt kill} instruction reaches the insertion point, it will
+wait there for a non-{\tt clog} instruction to reach the execution
+point.  When this occurs, the instruction at the execution point is
+retired and the count field of the {\tt kill} instruction is
+decremented.  If the {\tt kill} instruction's count was {\tt 0} before
+decrementing, the {\tt kill} instruction is retired.  The programmer
+is assured that a kill instruction with a count of $n$ will kill $n+1$
+{\it consecutive} instructions.
+
+\vspace{0.3cm}
+{\bf Clog}
+\addcontentsline{toc}{subsection}{Clog}
+
+{\tt
+\begin{bytefield}{26}
+  \bitheader[b]{0,20-25}\\
+  \bitbox{1}{0} 
+  \bitbox{1}{0} 
+  \bitbox{1}{1} 
+  \bitbox{1}{0} 
+  \bitbox{1}{0} 
+  \bitbox{21}{don't care}
+\end{bytefield}}
+When a {\tt clog} instruction reaches the execution point, it remains
+there and no more instructions will be executed until an {\tt unclog}
+is performed.
+
+\vspace{0.3cm}
+{\bf UnClog}
+\addcontentsline{toc}{subsection}{UnClog}
+
+{\tt
+\begin{bytefield}{26}
+  \bitheader[b]{0,20-25}\\
+  \bitbox{1}{0} 
+  \bitbox{1}{0} 
+  \bitbox{1}{0} 
+  \bitbox{1}{1} 
+  \bitbox{1}{0} 
+  \bitbox{21}{don't care}
+\end{bytefield}}
+When an {\tt unclog} instruction reaches the insertion point, it will wait
+there until a {\tt clog} instruction is at the execution point.  When
+this occurs, both instructions retire.
+
+\vspace{0.3cm}
+{\bf Literal}
+\addcontentsline{toc}{subsection}{Literal}
+
+{\tt
+\begin{bytefield}{26}
+  \bitheader[b]{0,6,7,23-25}\\
+  \bitbox{1}{0} 
+  \bitbox{1}{1} 
+  \bitbox{17}{Literal}
+  \bitbox{7}{Count} 
+\end{bytefield}}
+When a literal instruction reaches the execution point, its {\tt
+  Literal} field is sign-extended to a full word length and captured
+in the data latch.
+
+
+\pagebreak
+{\bf Normal Instruction}
+\addcontentsline{toc}{subsection}{Normal Instruction}
+
+{\tt
+\begin{bytefield}{26}
+  \bitheader[b]{0,6,7,16-25}\\
+  \bitbox{1}{1} 
+  \bitbox{1}{Ti} 
+  \bitbox{1}{Di} 
+  \bitbox{1}{Dc} 
+  \bitbox{1}{Do} 
+  \bitbox{1}{To} 
+  \bitbox{1}{Ig} 
+  \bitbox{1}{Rq} 
+  \bitbox{11}{Dest} 
+  \bitbox{7}{Count} 
+\end{bytefield}
+}
+
+\footnoteremember{tidi}{{\tt Ti}=1,{\tt Di}=1 is invalid on input port.}
+\footnoteremember{didc}{Note that {\tt Di}=0,{\tt Dc}=1
+                 is meaningless and therefore reserved for other
+                 uses.}
+\footnoteremember{todo}{ {\tt To}=1,{\tt Do}=1 have special meaning on an output port.}
+\footnoteremember{toig}{{\tt To}=0,{\tt Ig}=1 is invalid}
+\begin{itemize}
+  \item [\tt Ti] ({\bf Token Input}) wait for a token and acknowledge it.
+
+  \item [\tt Di] ({\bf Data Input}) wait for a datum and acknowledge it.
+                 \footnoterecall{tidi}\footnoterecall{didc}
+
+  \item [\tt Dc] ({\bf Data Capture}) capture (latch) the accepted
+                 datum in the data latch.  This bit is ignored if the incoming packet is
+                 a token. \footnoterecall{didc}
+
+  \item [\tt Do] ({\bf Data Output}) emit a datum.\footnoterecall{todo}
+
+  \item [\tt To] ({\bf Token Output}) emit a token.\footnoterecall{todo}\footnoterecall{toig}
+
+  \item [\tt Ig] ({\bf Ignore {\tt To} Until Last Iteration}) ignore
+                 the {\tt To} bit unless {\tt Count=0}\footnoterecall{toig}
+
+  \item [\tt Rq] ({\bf ReQueue}) if set, instructions having nonzero
+                 count are ``Re-Queued'' rather than RePeated.  See
+                 {\tt Count} for more detail. \footnote{ An
+                 instruction {\it in memory} may not have {\tt
+                 Rq=1,Count=0} (use {\tt Rq=0,Count=0})}
+
+  \item  [\tt Count] ({\bf Count}) {\it After} executing:
+\begin{verbatim}
+if (Count==0) {
+    discard this instruction
+} else {
+    if Count < MAX_COUNT {
+      decrement count
+    }
+    if Rq=1 or Literal {
+       put this instruction back into the instruction fifo
+    } else {
+       execute this instruction again
+    }
+}
+\end{verbatim}
+Note how a ``standing'' instruction is encoded as {\tt Count=MAX\_COUNT}       
+
+\item [\tt Dest] ({\bf Data/Token Destination})
+   Normally, this field is copied into the path portion of any
+   outgoing packet ({\tt Do} on an output port or {\tt To} on either).
+
+   However, in the special case of an output port, if {\tt Do=1,To=1}, then
+   the {\it most significant} {\tt 11} bits of the value in the {\it
+   data register} are used as a destination path instead.
+   %\footnote{This
+   %functionality eliminates the need for any sort of ``{\tt Execute}''
+   %ship, and lets a {\tt Fifo} ship act as an extension of the
+   %instruction queue in the pump.}
+
+\end{itemize}
+
+
+\pagebreak
+\section{Opcodes}
+
+Opcodes, as specified in \cite{am25}, are not yet implemented, but
+should be.
+
+\section{Bypasses}
+
+Bypasses, as specified in \cite{am27}, are not yet implemented, but
+should be.
+
+\section{Sequencing Guarantees}
+
+\addcontentsline{toc}{subsection}{Source Sequence Guarantee}
+If two packets leave the same source and have the same path, they will
+arrive at their common destination {\it in the same order in which
+  they left the source}.  This assurance is referred to as the {\it
+  source sequence guarantee}.
+
+\addcontentsline{toc}{subsection}{Instruction Sequence Guarantee}
+CodeBags in memory consist of an unordered set of {\it fibers}.  A
+fiber is an ordered set of instructions which all share the same
+instruction path, and therefore will be executed by the same pump.
+Any code which dispatches a codebag {\it must} ensure that the
+instructions within a fiber reach their pump in the order in which
+they appear in the fiber.  This is known as the {\it instruction
+  sequence guarantee}.  Typically the software dispatching a codebag
+will take advantage of the source sequence guarantee in order to
+fulfill the instruction sequence guarantee.
+
+\section{Code Bags}
+
+Code bags may overlap in memory.  If the assembler determines that two
+code bags share a set of fibers, it may feel free to re-order those
+fibers in such a way that the code bags overlap, sharing memory words
+for these fibers.  The codebag descriptors for the two bags will then
+have different addresses and/or sizes, but the ranges which they
+encompass will overlap.
+
+\subsection{Dispatching Code Bags}
+
+A codebag is ``dispatched'' by causing its constituent words to
+arrive at the data latch of some output port, and then causing that
+output port's pump to execute a {\tt send} (not {\tt sendto})
+instruction, which is encoded as {\tt Do=1,To=1}.  Because
+instructions are encoded in such a way that their {\tt Instruction
+  Path} appears in the upper 11 bits, the {\tt send} mechanism will
+correctly route the instruction to a pump will execute it.
+
+Currently the {\tt inCBD} port of the {\tt Memory} ship is ideally
+suited for this purpose, although a similar effect can easily be
+achieved using the {\tt BitFifo} ship in conjunction with the {\tt
+  Memory} ship.  The only disadvantage to this arrangement is that the
+{\tt out} port must execute {\tt send} a certain number of times, and
+that number of times is determined by the {\tt size} field of the
+codebag descriptor.  Unfortunately this value is not known at compile
+time, so it cannot be encoded as a repeat count on the instruction at
+the {\tt out} port.  The typical solution is to place a standing ({\tt
+  count=$\infty$}) {\tt send} instruction at the {\tt out} port of one
+{\tt Memory} ship, and reserve that ship exclusively for dispatching
+code bags.
+
+Note that instructions are encoded relative to a particular dispatch
+output port.  That is, the {\tt Instruction Path} field of the
+instruction specifies a path to the desired execution pump -- but this
+path is also specified with respect to some source.  Therefore the
+instruction can be correctly dispatched only from that particular
+source.  However, it is fairly simple to write software which can
+``relocate'' a codebag by replacing the {\tt Instruction Path} fields
+as needed.
+
+\subsection{Tokens and Data Items}
+
+When a data item is sent to a destination which expects a token, such
+as an output port destination, the effect will be the same as if a token
+had been sent to that destination, and the data value will be lost.
+
+When a token is sent to a destination which expects a data item, such
+as a pump destination or an input port destination, the effect will be
+the same as if a data item {\it having an undefined value} were sent
+to that destination.  In other words, the programmer has no completely
+reliable mechanism for distinguishing between tokens and data items.
+
+
+\section{Future Directions}
+
+\subsection{The Role of the Count Field}
+
+Looking back on the design of the pump, several things are now
+apparent which were not initially.  In particular, it seems that it
+could be useful to separate {\it loading the count register} from
+other types of instructions.  This would have a few advantages:
+
+\begin{itemize}
+\item The size of the count field would not be a consideration in the
+      ``instruction budget'' of normal execution instructions
+
+\item It would be possible to have finitely-repeating,
+      infinitely-requeueing instructions.  Various implementation
+      details\footnote{In many implementations, the count field of an
+      instruction is destroyed as it counts down; another register and
+      mux would be needed to ``save'' this value so it could be
+      restored prior to being requeued} make it awkward to support
+      this unless the count register can be manipulated independently
+      of instruction execution.
+\end{itemize}
+
+With this in mind, we can refactor the ``essence of the pump'' into
+the following actions, each of which may or may not be performed by a
+particular instruction:
+
+\begin{itemize}
+\item await and acknowledge a token
+\item await and acknowledge a datum
+\item load the awaited datum into the path latch (top 11 bits)
+\item load the awaited datum into the data latch
+\item load a literal into the data latch
+\item load a literal into the path latch
+\item send the value in the data latch along the path in the path latch
+\item send a token along the path in the path latch
+\item set the count register to a literal value
+\item decrement the count register
+\item requeue this instruction if {\tt count>0}
+\item requeue this instruction unconditionally
+\item repeat this instruction if {\tt count>0}
+\item repeat this instruction unconditionally
+\end{itemize}
+
+The crucial change here is the decoupling of the act of {\it loading
+  the count register} from the act of {\it loading the next
+  instruction}.  It also separates the act of loading the ``path
+latch'' from the act of actually performing the transmission.  This
+latter feature makes it possible to load the data and destination
+latches from two distinct data items, allowing ships to create,
+handle, and consume {\it packets} in the form of a pair of data items.
+
+At this point, the remaining decisions are simply a question of
+instruction bit budgeting.  Currently we have a separate instruction
+form for literals, so that the literal can use bits which are not
+otherwise relevant to literal instructions (for example, {\tt Di}).
+Adding an additional instruction form for loading the count register
+would have similar advantages.
+
+
+\subsection{For Just a Little Bit More...}
+
+Compared to early revisions of the Fleet architecture, the docks of
+FleetTwo are substantially more powerful.  One might ask, why not add
+additional power to the docks, perhaps up to the point of making them
+tiny von Neumann machines in their own right?  Indeed, doing so would
+risk reliving the {\it Wheel of Reincarnation}
+\cite{WheelOfReincarnation}.
+
+I believe, however, that there is a fundamental distinction to be
+made between devices whose control flow {\it can branch} and those
+whose control flow {\it cannot branch}, and that this distinction is
+founded in the geometry of VLSI, and indeed, Euclidean space.
+Ultimately, the instruction stream for any component of a processor
+must exist in some physical incarnation -- some geometric extent.  If
+the control flow of a program is linear, with no branching, then the
+instruction stream has an optimal spatial mapping which is 
+efficient: simply lay it out as a FIFO.
+
+By contrast, however, a program whose instruction stream has
+unrestricted branching is logically a {\it tree} structure.  
+Unfortunately, however, general trees have no efficient mapping onto
+two-dimensional surfaces.  By this, I mean that in every possible
+mapping, there exists some pair of {\it logically adjacent}
+instructions whose {\it physical distance} is proportional to the size
+of the entire program, rather than some constant factor irrespective
+of the program size.  Therefore I conclude that the spatial mapping of
+a program with unrestricted branching is in an entirely different
+class than that of programs with linear control flow, and I choose this
+distinction as the basis for limiting the docks to linear control
+flow sequences.  A similar argument can be made for looping constructs
+in which two or more loops may be nested within a single parent loop.
+
+With this distinction in mind, it would not be objectionable for
+future incarnations of Fleet to have {\it predicated} instructions at
+the docks.  This might take the form of:
+
+\begin{itemize}
+\item Instructions to unconditionally set some ``state flags''
+\item Instructions to conditionally set some ``state flags'' based on the contents of the data latch
+\item Bits which cause an instruction to be ignored or retired based on the state flags
+\end{itemize}
+
+I feel that this addition would not risk falling down the slippery
+slope -- instruction streams with predicated instructions (but not
+unrestricted branching or nested looping) preserve the crucial
+property that they have an efficient spatial mapping.  Any steps
+beyond this, however, cross a fairly fundamental line.
+
+
+\addcontentsline{toc}{section}{Ship Descriptions}
+
+
diff --git a/doc/bytefield.sty b/doc/bytefield.sty
new file mode 100644 (file)
index 0000000..55adde2
--- /dev/null
@@ -0,0 +1,310 @@
+%%
+%% This is file `bytefield.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% bytefield.dtx  (with options: `package')
+%% 
+%% This is a generated file.
+%% 
+%% Copyright (C) 2005 by Scott Pakin <scott+bf@pakin.org>
+%% 
+%% This file may be distributed and/or modified under the conditions of
+%% the LaTeX Project Public License, either version 1.3a of this license
+%% or (at your option) any later version.  The latest version of this
+%% license is in:
+%% 
+%%    http://www.latex-project.org/lppl.txt
+%% 
+%% and version 1.3a or later is part of all distributions of LaTeX version
+%% 2004/10/11 or later.
+%% 
+\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+\ProvidesPackage{bytefield}
+    [2005/07/31 v1.2a Network protocol diagrams]
+\RequirePackage{calc}[1998/07/07]
+\def\bf@newdimen#1{\advance\count11 by 1
+  \ch@ck1\insc@unt\dimen% Check room
+  \allocationnumber=\count11
+  \dimendef#1=\allocationnumber
+  \wlog{\string#1=\string\dimen\the\allocationnumber\space (locally)}}
+\newlength{\bytefield@height}
+\newif\ifcounting@words
+\newlength{\bytefield@height@increment}
+\DeclareRobustCommand{\inc@bytefield@height}[1]{%
+  \setlength{\bytefield@height@increment}{#1}%
+  \global\advance\bytefield@height by \bytefield@height@increment}
+\newcounter{bits@wide}
+\newsavebox{\entire@bytefield@picture}
+\newenvironment{bytefield}[1]{%
+  \setcounter{bits@wide}{#1}%
+  \let\old@nl=\\%
+  \let\amp=&%
+  \catcode`\&=10
+  \openup -1pt
+  \setlength{\bytefield@height}{0pt}%
+  \setlength{\unitlength}{1pt}%
+  \counting@wordstrue
+  \begin{lrbox}{\entire@bytefield@picture}%
+  \renewcommand{\\}{%
+    \amp\show@wordlabelr\cr%
+    \ignorespaces\counting@wordstrue\make@lspace\amp}%
+  \vbox\bgroup\ialign\bgroup##\amp##\amp##\cr\amp%
+}{%
+  \amp\show@wordlabelr\cr\egroup\egroup%
+  \end{lrbox}%
+  \usebox{\entire@bytefield@picture}}
+\newlength{\bitwidth}
+\AtBeginDocument{\settowidth{\bitwidth}{\tiny 99i}}
+\newlength{\byteheight}
+\AtBeginDocument{\setlength{\byteheight}{4ex}}
+\newlength{\units@wide}
+\newlength{\units@tall}
+\DeclareRobustCommand{\bitbox}[3][lrtb]{%
+  \setlength{\units@wide}{\bitwidth * #2}%
+  \parse@bitbox@arg{#1}%
+  \draw@bit@picture{\strip@pt\units@wide}{\strip@pt\byteheight}{#3}}
+\DeclareRobustCommand{\wordbox}[3][lrtb]{%
+  \setlength{\units@wide}{\bitwidth * \value{bits@wide}}%
+  \setlength{\units@tall}{\byteheight * #2}%
+  \parse@bitbox@arg{#1}%
+  \draw@bit@picture{\strip@pt\units@wide}{\strip@pt\units@tall}{#3}}
+\DeclareRobustCommand{\draw@bit@picture}[3]{%
+  \begin{picture}(#1,#2)%
+    \put(0,0){\makebox(#1,#2){\parbox[c]{#1\unitlength}{%
+      \bf@newdimen\height
+      \bf@newdimen\depth
+      \bf@newdimen\totalheight
+      \bf@newdimen\width
+      \height=#2\unitlength
+      \depth=0pt%
+      \totalheight=#2\unitlength
+      \width=#1\unitlength
+      \def\widthunits{#1}%
+      \def\heightunits{#2}%
+      \centering #3}}}%
+    \ifbitbox@top
+      \put(0,#2){\line(1,0){#1}}
+    \fi
+    \ifbitbox@bottom
+      \put(0,0){\line(1,0){#1}}
+    \fi
+    \ifbitbox@left
+      \put(0,0){\line(0,1){#2}}
+    \fi
+    \ifbitbox@right
+      \put(#1,0){\line(0,1){#2}}
+    \fi
+  \end{picture}%
+  \ifcounting@words
+    \inc@bytefield@height{\unitlength * \real{#2}}%
+    \counting@wordsfalse
+  \fi
+  \ignorespaces}
+\newif\ifbitbox@top
+\newif\ifbitbox@bottom
+\newif\ifbitbox@left
+\newif\ifbitbox@right
+\def\parse@bitbox@arg#1{%
+  \bitbox@topfalse
+  \bitbox@bottomfalse
+  \bitbox@leftfalse
+  \bitbox@rightfalse
+  \parse@bitbox@sides#1X}
+\def\parse@bitbox@sides#1{%
+  \ifx#1X%
+  \else
+    \ifx#1t%
+      \bitbox@toptrue
+    \else
+      \ifx#1b%
+        \bitbox@bottomtrue
+      \else
+        \ifx#1l%
+          \bitbox@lefttrue
+        \else
+          \ifx#1r%
+            \bitbox@righttrue
+          \fi
+        \fi
+      \fi
+    \fi
+    \expandafter\parse@bitbox@sides
+  \fi}
+\newlength{\units@high}
+\DeclareRobustCommand{\skippedwords}[1][2ex]{%
+  \setlength{\units@wide}{\bitwidth * \value{bits@wide}}%
+  \setlength{\units@high}{1pt * \ratio{\units@wide}{6.0pt}}%
+  \setlength{\units@tall}{#1 + \units@high}%
+  \edef\num@wide{\strip@pt\units@wide}%
+  \edef\num@tall{\strip@pt\units@tall}%
+  \edef\num@high{\strip@pt\units@high}%
+  \begin{picture}(\num@wide,\num@tall)
+    \put(0,\num@tall){\line(6,-1){\num@wide}}
+    \put(\num@wide,0){\line(-6,1){\num@wide}}
+    \put(0,0){\line(0,1){\num@high}}
+    \put(\num@wide,\num@tall){\line(0,-1){\num@high}}
+  \end{picture}%
+  \ifcounting@words
+    \inc@bytefield@height{\unitlength * \real{\num@tall}}%
+    \counting@wordsfalse
+  \fi}
+\DeclareRobustCommand{\bitheader}[2][l]{%
+  \parse@bitbox@arg{lrtb}%
+  \setlength{\units@wide}{\bitwidth * \value{bits@wide}}%
+  \setlength{\units@tall}{\heightof{\tiny 9}}%
+  \setlength{\units@high}{\units@tall * -1}%
+  \def\bit@endianness{#1}%
+  \begin{picture}(\strip@pt\units@wide,\strip@pt\units@tall)%
+                 (0,\strip@pt\units@high)
+    \parse@range@list#2,X,
+  \end{picture}%
+  \ifcounting@words
+    \inc@bytefield@height{\unitlength * \real{\strip@pt\units@tall}}%
+    \counting@wordsfalse
+  \fi
+  \ignorespaces}
+\def\parse@range@list#1,{%
+  \ifx X#1
+  \else
+    \parse@range#1-#1-#1\relax
+    \expandafter\parse@range@list
+  \fi}
+\newlength{\header@xpos}
+\newcounter{header@val}
+\newcounter{max@header@val}
+\def\parse@range#1-#2-#3\relax{%
+  \setcounter{header@val}{#1}
+  \setcounter{max@header@val}{#2 + 1}
+  \loop
+    \ifnum\value{header@val}<\value{max@header@val}%
+      \if\bit@endianness b%
+        \setlength{\header@xpos}{%
+          \bitwidth * (\value{bits@wide}-\value{header@val}-1)}
+      \else
+        \setlength{\header@xpos}{\bitwidth * \value{header@val}}
+      \fi
+      \put(\strip@pt\header@xpos,0){%
+        \makebox(\strip@pt\bitwidth,\strip@pt\units@tall){%
+          \tiny \theheader@val}}
+      \addtocounter{header@val}{1}
+  \repeat}
+\newlength{\curlyshrinkage}
+\setlength{\curlyshrinkage}{5pt}
+\newlength{\curlyspace}
+\AtBeginDocument{\setlength{\curlyspace}{1ex}}
+\newlength{\labelspace}
+\AtBeginDocument{\setlength{\labelspace}{0.5ex}}
+\newbox{\curly@box}
+\def\store@rcurly#1#2{%
+  \begingroup
+    \bf@newdimen\curly@height%
+    \setlength{\curly@height}{#2 - \curlyshrinkage}%
+    \bf@newdimen\half@curly@height%
+    \setlength{\half@curly@height}{0.5\curly@height}%
+    \bf@newdimen\curly@shift%
+    \setlength{\curly@shift}{\half@curly@height + 0.5\curlyshrinkage}%
+    \global\sbox{#1}{\raisebox{\curly@shift}{%
+      $\xdef\old@axis{\the\fontdimen22\textfont2}$%
+      $\fontdimen22\textfont2=0pt%
+       \left.\vrule height\half@curly@height
+                    width 0pt
+                    depth\half@curly@height\right\}$%
+      $\fontdimen22\textfont2=\old@axis$}}%
+  \endgroup
+}
+\def\store@lcurly#1#2{%
+  \begingroup
+    \bf@newdimen\curly@height%
+    \setlength{\curly@height}{#2 - \curlyshrinkage}%
+    \bf@newdimen\half@curly@height%
+    \setlength{\half@curly@height}{0.5\curly@height}%
+    \bf@newdimen\curly@shift%
+    \setlength{\curly@shift}{\half@curly@height + 0.5\curlyshrinkage}%
+    \global\sbox{#1}{\raisebox{\curly@shift}{%
+      $\xdef\old@axis{\the\fontdimen22\textfont2}$%
+      $\fontdimen22\textfont2=0pt%
+       \left\{\vrule height\half@curly@height
+                     width 0pt
+                     depth\half@curly@height\right.$%
+      $\fontdimen22\textfont2=\old@axis$}}%
+  \endgroup
+}
+\def\show@wordlabelr{}
+\newlength{\wordlabelr@start}
+\newlength{\wordlabelr@end}
+\newenvironment{wordgroupr}[1]{%
+  \global\wordlabelr@start=\bytefield@height
+  \gdef\wordlabelr@text{#1}%
+  \ignorespaces%
+}{%
+  \global\wordlabelr@end=\bytefield@height
+  \gdef\show@wordlabelr{%
+    \sbox{\word@label@box}{%
+      \begin{tabular}[b]{@{}l@{}}\wordlabelr@text\end{tabular}}%
+    \settowidth{\label@box@width}{\usebox{\word@label@box}}%
+    \setlength{\label@box@height}{\wordlabelr@end-\wordlabelr@start}%
+    \store@rcurly{\curly@box}{\label@box@height}%
+    \bf@newdimen\total@box@width%
+    \setlength{\total@box@width}{%
+      \curlyspace +
+      \widthof{\usebox{\curly@box}} +
+      \labelspace +
+      \label@box@width}%
+    \begin{picture}(\strip@pt\total@box@width,0)
+      \put(0,0){%
+        \hspace*{\curlyspace}%
+        \usebox{\curly@box}%
+        \hspace*{\labelspace}%
+        \makebox(\strip@pt\label@box@width,\strip@pt\label@box@height){%
+          \usebox{\word@label@box}}}
+    \end{picture}%
+    \gdef\show@wordlabelr{}}%
+  \ignorespaces}
+\newlength{\wordlabell@start}
+\newlength{\wordlabell@end}
+\newlength{\total@lbox@width}
+\gdef\make@lspace{}
+\newenvironment{wordgroupl}[1]{%
+  \global\wordlabell@start=\bytefield@height
+  \gdef\wordlabell@text{#1}%
+  \sbox{\word@label@box}{%
+    \begin{tabular}[b]{@{}l@{}}\wordlabell@text\end{tabular}}%
+  \settowidth{\label@box@width}{\usebox{\word@label@box}}%
+  \store@lcurly{\curly@box}{5cm}%
+  \setlength{\total@lbox@width}{%
+    \curlyspace +
+    \widthof{\usebox{\curly@box}} +
+    \labelspace +
+    \label@box@width}%
+  \global\total@lbox@width=\total@lbox@width
+  \gdef\make@lspace{%
+    \hspace*{\total@lbox@width}%
+    \gdef\make@lspace{}}%
+  \ignorespaces%
+}{%
+  \global\wordlabell@end=\bytefield@height
+  \bf@newdimen\starting@point
+  \setlength{\starting@point}{%
+    -\total@lbox@width - \bitwidth*\value{bits@wide}}%
+  \sbox{\word@label@box}{%
+    \begin{tabular}[b]{@{}l@{}}\wordlabell@text\end{tabular}}%
+  \settowidth{\label@box@width}{\usebox{\word@label@box}}%
+  \setlength{\label@box@height}{\wordlabell@end-\wordlabell@start}%
+  \store@lcurly{\curly@box}{\label@box@height}%
+  \begin{picture}(0,0)
+    \put(\strip@pt\starting@point,0){%
+      \makebox(\strip@pt\label@box@width,\strip@pt\label@box@height){%
+        \usebox{\word@label@box}}%
+      \hspace*{\labelspace}%
+      \usebox{\curly@box}%
+      \hspace*{\curlyspace}}
+  \end{picture}%
+  \ignorespaces}
+\newlength{\label@box@width}
+\newlength{\label@box@height}
+\newsavebox{\word@label@box}
+\endinput
+%%
+%% End of file `bytefield.sty'.
diff --git a/doc/javadoc.css b/doc/javadoc.css
new file mode 100644 (file)
index 0000000..5070af3
--- /dev/null
@@ -0,0 +1,9 @@
+/* Page background color */
+body {
+   font-family: arial, helvetica, sans-serif;
+   font-size: 14px;
+   margin-left: 40px;
+   margin-right: 40px;
+   margin-top: 0px;
+}
+
diff --git a/doc/locations.svg b/doc/locations.svg
new file mode 100644 (file)
index 0000000..0ebd888
--- /dev/null
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1052.3622"
+   height="744.09448"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/Users/megacz/proj/fleet/doc"
+   sodipodi:docname="locations.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow2Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mstart"
+       style="overflow:visible">
+      <path
+         id="path3224"
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) translate(0,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Mend"
+       style="overflow:visible">
+      <path
+         id="path3227"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(-0.6,-0.6)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend"
+       style="overflow:visible">
+      <path
+         id="path3209"
+         d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.3060085"
+     inkscape:cx="485.19327"
+     inkscape:cy="306.01725"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     gridspacingx="2mm"
+     gridspacingy="2mm"
+     gridanglex="8.4666669mm"
+     gridanglez="8.4666669mm"
+     grid_units="mm"
+     inkscape:grid-bbox="false"
+     inkscape:grid-points="true"
+     inkscape:window-width="1640"
+     inkscape:window-height="1006"
+     inkscape:window-x="0"
+     inkscape:window-y="22"
+     width="1052.3622px"
+     height="744.09448px"
+     showguides="true"
+     inkscape:guide-bbox="true" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 744.09449,354.33071 L 492.97638,354.33071"
+       id="path3413"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 481.88976,304.72441 L 711.74803,304.72441"
+       id="path3397"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 315.81102,340.15748 L 222.77165,340.15748"
+       id="path3193"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 432.28346,425.19686 L 432.28346,368.50394"
+       id="path3171" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 488.97638,283.46456 L 488.97638,389.76378 L 361.41733,389.76378 L 311.81103,340.15748 L 361.41733,283.46456 L 488.97638,283.46456 z "
+       id="path3187"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 422.72608,389.92662 L 432.28346,375.59056 L 441.84084,389.92662 L 422.72608,389.92662 z "
+       id="path3189" />
+    <g
+       id="g3407"
+       transform="translate(190.67764,269.74805)"
+       style="stroke:#999999">
+      <rect
+         y="74.409424"
+         x="439.37009"
+         height="21.259842"
+         width="21.259842"
+         id="rect3399"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#999999;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="460.62991"
+         height="21.259842"
+         width="21.259842"
+         id="rect3401"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#999999;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="481.88977"
+         height="21.259842"
+         width="21.259842"
+         id="rect3403"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#999999;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="503.1496"
+         height="21.259842"
+         width="21.259842"
+         id="rect3405"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#999999;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#999999;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="414.26114"
+       y="330.02695"
+       id="text3565"><tspan
+         sodipodi:role="line"
+         id="tspan3567"
+         x="414.26114"
+         y="330.02695"
+         style="text-align:center;text-anchor:middle;fill:#999999">Data</tspan><tspan
+         sodipodi:role="line"
+         x="414.26114"
+         y="357.17814"
+         id="tspan3569"
+         style="text-align:center;text-anchor:middle;fill:#999999">Latch</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 304.72441,425.54331 L 474.80315,425.54331 C 474.80315,425.54331 482.22667,425.21799 481.88976,432.62992 L 481.88976,488.97638 C 481.88976,488.97638 482.55199,496.06299 474.80315,496.06299 L 276.37795,496.06299 C 276.37795,496.06299 269.29133,497.39903 269.29133,488.97638 L 269.29133,432.62992 C 268.28061,424.20727 276.37795,425.54331 276.37795,425.54331 L 304.72441,425.54331 z "
+       id="path2247"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 290.37796,412.11024 L 290.37796,440.45669 L 325.81103,440.45669 L 339.98426,426.28347 L 325.81103,412.11024 L 290.37796,412.11024 z "
+       id="path2249" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 347.07087,412.11024 L 347.07087,440.45669 L 382.50394,440.45669 L 396.67717,426.28347 L 382.50394,412.11024 L 347.07087,412.11024 z "
+       id="path2251" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 453.37007,482.97637 L 453.37007,511.32282 L 417.937,511.32282 L 403.76377,497.1496 L 417.937,482.97637 L 453.37007,482.97637 z "
+       id="path2253" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 396.67716,482.97638 L 396.67716,511.32283 L 361.24409,511.32283 L 347.07086,497.14961 L 361.24409,482.97638 L 396.67716,482.97638 z "
+       id="path2255" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 339.98425,482.97637 L 339.98425,511.32282 L 304.55118,511.32282 L 290.37795,497.1496 L 304.55118,482.97637 L 339.98425,482.97637 z "
+       id="path2257" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#008000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 410.8504,412.11024 L 410.8504,440.45669 L 446.28347,440.45669 L 460.4567,426.28347 L 446.28347,412.11024 L 410.8504,412.11024 z "
+       id="path2259" />
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#999999;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="349.24408"
+       y="467.5433"
+       id="text2261"><tspan
+         sodipodi:role="line"
+         id="tspan2263"
+         x="349.24408"
+         y="467.5433">Pump</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 581.10236,576.92917 L 474.80315,504.06302"
+       id="path3244"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#008000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 581.10236,389.76377 L 460.62992,418.11023"
+       id="path4215"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="589.10236"
+       y="396.8504"
+       id="text4217"><tspan
+         sodipodi:role="line"
+         id="tspan4219"
+         x="589.10236"
+         y="396.8504">Execution Point</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="628.76544"
+       y="566.92914"
+       id="text4221"><tspan
+         sodipodi:role="line"
+         id="tspan4223"
+         x="628.76544"
+         y="566.92914"
+         style="text-align:center;text-anchor:middle;fill:#ff0000">Insertion</tspan><tspan
+         sodipodi:role="line"
+         x="628.76544"
+         y="594.08033"
+         id="tspan4225"
+         style="text-align:center;text-anchor:middle;fill:#ff0000">Point</tspan></text>
+    <path
+       style="fill:#999999;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 481.88975,446.45669 L 481.88975,474.80314"
+       id="path3421"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#999999;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="568.98541"
+       y="489.13257"
+       id="text3495"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3497"
+         x="568.98541"
+         y="489.13257"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#999999">Destination</tspan></text>
+    <path
+       style="fill:#999999;fill-rule:evenodd;stroke:#ff0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 531.66928,496.49172 L 446.62992,496.49172"
+       id="path3221"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:#999999;fill-rule:evenodd;stroke:#999999;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 732.09448,496.49171 L 480.97637,496.49171"
+       id="path3423"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
diff --git a/doc/ports.svg b/doc/ports.svg
new file mode 100644 (file)
index 0000000..07e5685
--- /dev/null
@@ -0,0 +1,552 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1052.3622"
+   height="744.09448"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/Users/megacz/proj/fleet/doc"
+   sodipodi:docname="ports.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow2Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mstart"
+       style="overflow:visible">
+      <path
+         id="path3224"
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) translate(0,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Mend"
+       style="overflow:visible">
+      <path
+         id="path3227"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(-0.6,-0.6)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend"
+       style="overflow:visible">
+      <path
+         id="path3209"
+         d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.1836462"
+     inkscape:cx="679.09752"
+     inkscape:cy="195.2233"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     gridspacingx="2mm"
+     gridspacingy="2mm"
+     gridanglex="8.4666669mm"
+     gridanglez="8.4666669mm"
+     grid_units="mm"
+     inkscape:grid-bbox="false"
+     inkscape:grid-points="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="1050"
+     inkscape:window-x="137"
+     inkscape:window-y="22"
+     width="1052.3622px"
+     height="744.09448px" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 439.37009,581.10236 L 609.44883,581.10236 C 609.44883,581.10236 616.87235,580.77704 616.53544,588.18897 L 616.53544,644.53543 C 616.53544,644.53543 617.19767,651.62204 609.44883,651.62204 L 411.02363,651.62204 C 411.02363,651.62204 403.93701,652.95808 403.93701,644.53543 L 403.93701,588.18897 C 402.92629,579.76632 411.02363,581.10236 411.02363,581.10236 L 439.37009,581.10236 z "
+       id="path2172"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 616.53543,602.18898 L 616.53543,630.53543"
+       id="path3421"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#008080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 616.53543,460.62992 L 843.30709,460.62992"
+       id="path3457"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#800080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 878.74016,191.33858 L 627.62205,191.33858"
+       id="path3413"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#008080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 616.53543,141.73228 L 846.3937,141.73228"
+       id="path3397"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 347.24409,496.06299 L 484.97638,496.06299"
+       id="path3195"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 450.45669,177.16535 L 357.41732,177.16535"
+       id="path3193"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 566.92913,581.10237 L 566.92913,524.40945"
+       id="path3147" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 425.19686,566.92914 L 425.19686,595.27559 L 460.62993,595.27559 L 474.80316,581.10237 L 460.62993,566.92914 L 425.19686,566.92914 z "
+       id="path2160" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 481.88977,566.92914 L 481.88977,595.27559 L 517.32284,595.27559 L 531.49607,581.10237 L 517.32284,566.92914 L 481.88977,566.92914 z "
+       id="path2162" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 588.18897,637.79527 L 588.18897,666.14172 L 552.7559,666.14172 L 538.58267,651.9685 L 552.7559,637.79527 L 588.18897,637.79527 z "
+       id="path2164" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 531.49606,637.79528 L 531.49606,666.14173 L 496.06299,666.14173 L 481.88976,651.96851 L 496.06299,637.79528 L 531.49606,637.79528 z "
+       id="path2166" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 474.80315,637.79527 L 474.80315,666.14172 L 439.37008,666.14172 L 425.19685,651.9685 L 439.37008,637.79527 L 474.80315,637.79527 z "
+       id="path2168" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 545.6693,566.92914 L 545.6693,595.27559 L 581.10237,595.27559 L 595.2756,581.10237 L 581.10237,566.92914 L 545.6693,566.92914 z "
+       id="path2170" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#008000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 488.97638,439.53292 L 488.97638,545.83213 L 616.53543,545.83213 L 666.14173,496.22584 L 616.53543,439.53292 L 488.97638,439.53292 z "
+       id="path2174"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 557.37175,545.83213 L 566.92913,531.49607 L 576.48651,545.83213 L 557.37175,545.83213 z "
+       id="path3149" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 566.92913,262.20473 L 566.92913,205.51181"
+       id="path3171" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#008000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 623.62205,120.47243 L 623.62205,226.77165 L 496.063,226.77165 L 446.4567,177.16535 L 496.063,120.47243 L 623.62205,120.47243 z "
+       id="path3187"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 557.37175,226.93449 L 566.92913,212.59843 L 576.48651,226.93449 L 557.37175,226.93449 z "
+       id="path3189" />
+    <rect
+       style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3191"
+       width="177.16536"
+       height="552.75592"
+       x="177.16536"
+       y="106.29921" />
+    <g
+       id="g3407"
+       transform="translate(325.32331,106.75592)"
+       style="stroke:#800080">
+      <rect
+         y="74.409424"
+         x="439.37009"
+         height="21.259842"
+         width="21.259842"
+         id="rect3399"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="460.62991"
+         height="21.259842"
+         width="21.259842"
+         id="rect3401"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="481.88977"
+         height="21.259842"
+         width="21.259842"
+         id="rect3403"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="503.1496"
+         height="21.259842"
+         width="21.259842"
+         id="rect3405"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    </g>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#800080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 876.04724,533.49606 L 635.62205,533.49606"
+       id="path3445"
+       sodipodi:nodetypes="cc" />
+    <g
+       id="g3447"
+       transform="translate(325.98424,448.91341)"
+       style="stroke:#800080">
+      <rect
+         y="74.409424"
+         x="439.37009"
+         height="21.259842"
+         width="21.259842"
+         id="rect3449"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="460.62991"
+         height="21.259842"
+         width="21.259842"
+         id="rect3451"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="481.88977"
+         height="21.259842"
+         width="21.259842"
+         id="rect3453"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <rect
+         y="74.409424"
+         x="503.1496"
+         height="21.259842"
+         width="21.259842"
+         id="rect3455"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#800080;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:52.43335342px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="205.51183"
+       y="396.8504"
+       id="text3459"><tspan
+         sodipodi:role="line"
+         id="tspan3461"
+         x="205.51183"
+         y="396.8504">Ship</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="484.06299"
+       y="622.36218"
+       id="text3467"><tspan
+         sodipodi:role="line"
+         id="tspan3469"
+         x="484.06299"
+         y="622.36218">Pump</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#800080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="703.63574"
+       y="184.24554"
+       id="text3479"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3481"
+         x="703.63574"
+         y="184.24554"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#800080">Destination</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="703.61377"
+       y="134.64098"
+       id="text3483"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3485"
+         x="703.61377"
+         y="134.64098"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#008080">Source</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="703.61377"
+       y="455.52747"
+       id="text3487"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3489"
+         x="703.61377"
+         y="455.52747"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#008080">Source</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;fill:#800080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="651.99121"
+       y="528.39105"
+       id="text3491"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3493"
+         x="651.99121"
+         y="528.39105"
+         style="font-size:18px;fill:#800080">Destination</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#800080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="703.63574"
+       y="644.85944"
+       id="text3495"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3497"
+         x="703.63574"
+         y="644.85944"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#800080">Destination</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 389.76378,680.31495 L 389.76378,708.66141"
+       id="path3501" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 389.76378,694.48818 L 155.90551,694.48818"
+       id="path3503" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 673.22835,680.31495 L 673.22835,708.66141"
+       id="path3507" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 673.22835,694.48818 L 850.3937,694.48818"
+       id="path3509" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 389.76378,694.48818 L 673.22835,694.48818"
+       id="path3511" />
+    <text
+       xml:space="preserve"
+       style="font-size:21.32734108px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="273.22864"
+       y="722.83466"
+       id="text3515"><tspan
+         sodipodi:role="line"
+         id="tspan3517"
+         x="273.22864"
+         y="722.83466">Ship</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.32734108px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="541.69458"
+       y="722.83466"
+       id="text3519"><tspan
+         sodipodi:role="line"
+         id="tspan3521"
+         x="541.69458"
+         y="722.83466"
+         style="text-align:center;text-anchor:middle">Docks</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.32734108px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="972.50598"
+       y="531.49603"
+       id="text3523"><tspan
+         sodipodi:role="line"
+         x="972.50598"
+         y="531.49603"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3535">Output</tspan><tspan
+         sodipodi:role="line"
+         x="972.50598"
+         y="558.15521"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3539">Port</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.10158062;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 871.70433,389.81456 C 871.70433,389.81456 885.82677,389.91124 885.82677,405.52036 L 885.82677,531.16676 C 885.82677,546.79199 899.94921,546.87256 899.94921,546.87256 C 899.94921,546.87256 885.82677,548.38826 885.82677,562.57837 L 885.82677,664.66606 C 885.82677,680.98468 871.70433,680.37186 871.70433,680.37186"
+       id="path3527"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 871.65354,106.29921 C 871.65354,106.29921 885.82677,106.38646 885.82677,120.47244 L 885.82677,233.85827 C 885.82677,247.95879 900,248.0315 900,248.0315 C 900,248.0315 885.82677,249.39929 885.82677,262.20473 L 885.82677,354.33071 C 885.82677,369.05696 871.65354,368.50394 871.65354,368.50394"
+       id="path3529"
+       sodipodi:nodetypes="ccccccc" />
+    <text
+       xml:space="preserve"
+       style="font-size:21.32734108px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="756.60126"
+       y="722.83466"
+       id="text3531"><tspan
+         sodipodi:role="line"
+         id="tspan3533"
+         x="756.60126"
+         y="722.83466"
+         style="text-align:center;text-anchor:middle">Switch Fabric</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.32734108px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="972.50598"
+       y="240.94487"
+       id="text3541"><tspan
+         sodipodi:role="line"
+         x="972.50598"
+         y="240.94487"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3545">Input</tspan><tspan
+         sodipodi:role="line"
+         x="972.50598"
+         y="267.60405"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3549">Port</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="565.48059"
+       y="488.62991"
+       id="text3551"><tspan
+         sodipodi:role="line"
+         id="tspan3553"
+         x="565.48059"
+         y="488.62991"
+         style="text-align:center;text-anchor:middle;fill:#008000">Data</tspan><tspan
+         sodipodi:role="line"
+         x="565.48059"
+         y="515.7811"
+         id="tspan3555"
+         style="text-align:center;text-anchor:middle;fill:#008000">Latch</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="548.9068"
+       y="167.03481"
+       id="text3565"><tspan
+         sodipodi:role="line"
+         id="tspan3567"
+         x="548.9068"
+         y="167.03481"
+         style="text-align:center;text-anchor:middle;fill:#008000">Data</tspan><tspan
+         sodipodi:role="line"
+         x="548.9068"
+         y="194.18599"
+         id="tspan3569"
+         style="text-align:center;text-anchor:middle;fill:#008000">Latch</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 680.31496,652.22401 L 595.2756,652.22401"
+       id="path3221"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#800080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 878.74016,652.224 L 627.62205,652.224"
+       id="path3423"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 439.37013,276.37794 L 609.44887,276.37794 C 609.44887,276.37794 616.87239,276.05262 616.53548,283.46455 L 616.53548,339.81101 C 616.53548,339.81101 617.19771,346.89762 609.44887,346.89762 L 411.02367,346.89762 C 411.02367,346.89762 403.93705,348.23366 403.93705,339.81101 L 403.93705,283.46455 C 402.92633,275.0419 411.02367,276.37794 411.02367,276.37794 L 439.37013,276.37794 z "
+       id="path3223"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 616.53547,297.46456 L 616.53547,325.81101"
+       id="path3225"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 425.1969,262.20472 L 425.1969,290.55117 L 460.62997,290.55117 L 474.8032,276.37795 L 460.62997,262.20472 L 425.1969,262.20472 z "
+       id="path3228" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 481.88981,262.20472 L 481.88981,290.55117 L 517.32288,290.55117 L 531.49611,276.37795 L 517.32288,262.20472 L 481.88981,262.20472 z "
+       id="path3230" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 588.18901,333.07085 L 588.18901,361.4173 L 552.75594,361.4173 L 538.58271,347.24408 L 552.75594,333.07085 L 588.18901,333.07085 z "
+       id="path3232" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 531.4961,333.07086 L 531.4961,361.41731 L 496.06303,361.41731 L 481.8898,347.24409 L 496.06303,333.07086 L 531.4961,333.07086 z "
+       id="path3234" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 474.80319,333.07085 L 474.80319,361.4173 L 439.37012,361.4173 L 425.19689,347.24408 L 439.37012,333.07085 L 474.80319,333.07085 z "
+       id="path3236" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 545.66934,262.20472 L 545.66934,290.55117 L 581.10241,290.55117 L 595.27564,276.37795 L 581.10241,262.20472 L 545.66934,262.20472 z "
+       id="path3238" />
+    <text
+       xml:space="preserve"
+       style="font-size:21.72095108px;font-style:normal;font-weight:normal;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="484.06305"
+       y="317.63776"
+       id="text3240"><tspan
+         sodipodi:role="line"
+         id="tspan3242"
+         x="484.06305"
+         y="317.63776">Pump</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#800080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="703.63574"
+       y="340.14563"
+       id="text3244"
+       transform="scale(0.9999652,1.0000348)"><tspan
+         sodipodi:role="line"
+         id="tspan3246"
+         x="703.63574"
+         y="340.14563"
+         style="font-size:18px;text-align:center;text-anchor:middle;fill:#800080">Destination</tspan></text>
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 680.315,347.49959 L 595.27564,347.49959"
+       id="path3248"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#800080;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 878.74016,347.49958 L 627.62209,347.49958"
+       id="path3250"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
diff --git a/doc/register.sty b/doc/register.sty
new file mode 100644 (file)
index 0000000..3e1755a
--- /dev/null
@@ -0,0 +1,358 @@
+%%
+%% This is file `register.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% register.dtx  (with options: `package')
+%% Register diagrams with field descriptions.
+%% 
+%% This program is provided under the terms of the
+%% LaTeX Project Public License distributed from CTAN
+%% archives in directory macros/latex/base/lppl.txt.
+%% 
+%% Author: Matthew Lovell (lovell@indra.com)
+%% 
+
+
+
+\ProvidesPackage{register} [2007/03/08 v1.5 Register macros with
+hyperref/LyX support]
+
+\RequirePackage{ifthen}[1997/11/02]
+\RequirePackage{graphicx}[1997/06/09]
+\RequirePackage{float}[2001/07/25]
+\RequirePackage{calc}[1998/06/07]
+\DeclareOption{LyX}{\setboolean{RegisterLyX}{true}}
+\DeclareOption{hyperref}{\setboolean{RegisterHyperref}{true}}
+\DeclareOption{TRflags}{\setboolean{RegisterTRFlags}{true}}
+\DeclareOption{TRboxed}{\setboolean{RegisterTRBoxed}{true}}
+
+\DeclareOption*{%  Emit a warning for other options
+  \PackageWarning{register}{Unknown option '\CurrentOption'}%
+}
+
+\newboolean{RegisterLyX}
+\newboolean{RegisterHyperref}
+\newboolean{RegisterTRFlags}
+\newboolean{RegisterTRBoxed}
+
+\setboolean{RegisterLyX}{false}
+\setboolean{RegisterHyperref}{false}
+\setboolean{RegisterTRFlags}{false}
+\setboolean{RegisterTRBoxed}{false}
+
+\ProcessOptions\relax  % Process package options
+\newboolean{RegisterContext}
+\setboolean{RegisterContext}{false}
+\floatstyle{plaintop} \@ifundefined{chapter}
+{\newfloat{Regfloat}{tbp}{rdf}[section]}
+{\newfloat{Regfloat}{tbp}{rdf}[chapter]}
+\floatname{Regfloat}{Register}
+\newlength{\regWidth}
+\newlength{\regFieldLen}
+\newlength{\regLabelAdjust}
+\newlength{\regResetHeight}
+\newlength{\regResetDepth}
+\newlength{\regResetDrop}
+\newlength{\regDescSkip}
+\setlength{\regWidth}{0.95\textwidth}
+\newcommand{\regBitWidth}{32}
+\newcommand{\regResetName}{Reset}
+\newcommand{\regBitSize}{\tiny}
+\newcommand{\regBitFamily}{\sffamily}
+\newcommand{\regResetSize}{\scriptsize}
+\newcommand{\regLabelSize}{\footnotesize}
+\newcommand{\regLabelFamily}{\rmfamily}
+\newcommand{\regDescFamily}{\bf}
+\newlength{\regdescsep}
+\newlength{\oldregdescsep}
+\setlength{\regdescsep}{-\medskipamount}
+
+\newsavebox{\Label}
+\newsavebox{\RotatedLabel}
+\newcounter{upperbit}
+\newcounter{lowerbit}
+\newenvironment{reglist}[1][M]
+  {\begin{list}{}
+    {\settowidth{\labelwidth}{\regDescFamily #1}
+     \addtolength{\labelwidth}{\labelsep}
+     \setlength{\leftmargin}{\labelwidth}
+     \addtolength{\leftmargin}{\labelsep}
+     \addtolength{\leftmargin}{0.5\regDescSkip}
+     \addtolength{\rightmargin}{0.5\regDescSkip}
+     \setlength{\topsep}{0pt}
+     \setlength{\itemsep}{0pt}
+     \setlength{\parsep}{0.5\baselineskip}
+     \renewcommand{\makelabel}[1]{\regDescFamily ##1 \hfill}}}
+  {\end{list}}
+\newenvironment{regdesc}[1][0.90\textwidth]%
+{%
+ \setlength{\regDescSkip}{\textwidth - #1}%
+ \vspace{\regdescsep}%
+\ifthenelse{\boolean{RegisterLyX}}{%
+  \renewenvironment{lyxlist}[1]
+    {\begin{list}{}
+      {\settowidth{\labelwidth}{\regDescFamily ##1}
+       \addtolength{\labelwidth}{\labelsep}
+       \setlength{\leftmargin}{\labelwidth}
+       \addtolength{\leftmargin}{\labelsep}
+       \addtolength{\leftmargin}{0.5\regDescSkip}
+       \addtolength{\rightmargin}{0.5\regDescSkip}
+       \setlength{\topsep}{0pt}
+       %\setlength{\partopsep}{0pt}
+       \renewcommand{\makelabel}[1]{\regDescFamily ####1 \hfill}}}
+    {\end{list}}}{}%
+ % endif
+ % set spacing appropriately
+ \leftskip 0.5\regDescSkip%
+ \rightskip 0.5\regDescSkip%
+ \parfillskip=\z@ plus 1fil%
+ \parskip=0.5\baselineskip \advance\parskip by 0pt plus 2pt%
+}% end begin{regdesc}
+{\vskip\baselineskip}
+\newcommand{\regnewline}{\\*}
+\newenvironment{register}[3]
+{\begin{Regfloat}[#1]%
+  \setlength{\leftskip}{0pt}%
+  \setlength{\oldregdescsep}{\regdescsep}%
+  \setlength{\regdescsep}{0.5\baselineskip}%
+  \setlength{\partopsep}{0pt}%
+  \setlength{\topsep}{0pt}%
+  \setboolean{RegisterContext}{true}%
+  \ifthenelse{\equal{#3}{}}%
+  {\caption[#2]{\textsc{#2}}}% else
+  {\caption[#2]{\textsc{#2} ({#3})}}%
+  \centering}
+{% restore lengths
+  \leftskip\z@%
+  \rightskip\z@%
+  \parfillskip=\z@ plus 1fil%
+  \setlength{\regdescsep}{\oldregdescsep}%
+  \setboolean{RegisterContext}{false}%
+  \end{Regfloat}}
+\def\regUnderScore{_}%
+\def\regFiller#1{\def\regInner{#1}%
+\ifx\regInner\regUnderScore%
+\else%
+\ifnum\count0>0%
+\hfill#1%
+\else#1\fi%
+\fi%
+\advance\count0 by 1%
+}
+\def\regSpread#1{\count0=0{}\regSpreadaux#1\empty}
+\def\regSpreadaux#1#2\empty{\def\aux{#1}%\show#1%
+\ifx\aux\empty%
+\else%
+\def\aux{#2}%
+\regFiller{#1}%
+\ifx\aux\empty%
+\else%
+\regSpreadaux#2\empty%
+\fi\fi}
+\newcommand{\setRegLengths}{%
+  % Compute basic width of a single bit
+  \settowidth{\regFieldLen}{\regLabelSize \regResetName}%
+  \setlength{\regFieldLen}{\regWidth - \regFieldLen}%
+  \setlength{\regFieldLen}{\regFieldLen / \regBitWidth}%
+  % Figure out height and depth of reset field in current font
+  % Is there a more ``official'' method to do this?
+  \settodepth{\regResetDepth}{\regResetSize ()jgpq}%
+  \settoheight{\regResetHeight}{\regResetSize ()ABCjkl}%
+  \addtolength{\regResetHeight}{\regResetDepth}%
+  % Compute how far to drop the reset fields down.  The value at
+  % the end is effectively the separation between the bit position
+  % box and the reset value box.
+  \setlength{\regResetDrop}{\regResetHeight + 2\fboxsep - 2\fboxrule + 3pt}%
+}
+\newcommand{\regMakeFieldName}[1]{%
+  % Create box to hold label
+  \savebox{\Label}{\regLabelSize\regLabelFamily #1}%
+}
+\newcommand{\regRotateFieldName}{%
+  \savebox{\RotatedLabel}{\rotatebox[origin=lB]{45}{\usebox{\Label}}}%
+  \makebox[0pt][l]{\raisebox{\regResetHeight + \fboxsep + \depth + 1pt}%
+        {\hspace{\regLabelAdjust}\usebox{\RotatedLabel}}}%
+}
+\newcommand{\typesetRegBits}[1]{%
+  \ifthenelse{#1 > 1}%
+    {\framebox[\regFieldLen][c]%
+        {\regBitSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}%
+           \regBitFamily\arabic{upperbit} \hfill \arabic{lowerbit}}}%
+    {\framebox[\regFieldLen][c]%
+        {\regBitSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}%
+           \regBitFamily\arabic{lowerbit}}}%
+}
+\newcommand{\typesetRegReset}[1]{%
+ % Typeset reset value in a framebox
+  \makebox[0pt][l]{\raisebox{-1\regResetDrop}{\framebox[\regFieldLen][c]%
+        % Place an invisible rule to control the box
+        % surrounding the reset field
+        {\regResetSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}\regSpread{#1}}}}%
+}
+\newcommand{\regfield}[4]{%
+  % Compute overall field length
+  \setRegLengths%
+  \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}%
+  % Figure out bit positions
+  \setcounter{lowerbit}{#3}%
+  \setcounter{upperbit}{#3 + #2 - 1}%
+  \regMakeFieldName{#1}%
+  % Figure out how far over to place label, accounting for height
+  \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}%
+  % Now, rotate and type the label
+  \regRotateFieldName%
+  \typesetRegReset{#4}%
+  % Typeset bit positions in a framebox
+  \typesetRegBits{#2}%
+  \hspace{-1\fboxrule}%
+}
+\newcommand{\regfieldb}[3]{%
+  % Compute overall field length
+  \setRegLengths%
+  \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}%
+  % Figure out bit positions
+  \setcounter{lowerbit}{#3}%
+  \setcounter{upperbit}{#3 + #2 - 1}%
+  % Create box to hold label
+  \regMakeFieldName{#1}%
+  % Figure out how far over to place label, accounting for height
+  \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}%
+  % Now, rotate and typeset the label
+  \regRotateFieldName%
+  % Typeset bit positions
+  \typesetRegBits{#2}%
+  \hspace{-1\fboxrule}%
+}
+\newcommand{\regbits}[3]{%
+  % Compute overall field length
+  \setRegLengths%
+  \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}%
+  % Figure out bit positions
+  \setcounter{lowerbit}{#3}%
+  \setcounter{upperbit}{#3 + #2 - 1}%
+  % Create box to hold label
+  \regMakeFieldName{#1}%
+  % Figure out how far over to place label, accounting for height
+  \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}%
+  % Now, rotate and typeset the label
+  \regRotateFieldName%
+  % Typeset field value
+  \framebox[\regFieldLen][c]%
+        {\tiny\regSpread{#3}}%
+  \hspace{-1\fboxrule}%
+}
+\newcommand{\regspace}[1]{%
+  % Compute overall field length
+  \setRegLengths%
+  \setlength{\regFieldLen}{#1\regFieldLen + \fboxrule}%
+  \makebox[\regFieldLen]{}%
+}
+
+\newcommand{\reglabel}[1]{%
+  \settowidth{\regFieldLen}{\regLabelSize \regResetName}%
+  \setlength{\regResetDrop}{\regResetDrop + 0.5\fboxsep}%
+  $\,$\raisebox{-1\regResetDrop}{\makebox[\regFieldLen][l]%
+    {\regLabelSize\regBitFamily #1}}%
+}
+
+\newcommand{\reglabelb}[1]{%
+  \settowidth{\regFieldLen}{\regLabelSize \regResetName}%
+  $\,$\raisebox{-0.5\fboxsep}{\makebox[\regFieldLen][l]%
+    {\regLabelSize\regBitFamily #1}}%
+}
+\ifthenelse{\boolean{RegisterHyperref}}{%
+  % Define a counter for the hyperref package.  Otherwise,
+  % the hyperlinks to registers don't work correctly
+  \@namedef{theHRegfloat}{\theRegfloat}
+
+  % Define a bookmark level for Regfloats (for hyperref package)
+  \def\toclevel@Regfloat{0}
+}{}
+\newcommand{\listofregisters}{%
+  \@ifundefined{ext@Regfloat}{\float@error{Regfloat}}{%
+    \@ifundefined{chapter}{\def\@tempa{\section*}}%
+      {\def\@tempa{\chapter*}}%
+    \@tempa{List of Registers\@mkboth{\uppercase{List of Registers}}%
+       {\uppercase{List of Registers}}}%
+    \addcontentsline{toc}{chapter}{List of Registers}%
+    \@starttoc{\@nameuse{ext@Regfloat}}}}
+\newcommand\l@Regfloat{\@dottedtocline{1}{1.5em}{2.3em}}
+\@ifundefined{chapter}{}
+{% Adjust chapter definition slightly for Regfloats
+\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne
+  \if@mainmatter
+    \refstepcounter{chapter}%
+    \typeout{\@chapapp\space\thechapter.}%
+    \addcontentsline{toc}{chapter}%
+    {\protect\numberline{\thechapter}#1}%
+  \else
+    \addcontentsline{toc}{chapter}{#1}%
+  \fi
+  \else
+    \addcontentsline{toc}{chapter}{#1}%
+  \fi
+  \chaptermark{#1}%
+    \addtocontents{lof}{\protect\addvspace{10\p@}}%
+    \addtocontents{lot}{\protect\addvspace{10\p@}}%
+    \addtocontents{rdf}{\protect\addvspace{10\p@}}% --- Add space ---
+  \if@twocolumn
+    \@topnewpage[\@makechapterhead{#2}]%
+  \else
+    \@makechapterhead{#2}%
+    \@afterheading
+  \fi}
+}
+\newcommand\@GetTRSecondParam{}
+\long\def\@GetTRSecondParam#1#2#3\@nil{#2}
+\newcommand*{\GetTRPageRef}[1]{%
+  \expandafter\expandafter\expandafter\@GetTRSecondParam
+    \csname r@#1\endcsname
+    0% dummy, if the reference is undefined
+    \@nil
+}
+
+\newcommand{\TRfamily}{\sffamily}
+\newcounter{T@peReleaseTag}
+\newlength{\TRwidth}
+\setlength{\TRwidth}{\marginparwidth}
+\newlength{\T@peReleaseDepth}
+
+\newcommand{\TRwriteout}[1]{%
+  \makebox[\TRwidth][c]{%
+    \raisebox{\T@peReleaseDepth}{%
+     \ifthenelse{\boolean{RegisterTRBoxed}}%
+       {\fbox{\TRfamily #1}}%
+       {\TRfamily #1}}}%
+}
+
+\newcommand{\TRrightlabel}[1]{%
+  % Place a strut in order to set line depth
+  \mbox{}\strut\settodepth{\T@peReleaseDepth}{\strut}%
+   \vadjust{\hspace{\textwidth}\hspace{\marginparsep}%
+   \smash{\rlap{\TRwriteout{#1}}}}}
+
+\ifthenelse{\boolean{@twoside}}{
+  % Two-sided document
+  \newcommand{\TRleftlabel}[1]{%
+    % Place a strut in order to set line depth
+    \mbox{}\strut\settodepth{\T@peReleaseDepth}{\strut}%
+    \vadjust{\smash{\llap{\TRwriteout{#1}}\kern\marginparsep}}}
+}{
+  % Otherwise, the command is the same as rightlabel
+  \newcommand{\TRleftlabel}[1]{%
+    \TRrightlabel{#1}}
+}
+\ifthenelse{\boolean{RegisterTRFlags}}{
+\newcommand{\TR}[1]{%
+  \stepcounter{T@peReleaseTag}%
+  \label{TapeReleaseTag-\theT@peReleaseTag}%
+  \ifthenelse{\isodd{\GetTRPageRef{TapeReleaseTag-\theT@peReleaseTag}}}%
+   {\TRrightlabel{TR\hspace{1pt}#1}}%
+   {\TRleftlabel{TR\hspace{1pt}#1}}%
+}}
+{\newcommand{\TR}[1]{}}
+\endinput
+%%
+%% End of file `register.sty'.
diff --git a/doc/toolchain.tex b/doc/toolchain.tex
new file mode 100644 (file)
index 0000000..3a6e3dc
--- /dev/null
@@ -0,0 +1,420 @@
+\documentclass[10pt,oneside]{article}
+\reversemarginpar 
+\usepackage[titles]{tocloft}
+\usepackage{palatino}
+\usepackage{wrapfig}
+\usepackage{epsfig}
+\usepackage{verbatim}
+\usepackage{parskip}
+\usepackage{register}
+\usepackage{bytefield}
+\usepackage[colorlinks=true, pdfstartview=FitV, linkcolor=blue, citecolor=blue, urlcolor=blue]{hyperref}
+\renewcommand{\ttdefault}{cmtt}
+\title{The FleetTwo Toolchain Manual\\{\normalsize A Compiler Writer's View of FleetTwo}}
+\author{Adam Megacz}
+\begin{document}
+\maketitle
+
+\begin{thebibliography}{[GDG01]}
+\bibitem[ArchMan]{ArchMan}
+  {\it The FleetTwo Architecture Manual}
+\bibitem[Meg06]{SBP}
+  Megacz, Adam, {\it Scannerless Boolean Parsing}. Electronic Notes in
+  Theoretical Computer Science 1368, (Volume 164, Issue 2):
+  Proceedings of the Sixth Workshop on Language Descriptions, Tools,
+  and Applications (LDTA 2006)
+\end{thebibliography}
+
+
+\vspace{3cm}
+\begin{abstract}
+Fleet compilers and tools work primarily with three entities: Ships,
+Instructions, and Test Cases.  In order to promote greater
+interoperability, the FleetTwo Toolchain defines both a Java API and a
+text file format for each of these.
+\end{abstract}
+
+\vfill
+\fbox{\parbox{5in}{\footnotesize
+\begin{center}
+The software described in this memo may be obtained using
+\href{http://www.darcs.net/}{\tt darcs}, with the command:
+
+{\tt darcs get http://research.cs.berkeley.edu/class/fleet/repos/fleet/}
+\end{center}
+}}
+
+\pagebreak
+\tableofcontents
+
+\pagebreak
+\section{Introduction}
+
+Fleet compilers and tools work primarily with three entities: Ships,
+Instructions, and Test Cases.  In order to promote greater
+interoperability, the FleetTwo Toolchain defines both a Java API and a
+textual file format for each of these.
+
+In the case of ships, this takes the form of the {\tt .ship} file
+format for describing ships and the {\tt ShipDescription} Java class
+which an implementation of Fleet uses to inform the toolchain of what
+ships it contains and how they may be used.  The toolchain includes a
+library for parsing the textual file format into the Java
+representation.
+
+In the case of instructions, and more generally programs, this takes
+the form of the {\tt .fleet} assembly language file format for
+representing Fleet programs and the {\tt Instruction} and {\tt
+  CodeBag} Java classes for representing programs and manipulating
+them.  A library is provided for parsing Fleet assembly language
+programs into {\tt CodeBag}s of {\tt Instruction}s, and for writing
+those objects back out as text.
+
+In the case of Test Cases, the FleetTwo Toolchain defines a very
+simple debugging interface, {\tt Device}, which lets a program
+dispatch a codebag to a running Fleet implementation or emulator and
+read back the words which arrive at its {\tt Debug} port.  A test
+harness has been written which makes no assumptions about the device
+under test other than that it supports this debugging interface and
+that it is capable of describing itself via the {\tt ShipDescription}
+API.  By meeting these relatively modest requirements, a new Fleet
+implementation can immediately take advantage of a great deal of
+prebuilt testing infrastructure.  This API has been implemented and is
+fully functional for both the software interpreter implementation of
+Fleet and the FPGA simulation of Fleet.
+
+
+\pagebreak
+\section{Ships}
+\subsection{Ship Description Files (FleetDoc)}
+
+Inspired by JavaDoc, the Fleet software toolchain includes a tool
+called {\tt FleetDoc}, which processes {\it ship description files}
+with the extension {\tt .ship}.  These files contain sections for:
+
+\begin{itemize}
+\item The name of the ship
+\item A list of its ports
+\item A prose description of the ship
+\item A list of the constants associated with a ship
+\item Java source code for a software simulation of the ship
+\item Verilog source code for an FPGA simulation of the ship
+\item A test case for the ship
+\item A list of the people who contributed to all of the above
+\end{itemize}
+
+Keeping all of this information in a single file ensures that changes
+to one item -- such as the list of ports -- are propagated to the
+other items -- such as the verilog code for simulation purposes.
+
+Keeping this information in {\it machine-readable} format makes it
+possible to automatically generate tools which depend on the precise
+details of ship ports without the risk
+inherent in manual synchronization.
+
+The latter half of the architecture manual \cite{ArchMan} -- including
+the ship diagrams -- is generated automatically from the contents of
+the {\tt .ship} files.
+
+\pagebreak
+\subsubsection{An Example FleetDoc File}
+\begin{verbatim}
+ship: BitFifo
+
+== Ports ===========================================================
+in:   in
+in:   inOp
+  constant lsbFirst: ....................................1
+  constant msbFirst: ....................................0
+  constant drop:     .............................uuuuuu..
+  constant take:     .......................uuuuuu........
+...
+  
+== TeX ==============================================================
+The BitFifo internally stores some number of bits in a fifo structure.
+Its capacity is guaranteed to be at least two full machine words or
+more.
+...
+
+== Fleeterpreter ====================================================
+public void service() {
+  if (box_inOp.dataReadyForShip() && box_in.dataReadyForShip()) {
+  ...
+
+== FPGA ==============================================================
+always @(posedge clk) begin
+  if (!in_r    && in_a)     in_a    <= 0;
+  if (!inOp_r  && inOp_a)   inOp_a  <= 0;
+  ...
+
+== Test ==============================================================
+#expect 1
+#expect 68719476736
+#ship debug        : Debug
+#ship bitfifo      : BitFifo
+
+bitfifo.outOp:      literal BitFifo.outOp[take=37]; [*] deliver;
+...
+
+== Contributors =========================================================
+Amir Kamil <kamil@cs.berkeley.edu>
+Adam Megacz <megacz@cs.berkeley.edu>
+\end{verbatim}
+
+
+\pagebreak
+\subsection{Java API for Ship Descriptions}
+
+The FleetTwo toolchain includes a utility for parsing a {\tt .ship}
+file into a {\tt ShipDescription}.  There is one {\tt ShipDescription}
+for each {\it kind} of ship.  This distinction will become important
+later, when we introduce classes to represent {\it instances} of ship
+types.
+
+\begin{verbatim}
+/** a description of a ship */
+public class ShipDescription implements Iterable<DockDescription> {
+  public String                        getName();
+  public Iterable<ConstantDescription> getConstantDescriptions();
+  public Iterable<DockDescription>    getDockDescriptions();
+}
+
+/** a description of a valve */
+public class DockDescription {
+  public String           getName();
+  public boolean          isInbox();
+  public boolean          isOutbox();
+  public DockDescription getShortcut();
+}
+
+/** a constant declared by a ship */
+public class ConstantDescription {
+  public final long setbits;
+  public final long clearbits;
+  public final boolean signExtend;
+  public final int numberOffset;
+  public final int numberWidth;
+}
+\end{verbatim}
+
+
+\pagebreak
+\section{Instructions}
+\subsection{Fleet Assembly Language}
+
+The Fleet Assembly language is designed to be a human-readable
+depiction of the bits which comprise a Fleet program.
+
+\subsubsection{Formal Grammar}
+
+The formal syntax is given below.  The metagrammar used is that of the
+Scannerless Boolean Parser \cite{sbp}.
+
+\verbatiminput{fleet.g}
+
+\subsubsection{Translation To Machine Code}
+
+Please refer to \cite{ArchMan} for the details of the Fleet
+instruction encoding.
+
+As shown in the grammar above, the start symbol for the grammar ({\tt
+  s}) yields a {\tt Program} surrounded by optional whitespace.  A
+program is a sequence of {\tt Directive}s followed by a {\tt
+  CodeBagBody}.  A {\tt CodeBagBody} consists of zero or more
+elements, each of which is either a {\tt Fiber} or a (nested) {\tt
+  CodeBagDef}.
+
+A {\tt Fiber} is a set of {\tt Instruction}s which all share a common
+execution point ({\tt Pump}).  Each instruction can be {\tt unclog},
+{\tt clog}, {\tt kill}, {\tt literal}, or a set of {\tt Command}s.  It
+should be fairly clear how to translate all but the last sort of
+instruction into machine code, based on the encodings in
+\cite{ArchMan}.  Take particular note of the fact that {\tt literal}s
+may have a {\tt RequeueCount} but not a {\tt RepeatCount}.
+
+The repetition count for an instruction is placed in square brackets
+and prefixes the instruction.  The requeueing count for an instruction
+is placed at the end of the instruction because, {\it conceptually},
+requeueing takes place after the instruction executes.
+
+A {\tt Command} is either {\tt wait}, {\tt nop}, {\tt discard}, {\tt
+  recieve}, {\tt take}, {\tt deliver}, {\tt send}, {\tt sendto}, {\tt
+  notify}, or {\tt notifyLast}.  These are compiled as shown below:
+
+\begin{itemize}
+\item[\tt nop] is not valid in combination with any other command; it sets all control bits to {\tt 0}
+\item[\tt wait] is valid only on an output port, and sets {\tt Ti=1}
+\item[\tt discard] sets {\tt Di=1,Dc=0}
+\item[\tt recieve] is valid only on an input port, and sets {\tt Di=1,Dc=1}
+\item[\tt take] is valid only on an output port, and sets {\tt Di=1,Dc=1}
+\item[\tt deliver] is valid only on an input port, and sets {\tt Do=1}
+\item[\tt sendto] is valid only on an output port, and sets {\tt Do=1}
+\item[\tt send] is valid only on an output port, and sets {\tt Do=1,To=1}\footnote{see \cite{ArchMan} for the special meaning this bit combination has}
+\item[\tt notify] sets {\tt To=1} and is not valid in combination with {\tt send} or {\tt sendto}
+\item[\tt notifyLast] sets {\tt To=1,Ig=1} and is not valid in combination with {\tt send} or {\tt sendto}
+\end{itemize}
+
+It is an error to specify two commands within a single instruction if
+both of the commands attempt to set the same bit, even if they attempt
+to set it to the same value.
+
+Note that un-named ``anonymous'' codebags may appear as literals.
+This means that it is possible to write interesting programs such as
+the one below:
+
+\begin{verbatim}
+#ship debug  : Debug
+#ship memory : Memory
+
+memory.inCBD: literal {
+    memory.inCBD: literal {
+        memory.inCBD: literal {
+            debug.in:
+              literal 3;
+              deliver;
+          }; deliver;
+      }; deliver;
+  }; deliver;
+\end{verbatim}
+
+
+
+
+\pagebreak
+\subsection{Java API for Fleet Machine Code}
+
+\subsection{Ships}
+\begin{verbatim}
+public abstract class Ship {
+
+    /** return the description for this ship */
+    public ShipDescription getShipDescription();
+
+    /** return all pumps which feed this ship; order is NOT significant */
+    public Iterable<Dock> getDocks();
+    public Dock getDock(String s);
+
+    /** if this is the 4th fifo ship, this method returns 4 */
+    public int getOrdinal();
+
+    /** return the Fleet that this Ship belongs to, if any */
+    public Device  getDevice();
+}
+\end{verbatim}
+
+\subsection{Dock}
+\begin{verbatim}
+public class Dock {
+
+    /** the descriptive name of this pump (relative to its ship) */
+    public abstract String getName();
+
+    /** return the Ship to which this Dock belongs */
+    public abstract Ship   getShip();
+
+    /** the maximum number of instructions we can put in the Dock instruction fifo,
+     *  or Integer.MAX_VALUE if unbounded */
+    public abstract int getInstructionFifoLength();
+
+    /** returns true if this is an inbox */
+    public abstract boolean isInbox();
+
+    /** returns true if this is an outbox */
+    public abstract boolean isOutbox();
+
+    /** return the Dock which is the destination of this Box's shortcut (if any) */
+    public Destination getShortcut() { return null; }
+}            
+\end{verbatim}
+
+\subsection{Instructions}
+\begin{verbatim}
+public abstract class Instruction {
+    public final Pump pump;
+
+    public static class UnClog extends Instruction {
+    }
+
+    public static class Clog extends Instruction {
+    }
+
+    public static abstract class CountingInstruction extends Instruction {
+        public final int count;
+        public CountingInstruction decrementCount();
+    }
+
+    public static class Kill extends CountingInstruction {
+    }
+
+    public static class Executable extends CountingInstruction {
+
+        public final Destination dest;
+
+        public final boolean     tokenIn;
+        public final boolean     dataIn;
+        public final boolean     latch;
+        public final boolean     send;
+        public final boolean     sendTo;
+        public final boolean     tokenOut;
+        public final boolean     requeue;
+        public final boolean     ignoreUntilLast;
+
+        public boolean isStanding();
+    }
+
+    public static class Literal extends CountingInstruction {
+        public final long literal;
+    }
+}
+\end{verbatim}
+
+\pagebreak
+\section{Test Cases}
+
+\subsection{Test Case File Format}
+
+The test case file format is quite simple -- it is nothing more than a
+regular Fleet assembly language program with {\tt \#expect} statements
+to indicate the values which should arrive at the {\tt Debug.in} port
+if the test runs correctly.
+
+\subsection{Java API for Controlling Device Under Test}
+
+\subsection{The Device}
+\begin{verbatim}
+public abstract class Device implements Iterable<Ship> {
+
+    /** read a machine-formatted instruction from a file (into a Java object) */
+    public abstract Instruction
+       readInstruction(DataInputStream is) throws IOException;
+
+    /** write a machine-formatted instruction to a file (from a Java object) */
+    public abstract void 
+       writeInstruction(DataOutputStream os, Instruction instr) throws IOException;
+
+    public abstract Iterator<Ship> iterator();
+
+    /** if possible, run the given code and create a FleetProcess */
+    public FleetProcess run(byte[] code);
+}
+\end{verbatim}
+
+\subsection{A Running Test}
+
+\begin{verbatim}
+/** represents a <i>running</i> "slave" fleet with a debug connection */
+public abstract class FleetProcess {
+
+    /** dumps an instruction into the fetch unit */
+    public abstract void invokeInstruction(Instruction i);
+
+    /** reads a word back from the debug port */
+    public abstract long readWord();
+
+    public final synchronized void terminate();
+
+    public final boolean isTerminated();
+}
+\end{verbatim}
+
+\end{document}
diff --git a/lib/HSbase.jar b/lib/HSbase.jar
new file mode 100644 (file)
index 0000000..9bf683e
Binary files /dev/null and b/lib/HSbase.jar differ
diff --git a/lib/HSrts.jar b/lib/HSrts.jar
new file mode 100644 (file)
index 0000000..29cd392
Binary files /dev/null and b/lib/HSrts.jar differ
diff --git a/lib/HSstm.jar b/lib/HSstm.jar
new file mode 100644 (file)
index 0000000..6c86870
Binary files /dev/null and b/lib/HSstm.jar differ
diff --git a/lib/RXTXcomm.jar b/lib/RXTXcomm.jar
new file mode 100644 (file)
index 0000000..4159f21
Binary files /dev/null and b/lib/RXTXcomm.jar differ
diff --git a/lib/SBP.lhs b/lib/SBP.lhs
new file mode 100644 (file)
index 0000000..bab70a6
--- /dev/null
@@ -0,0 +1,149 @@
+\begin{code}
+--
+-- These bindings are highly experimental and subject to change
+-- without notice.  You've been warned.
+--
+module SBP(Tree(Tree),Location(Location),Region(Region),parseFile,prettyPrintTree,coalesceFlatHeadlessNodes)
+where
+
+#if defined(java_HOST_OS)
+import Foreign
+import Foreign.Java
+import Text.PrettyPrint.HughesPJ
+#define CONCAT(x,y) x/**/y
+#define DEFINE_OBJECT(s,name) \
+data CONCAT(name,_); \
+type name = Object CONCAT(name,_); \
+foreign import jvm s CONCAT(_,name) :: JClass; \
+instance JType_ CONCAT(name,_) where jClass_ _ = CONCAT(_,name);
+#else
+import Header_Java;
+import Class_edu_berkeley_sbp_misc_HaskellHelper;
+import Class_java_lang_Object;
+import Class_java_lang_Class;
+import Class_java_lang_String;
+import Class_edu_berkeley_sbp_Tree;
+import Header_edu_berkeley_sbp_Tree;
+import JVM_edu_berkeley_sbp_misc_HaskellHelper;
+import Header_edu_berkeley_sbp_misc_HaskellHelper;
+import TypedString;
+import JVMBridge;
+import JavaText;
+import JavaTypes;
+import Data.Int;
+import Invocation;
+import Text.PrettyPrint.HughesPJ
+#endif
+
+data Location = Location Int Int
+data Region   = Region Location Location
+
+data Tree     = Tree String [Tree] Region
+instance Show Tree
+ where
+  show t@(Tree _ _ _) = show $ prettyPrintTree $ t
+
+coalesceFlatHeadlessNodes t@(Tree s children r)
+  | s==[], flat t = Tree (concat $ map (\(Tree s _ _) -> s) children) [] r
+  | otherwise     = Tree s (map coalesceFlatHeadlessNodes children) r
+ where
+  flat (Tree _ children _) = not (any id $ map notFlatComponent children)
+  notFlatComponent (Tree _ [] _) = False
+  notFlatComponent (Tree _ _  _) = True
+
+prettyPrintTree (Tree "" []       _) = empty
+prettyPrintTree (Tree s  []       _) = text s
+prettyPrintTree (Tree [] children _) = prettyPrintTreeList children
+prettyPrintTree (Tree s  children _) = (text (s++":")) <+> (nest 4 $ prettyPrintTreeList children)
+prettyPrintTreeList []               = text "{}"
+prettyPrintTreeList children         = (text "{") <+> ((fsep $ map prettyPrintTree children) <+> (text "}"))
+
+nullRegion = (Region (Location 0 0) (Location 0 0))
+
+
+
+------------------------------------------------------------------------------
+#if defined(java_HOST_OS)
+foreign import jvm type "edu.berkeley.sbp.Tree" JTree#
+data JTree = JTree JTree#
+foreign import jvm safe "edu.berkeley.sbp.misc.RegressionTests.main" regressionTests :: IO ()
+foreign import jvm safe "edu.berkeley.sbp.misc.HaskellHelper.help0" haskellHelper :: JString -> JString -> IO JTree
+foreign import jvm safe "edu.berkeley.sbp.misc.HaskellHelper.isNull" isNull :: (Object a) -> IO Bool
+foreign import jvm safe "getHead" getHead :: JTree -> IO (Object a)
+foreign import jvm safe "child" getChild :: JTree -> Int32 -> IO JTree
+foreign import jvm safe "size" size :: JTree -> IO Int32
+foreign import jvm safe "toString" jtoString :: (Object a) -> IO JString
+
+toString o  = do isn <- isNull o
+                 if isn then return ""
+                        else do str <- jtoString o
+                                return (unpackJString str)
+
+         
+haskify :: JTree -> IO Tree
+haskify t =
+  do head <- getHead t
+     str  <- toString head
+     numChildren <- size t
+     children    <- if numChildren == 0
+                        then do return []
+                        else do children <- mapM (\i -> getChild t i)
+                                              $ take (fromIntegral numChildren)
+                                                $ iterate (+1) 0
+                                h        <- mapM haskify children
+                                return h
+     return $ Tree str children nullRegion
+
+parseFile ::
+ String   ->   -- grammar *.g file
+ String   ->   -- file to be parsed
+ IO Tree
+
+parseFile g f = do g' <- packJString g
+                   f' <- packJString f
+                   tree <- haskellHelper g' f'
+                   x <- haskify tree
+                   return x
+
+------------------------------------------------------------------------------
+#else
+  -- Why do I need this?
+  instance SubJavaClassMarker
+      Header_edu_berkeley_sbp_Tree.Class_Jedu_berkeley_sbp_Tree
+      Header_edu_berkeley_sbp_misc_HaskellHelper.Class_Jedu_berkeley_sbp_Tree
+
+  parseFile ::
+   [String] ->   -- class path
+   String   ->   -- grammar *.g file
+   String   ->   -- file to be parsed
+   IO Tree
+
+  parseFile classPath grammarFile inputFile =
+     runJVM classPath
+        ((do class_JHaskellHelper
+             s1   <- new_JString_ArrayJchar $ toJavaString grammarFile
+             s2   <- new_JString_ArrayJchar $ toJavaString inputFile
+             tree <- main_JHaskellHelper_JString_JString (s1, s2)
+             t <- haskifyTree tree
+             return t
+          ) :: JVM Tree)
+
+  haskifyTree t = 
+    ((do class_JHaskellHelper
+         class_JTree
+         head <- getHead_JTree t ()
+         isNull <- getIsNothing head
+         str  <- if isNull then (return "") else (toString_JObject ((castTLRef head) :: Jjava_lang_Object) () >>= getStringUTF >>= \x -> return (showUTF8 x))
+         numChildren <- size_JTree t()
+         children    <- if numChildren == 0
+                        then do return []
+                        else do children <- mapM (\i -> child_JTree_Jint t ((fromIntegral i)::Int32))
+                                              $ take (fromIntegral numChildren)
+                                                $ iterate (+1) 0
+                                h        <- mapM (\c -> haskifyTree (castTLRef c)) children
+                                return h
+         return $ Tree str children nullRegion
+      ) :: JVM Tree)
+
+#endif
+\end{code}
diff --git a/lib/edu.berkeley.sbp.jar b/lib/edu.berkeley.sbp.jar
new file mode 100644 (file)
index 0000000..8a9266b
Binary files /dev/null and b/lib/edu.berkeley.sbp.jar differ
diff --git a/lib/ibex.jar b/lib/ibex.jar
new file mode 100644 (file)
index 0000000..27cad7a
Binary files /dev/null and b/lib/ibex.jar differ
diff --git a/lib/librxtxSerial.jnilib b/lib/librxtxSerial.jnilib
new file mode 100644 (file)
index 0000000..7989a3b
Binary files /dev/null and b/lib/librxtxSerial.jnilib differ
diff --git a/marina/blockDiagram.pdf b/marina/blockDiagram.pdf
new file mode 100755 (executable)
index 0000000..0cb7acc
Binary files /dev/null and b/marina/blockDiagram.pdf differ
similarity index 100%
rename from lib/test.jar
rename to marina/lib/test.jar
diff --git a/marina/logo/cal.logo.png b/marina/logo/cal.logo.png
new file mode 100644 (file)
index 0000000..2b2ab81
Binary files /dev/null and b/marina/logo/cal.logo.png differ
diff --git a/marina/logo/marina-logo.png b/marina/logo/marina-logo.png
new file mode 100644 (file)
index 0000000..ded807f
Binary files /dev/null and b/marina/logo/marina-logo.png differ
diff --git a/marina/logo/marina-logo.svg b/marina/logo/marina-logo.svg
new file mode 100644 (file)
index 0000000..ade6e1b
--- /dev/null
@@ -0,0 +1,1060 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="544.11865"
+   height="543.87665"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45+devel"
+   version="1.0"
+   sodipodi:docname="marina-logo.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/Users/megacz/Desktop/marina-logo.png"
+   inkscape:export-xdpi="86.18"
+   inkscape:export-ydpi="86.18"
+   style="enable-background:new">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-50 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       id="perspective227" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-50 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       id="perspective226" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-50 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       id="perspective225" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-50 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       id="perspective201" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-257.73906 : -309.95255 : 0"
+       inkscape:vp_y="-87.155744 : 996.19471 : 0"
+       inkscape:vp_z="446.6007 : -23.405351 : 0"
+       inkscape:persp3d-origin="317.07944 : 492.14954 : 1"
+       id="perspective10" />
+    <inkscape:perspective
+       id="perspective2453"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3739"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3857"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3907"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3994"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2661"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2728"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <clipPath
+       id="clipPath2995"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path2997"
+         d="M 0,0 L 612,0 L 612,792 L 0,792 L 0,0 z" />
+    </clipPath>
+    <clipPath
+       id="clipPath2985"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path2987"
+         d="M 257.8686,187.257 L 287.5848,187.257 L 287.5848,217.4102 L 257.8686,217.4102 L 257.8686,187.257 z" />
+    </clipPath>
+    <inkscape:perspective
+       id="perspective2981"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <clipPath
+       id="clipPath3219"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path3221"
+         d="M 0,0 L 612,0 L 612,792 L 0,792 L 0,0 z" />
+    </clipPath>
+    <clipPath
+       id="clipPath3209"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path3211"
+         d="M 257.8686,187.257 L 287.5848,187.257 L 287.5848,217.4102 L 257.8686,217.4102 L 257.8686,187.257 z" />
+    </clipPath>
+    <inkscape:perspective
+       id="perspective3205"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <clipPath
+       id="clipPath3444"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path3446"
+         d="M 0,0 L 612,0 L 612,792 L 0,792 L 0,0 z" />
+    </clipPath>
+    <clipPath
+       id="clipPath3434"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         id="path3436"
+         d="M 257.8686,187.257 L 287.5848,187.257 L 287.5848,217.4102 L 257.8686,217.4102 L 257.8686,187.257 z" />
+    </clipPath>
+    <inkscape:perspective
+       id="perspective3430"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3956"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective4024"
+       inkscape:persp3d-origin="300 : 400 : 1"
+       inkscape:vp_z="700 : 600 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="-50 : 600 : 1"
+       sodipodi:type="inkscape:persp3d" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.9757343"
+     inkscape:cx="244.92509"
+     inkscape:cy="369.28065"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer4"
+     showgrid="false"
+     inkscape:window-width="1803"
+     inkscape:window-height="1148"
+     inkscape:window-x="2"
+     inkscape:window-y="6" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="back"
+     transform="translate(7.0945042,31.268307)">
+    <rect
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.12810874;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:3.12810891, 3.12810891;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect4681"
+       width="540.99054"
+       height="540.74854"
+       x="-5.5304499"
+       y="-29.704252"
+       rx="5.7142859"
+       ry="8.3458519"
+       inkscape:export-filename="/Users/megacz/Desktop/marina-logo.png"
+       inkscape:export-xdpi="86.379883"
+       inkscape:export-ydpi="86.379883" />
+  </g>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     style="opacity:0.43154764;display:none"
+     sodipodi:insensitive="true"
+     transform="translate(-160.94615,-182.49797)">
+    <image
+       y="256.96979"
+       x="138.57358"
+       id="image2455"
+       height="447.44907"
+       width="792.32086"
+       sodipodi:absref="/Users/megacz/Desktop/Southwold-Pier-and-Wave3.jpg"
+       xlink:href="Desktop/Southwold-Pier-and-Wave3.jpg" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="la"
+     style="display:inline"
+     transform="translate(-160.94615,-182.49797)">
+    <path
+       style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 174.13331,540.87358 L 227.49674,540.31186 L 236.48426,521.77509 L 227.49674,521.21337 L 227.49674,503.80004 L 239.85459,503.80004 L 261.19996,464.47962 L 261.76168,440.32564 L 249.40383,434.70844 L 254.45931,368.98716 L 311.19307,372.35748 L 339.84081,320.67921 L 696.53322,329.66674 L 695.9715,705.45764 L 174.13331,706.01936 L 174.13331,540.87358 z"
+       id="path3914"
+       sodipodi:nodetypes="cccccccccccccccc" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 589.24464,458.86241 L 588.1212,569.52132 L 664.51516,566.151 L 664.51516,437.51704 L 652.15732,442.0108 L 651.59559,458.86241 L 645.41667,463.35618 L 589.24464,458.86241 z"
+       id="path3916" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 557.7883,474.59058 L 556.66486,572.89164 L 572.39303,570.64476 L 572.95475,476.27575 L 557.7883,474.59058 z"
+       id="path3918" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 521.8382,487.51015 L 520.71476,575.70025 L 530.264,575.13852 L 530.264,486.38671 L 521.8382,487.51015 z"
+       id="path3920" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 478.58573,493.68908 L 478.02401,579.63229 L 507.23347,577.38541 L 507.23347,486.38671 L 492.06702,485.82499 L 492.06702,493.12736 L 489.25842,495.37424 L 478.58573,493.68908 z"
+       id="path3922" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 422.4137,508.2938 L 422.4137,588.05809 L 437.58015,586.37294 L 437.58015,507.73208 L 422.4137,508.2938 z"
+       id="path3924"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 447.69111,502.6766 L 447.12939,585.24949 L 455.5552,582.44089 L 456.11692,503.23832 L 447.69111,502.6766 z"
+       id="path3926" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 397.13628,512.22585 L 397.13628,602.1011 L 400.5066,602.1011 L 400.5066,509.41725 L 397.13628,512.22585 z"
+       id="path3928" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 391.51908,518.40477 L 390.39564,593.6753 L 383.09327,593.67529 L 382.53155,520.08993 L 391.51908,518.40477 z"
+       id="path3930"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 357.81586,524.02197 L 357.81586,593.11357 L 363.99478,591.99013 L 363.99478,525.14541 L 357.81586,524.02197 z"
+       id="path3932"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 338.71737,526.26886 L 343.21113,524.02197 L 344.89629,600.41594 L 339.27909,600.97766 L 338.71737,526.26886 z"
+       id="path3934" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer6"
+     inkscape:label="logos"
+     style="display:inline"
+     transform="translate(7.0945042,31.268307)">
+    <image
+       style="display:inline"
+       y="438.41339"
+       x="8.538662"
+       id="image3958"
+       height="52.447952"
+       width="51.757847"
+       sodipodi:absref="/Users/megacz/Desktop/chip logo/sun.logo.png"
+       xlink:href="sun.logo.png" />
+    <image
+       y="440.5524"
+       x="65.840584"
+       id="image4026"
+       height="47.157715"
+       width="59.243362"
+       sodipodi:absref="/Users/megacz/Desktop/chip logo/cal.logo.png"
+       xlink:href="cal.logo.png" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="above"
+     style="display:inline"
+     transform="translate(-160.94615,-182.49797)">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 414.22002,357.05591 L 414.22002,326.70424 L 399.04418,343.66546 L 399.04418,369.55365 L 414.22002,357.05591 z"
+       id="path2464" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 413.32732,357.05591 L 697.20469,386.51488"
+       id="path2466" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 413.83178,326.40187 L 695.84112,359.76636"
+       id="path2468" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 398.82833,370.12438 L 695.97839,400.70416"
+       id="path2472"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 173.57847,549.31317 L 240.4232,549.31317 L 240.4232,577.39919"
+       id="path2478" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 183.12772,549.87488 L 183.12772,575.71402"
+       id="path2482" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 178.07224,549.87489 L 178.07224,575.71403"
+       id="path2484" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 207.56255,549.87488 L 207.56255,575.71402"
+       id="path2486" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 202.50707,549.87489 L 202.50707,575.71403"
+       id="path2488" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 230.59309,549.87489 L 230.59309,575.71403"
+       id="path2490" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 225.53761,549.8749 L 225.53761,575.71404"
+       id="path2492" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 352.20554,401.019 L 352.20554,417.30889 L 361.75479,406.6362 L 361.75479,388.66115"
+       id="path2494" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 361.75479,406.6362 L 529.70917,417.87061 L 530.27089,397.08696 L 365.12511,384.16739"
+       id="path2496" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 351.64382,418.43233 L 529.14745,426.85813"
+       id="path2498" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 530.27089,383.60567 L 530.27089,661.65724"
+       id="path2500" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 556.67175,386.41427 L 556.67175,662.78068"
+       id="path2502" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 557.23347,398.2104 L 695.41667,410.00652"
+       id="path2504" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 556.67175,418.99405 L 696.54011,428.5433"
+       id="path2508" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 695.97839,437.53082 L 556.67175,427.41985"
+       id="path2510" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 321.87264,429.55867 L 321.87264,449.32695 L 329.73673,442.5863 L 328.54514,426.06374 L 456.12381,431.58457 L 456.12381,641.99702"
+       id="path2514"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 478.31176,424.33039 L 478.31176,642.83961"
+       id="path2517" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 507.24036,471.5149 L 507.24036,631.6052"
+       id="path2519" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 520.72165,472.07662 L 520.72165,631.88606"
+       id="path2521" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 572.39992,474.88522 L 572.39992,631.88606"
+       id="path2525" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 587.00465,631.6052 L 588.40895,458.59533 L 643.7384,462.80824 L 651.60248,459.99963 L 651.32162,442.02458 L 664.24119,437.81168 L 664.24119,638.90756"
+       id="path2527" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 686.14829,634.69466 L 686.14829,437.24996"
+       id="path2529" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 507.24036,471.79576 L 478.0309,470.67232"
+       id="path2531" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 520.72165,472.9192 L 530.27089,473.20006"
+       id="path2533" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 572.11906,475.44694 L 556.67175,474.04264"
+       id="path2535" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 521.28337,486.40049 L 529.99003,486.40049"
+       id="path2537" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 651.04076,442.30544 L 556.67175,435.00308"
+       id="path2539" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 651.88334,459.71877 L 556.39089,451.85469"
+       id="path2541" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 530.27089,434.90671 L 478.31176,432.65983"
+       id="path2543"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 530.55175,450.16953 L 478.31176,447.36093"
+       id="path2545" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 330.01759,442.5863 L 455.84295,446.79921"
+       id="path2547" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 321.87264,449.60781 L 456.12381,453.82071"
+       id="path2549" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 478.59262,454.10157 L 530.27089,455.78673"
+       id="path2551" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 556.95261,456.91017 L 588.12809,459.15705"
+       id="path2553" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 302.77415,451.34942 L 303.05501,467.86372 L 308.95308,461.40394 L 309.35028,446.92381"
+       id="path2555"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 302.21243,467.58286 L 399.95177,470.95318"
+       id="path2557" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 400.23263,452.41641 L 400.23263,627.11144"
+       id="path2559" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.80338,452.69727 L 416.80338,626.83058"
+       id="path2561" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 309.23394,461.40394 L 399.95177,464.77426"
+       id="path2563" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 309.23394,450.73125 L 400.51349,454.10157"
+       id="path2565" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 417.08424,455.78673 L 455.84295,456.62931"
+       id="path2567" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.52252,465.8977 L 456.40467,466.17856"
+       id="path2569" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.52252,472.63834 L 456.12381,471.5149"
+       id="path2571" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 478.31176,465.8977 L 530.27089,467.02114"
+       id="path2573" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 556.67175,468.7063 L 583.91518,470.95318 L 572.68078,475.44694"
+       id="path2575" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 225.56075,541.28505 L 399.53271,322.42991"
+       id="path2579" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 254.15888,369.69626 L 305.79439,372.47664 L 285.93458,410.60748 L 259.32243,409.41589 L 255.35047,369.69626 L 250.98131,436.02804 L 258.13084,435.23364 L 264.88318,412.59346 L 285.93458,413.78505 L 285.93458,410.21028"
+       id="path2581" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 261.70561,430.07009 L 261.70561,463.83178 L 263.69159,459.06542 L 263.69159,415.77103"
+       id="path2583" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 267.66355,412.99065 L 267.66355,448.73832 L 270.44393,445.16355 L 270.44393,412.99065"
+       id="path2585" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 250.98131,436.42523 L 261.70561,439.20561"
+       id="path2587" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 264.08879,439.20561 L 267.66355,440"
+       id="path2589" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 270.84112,439.20561 L 273.2243,439.20561 L 286.72897,414.57944"
+       id="path2591" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 339.15888,321.63551 L 240.65421,503.9486 L 228.34112,504.34579 L 227.14953,521.82243 L 241.84579,521.82243"
+       id="path2593" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 240.25701,513.48131 L 362.19626,322.03271"
+       id="path2595" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 243.03738,513.08411 L 376.49533,321.23832"
+       id="path2597" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 437.66355,502.35981 L 437.66355,607.61682"
+       id="path2599" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 446.40187,606.82243 L 446.40187,501.96262"
+       id="path2601" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 390.79439,516.65888 L 390.79439,599.6729"
+       id="path2689" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 397.14953,601.65888 L 397.14953,513.08411"
+       id="path2691" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 378.8785,470.98131 L 378.8785,608.80841"
+       id="path2693" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 363.38785,469.78972 L 363.38785,604.43925"
+       id="path2695" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 646.58879,353.41121 L 696.63551,329.57944"
+       id="path2707" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 556.42523,397.1028 L 575.09346,387.96729"
+       id="path2709" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 484.92991,431.65888 L 498.03739,425.30374"
+       id="path2711"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 433.69159,456.28505 L 440.04673,453.10748"
+       id="path2713"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 378.48131,482.5 L 401.1215,472.1729"
+       id="path2715" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 401.1215,429.6729 L 412.24299,421.33178"
+       id="path2721" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 453.15421,391.54206 L 471.02804,377.24299"
+       id="path2723" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 522.26636,339.50935 L 546.49533,321.23832"
+       id="path2725" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 378.8785,502.35981 L 400.3271,494.81308"
+       id="path2729" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.61215,489.25234 L 455.53738,476.93925"
+       id="path2731" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 519.88318,455.49065 L 530.60748,451.1215"
+       id="path2733" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 575.09346,436.02804 L 593.36449,429.6729"
+       id="path2735" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 664.06542,407.03271 L 685.11682,399.08878"
+       id="path2737" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 378.48131,514.6729 L 400.3271,508.71495"
+       id="path2741" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.61215,504.34579 L 455.93458,494.81308"
+       id="path2743" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 477.78037,488.85514 L 506.7757,480.91121"
+       id="path2745" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 520.67757,478.13084 L 530.60748,475.35047"
+       id="path2747" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 357.42991,478.92523 L 357.99163,596.17798"
+       id="path2771"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 344.32243,478.92523 L 344.32243,602.85047"
+       id="path2773" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 288.31776,466.21496 L 288.71495,481.30841 L 293.48131,476.14486 L 293.48131,461.84579"
+       id="path2775"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 293.48131,476.54206 L 363.78505,478.13084"
+       id="path2777" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 287.52336,481.70561 L 344.32243,483.69159"
+       id="path2779" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 357.03271,483.69159 L 363.38785,484.08878"
+       id="path2781" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 379.2757,484.88318 L 399.92991,485.28037"
+       id="path2783" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 478.57477,494.01869 L 488.90187,495.21028 L 491.68224,492.8271 L 478.17757,492.03271"
+       id="path2785" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 491.28505,492.8271 L 491.28505,485.28037 L 506.7757,486.07477"
+       id="path2787" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 338.76168,488.45794 L 338.76168,601.65888"
+       id="path2789" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 326.84579,492.8271 L 326.84579,599.2757"
+       id="path2791" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 313.34112,504.34579 L 313.34112,597.68692"
+       id="path2793" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 322.87383,504.34579 L 322.87383,598.08411"
+       id="path2795" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 391.19159,517.85047 L 384.43925,515.86449 L 385.63084,519.83645 L 381.26168,519.83645 L 381.26168,601.26168"
+       id="path2797" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 436.86916,502.75701 L 436.47196,508.31776 L 421.7757,507.92056 L 421.7757,606.02804"
+       id="path2799" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 446.40187,502.35981 L 455.53738,503.15421"
+       id="path2801" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 277.19626,478.52804 L 277.19626,489.25234 L 281.56542,485.28037 L 281.56542,470.98131"
+       id="path2803" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 276.79907,489.25234 L 327.24299,492.42991"
+       id="path2805" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 280.77103,485.67757 L 343.92523,488.85514"
+       id="path2807" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 365.37383,383.59813 L 399.13551,344.2757"
+       id="path2809" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 414.22897,327.19626 L 419.78972,321.63551"
+       id="path2811" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 506.3785,381.21495 L 485.7243,393.92523"
+       id="path2815" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 440.44393,422.92056 L 428.13084,430.07009"
+       id="path2817" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 564.36916,344.2757 L 601.30841,322.03271"
+       id="path2819" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 226.75234,540.88785 L 208.48131,540.88785"
+       id="path2821" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 235.49065,521.42523 L 226.35514,541.28505"
+       id="path3593" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 357.8271,524.6028 L 363.38785,525.3972"
+       id="path3595" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 269.64953,486.47196 L 269.64953,499.57944 L 274.81308,494.81308 L 274.81308,478.92523"
+       id="path3597" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 274.81308,495.21028 L 326.84579,497.59346"
+       id="path3599" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 270.44393,499.97664 L 326.84579,503.5514"
+       id="path3601" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 264.08879,495.60748 L 264.08879,507.12617 L 267.66355,501.16822 L 267.26636,488.85514"
+       id="path3603" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 266.86916,501.96262 L 312.94393,505.53738"
+       id="path3605" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 264.48598,508.71495 L 313.34112,513.08411"
+       id="path3607" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 329.22897,424.90654 L 352.26636,397.5 L 365.37383,383.59813"
+       id="path3609" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 276.00467,478.92523 L 330.02336,422.12617"
+       id="path3611" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 341.93925,322.42991 L 342.73365,352.21963"
+       id="path3613" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 323.66822,350.23364 L 324.85981,380.02336"
+       id="path3615" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 309.76636,376.4486 L 310.95794,403.06075"
+       id="path3617" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 299.83645,395.91121 L 301.42523,417.35981"
+       id="path3619" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 291.49533,411.00467 L 291.89252,431.65888"
+       id="path3621" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 284.34579,425.30374 L 284.74299,440.79439"
+       id="path3623" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 278.78505,434.43925 L 278.78505,451.51869"
+       id="path3625" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 274.01869,443.57477 L 274.81308,459.46262"
+       id="path3627" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 270.04673,453.50467 L 271.23832,463.83178"
+       id="path3629" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 382.45327,385.18692 L 399.92991,369.29907"
+       id="path3631" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 243.03738,546.4486 L 243.03738,579.01869"
+       id="path3633" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 247.00935,543.66822 L 247.00935,579.41589"
+       id="path3635" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 254.15888,538.90187 L 254.15888,582.59346"
+       id="path3637" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 264.08879,530.95794 L 264.08879,585.77103"
+       id="path3639" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 276.79907,522.61682 L 276.79907,589.74299"
+       id="path3641" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 288.31776,516.65888 L 288.31776,591.33178"
+       id="path3643" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 299.83645,513.48131 L 299.83645,594.50935"
+       id="path3645" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 259.32243,513.8785 L 299.83645,517.45327"
+       id="path3647" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 253.36449,522.61682 L 288.31776,525.79439"
+       id="path3649" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 247.00935,532.14953 L 287.12617,535.7243"
+       id="path3651" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 240.65421,541.28505 L 287.52336,546.0514"
+       id="path3653" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 227.94393,548.03738 L 264.08879,507.52336"
+       id="path3655" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 258.13084,500.37383 L 258.52804,513.48131"
+       id="path3657" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 251.3785,508.71495 L 252.1729,523.01402"
+       id="path3659" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 245.42056,517.85047 L 245.42056,528.97196"
+       id="path3661" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 208.48131,598.48131 C 209.0109,598.48131 209.0109,598.48131 208.48131,598.48131 C 184.73314,598.48131 229.62274,598.2064 232.31308,598.08411 C 253.32854,597.12886 294.77089,592.74776 282.35981,602.05607 C 280.87695,603.16822 286.06698,602.05607 287.92056,602.05607 C 313.41005,602.05607 339.6461,601.62475 364.97664,604.43925"
+       id="path3663" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 378.8785,606.02804 C 379.81471,606.02804 379.92829,608.01402 380.86449,608.01402 C 385.89564,608.01402 390.92679,608.01402 395.95794,608.01402 C 396.88474,608.01402 397.81153,608.01402 398.73832,608.01402"
+       id="path3665" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 416.21495,610 C 419.04629,607.16866 442.65197,611.04868 452.35981,608.80841 C 455.60816,608.05879 459.00136,608.16488 462.28972,607.61682"
+       id="path3669" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 477.78037,608.41121 C 483.87911,607.00381 494.08993,607.67894 501.61215,606.42523"
+       id="path3671" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 520.67757,605.23364 C 521.99636,604.92931 526.81575,605.23364 529.41589,605.23364"
+       id="path3673" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 560.79439,607.21963 C 564.51127,606.36189 570.38941,605.44704 573.90187,604.04206"
+       id="path3675" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 586.21495,605.23364 C 590.50165,604.24441 630.08802,599.3442 629.11215,603.24766 C 627.21393,610.84053 638.84009,604.3652 647.78037,603.24766 C 654.55147,602.40128 662.37128,601.28802 668.83178,599.6729"
+       id="path3677" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 208.08411,646.93925 C 233.25145,643.79333 263.07586,642.57009 289.90654,642.57009 C 317.17881,642.57009 297.95203,647.73364 306.58879,647.73364 C 338.69692,647.73364 370.66104,645.74766 402.71028,645.74766 C 413.20578,645.74766 423.59903,646.14486 434.08879,646.14486 C 445.82806,646.14486 466.47677,642.52299 481.35514,641.3785 C 493.49928,640.44434 506.94597,640.74014 518.69159,637.80374"
+       id="path3679" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 558.01402,645.74766 C 566.02729,645.13126 630.90154,637.20593 623.9486,644.15888 C 609.19293,658.91454 640.73605,647.52109 645.79439,646.54206 C 663.28084,643.15758 686.11885,647.39964 702.99065,641.7757"
+       id="path3681" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 189.31151,626.96602 C 189.31151,626.96602 189.31151,626.96602 189.31151,626.96602 C 219.3456,626.27472 251.27733,616.55101 280.66665,619.81649 C 296.43436,621.56846 261.16893,628.95201 287.02179,628.95201 C 310.43519,628.95201 347.82207,622.81197 372.41899,619.4193 C 376.99963,618.78748 382.32616,618.75983 387.11525,618.22771"
+       id="path3683" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 425.35047,669.97664 C 425.35047,669.97664 425.35047,669.97664 425.35047,669.97664 C 428.72863,668.56238 503.59889,659.53562 490.88785,666.79907 C 476.88606,674.80009 533.88925,667.73431 536.56542,667.59346 C 557.61721,666.48547 595.81464,662.90966 618.38785,657.26636"
+       id="path3685" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 594.95327,583.38785 C 599.25653,582.31204 636.49349,574.81492 629.11215,582.19626 C 628.7741,582.53431 657.41095,581.79907 663.27103,581.79907"
+       id="path3687" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 212.85047,588.15421 C 211.73256,589.27212 217.21605,588.3378 224.76636,587.75701 C 226.48754,587.62461 228.20872,587.49221 229.92991,587.35981 C 230.52027,587.3144 229.40031,588.419 229.13551,588.9486 C 228.95071,589.31821 232.52655,589.0837 242.64019,588.5514"
+       id="path3689" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 486.1215,584.97664 C 487.3059,584.9143 481.40329,588.15421 488.10748,588.15421 C 492.79713,588.15421 497.02074,586.65289 499.22897,587.75701"
+       id="path3691" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 588.99533,569.08878 C 612.95446,569.08878 635.03634,568.50666 658.90187,567.1028 C 661.54858,566.94711 664.19782,566.83801 666.84579,566.70561"
+       id="path3693" />
+  </g>
+  <text
+     xml:space="preserve"
+     style="font-size:18.56676483px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Futura;-inkscape-font-specification:Futura"
+     x="346.36441"
+     y="135.48186"
+     id="text3745"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan3747"
+       x="346.36441"
+       y="135.48186">the third Fleet test chip</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:26px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Futura;-inkscape-font-specification:Futura"
+     x="6.1165991"
+     y="153.95485"
+     id="text3749"
+     sodipodi:linespacing="100%"><tspan
+       sodipodi:role="line"
+       id="tspan3751"
+       x="6.1165991"
+       y="153.95485"
+       style="font-size:26px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Futura;-inkscape-font-specification:Futura">Sutherland</tspan><tspan
+       sodipodi:role="line"
+       x="6.1165991"
+       y="179.95485"
+       style="font-size:26px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Futura;-inkscape-font-specification:Futura"
+       id="tspan3940">Megacz</tspan></text>
+  <text
+     sodipodi:linespacing="125%"
+     id="text3785"
+     y="206.48242"
+     x="7.0163794"
+     style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Futura;-inkscape-font-specification:Futura"
+     xml:space="preserve"><tspan
+       id="tspan3791"
+       y="206.48242"
+       x="7.0163794"
+       sodipodi:role="line">Coates</tspan><tspan
+       y="231.48242"
+       x="7.0163794"
+       sodipodi:role="line"
+       id="tspan3936">Amberg</tspan><tspan
+       y="256.48242"
+       x="7.0163794"
+       sodipodi:role="line"
+       id="tspan3797">Kao</tspan><tspan
+       y="281.48245"
+       x="7.0163794"
+       sodipodi:role="line"
+       id="tspan3948">Lexau</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:18.56676483px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:100%;writing-mode:lr-tb;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Futura;-inkscape-font-specification:Futura"
+     x="531.3111"
+     y="499.19904"
+     id="text3942"
+     sodipodi:linespacing="100%"><tspan
+       sodipodi:role="line"
+       x="531.3111"
+       y="499.19904"
+       id="tspan3698">2009-0334</tspan><tspan
+       sodipodi:role="line"
+       x="531.3111"
+       y="517.76581"
+       id="tspan3702">2009 Sun Microsystems</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:18.56676483px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Futura;-inkscape-font-specification:Futura"
+     x="310.23792"
+     y="517.2558"
+     id="text4000"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       x="310.23792"
+       y="517.2558"
+       id="tspan4004">Ⓜ</tspan></text>
+  <image
+     y="25.335388"
+     x="7.485271"
+     id="image2730"
+     height="86.774666"
+     width="531.67871"
+     sodipodi:absref="/Users/megacz/Desktop/chip logo/title.png"
+     xlink:href="title.png" />
+</svg>
diff --git a/marina/logo/marina-logo.xcf b/marina/logo/marina-logo.xcf
new file mode 100644 (file)
index 0000000..1d310dd
Binary files /dev/null and b/marina/logo/marina-logo.xcf differ
diff --git a/marina/logo/metal9.png b/marina/logo/metal9.png
new file mode 100644 (file)
index 0000000..8e3a9ad
Binary files /dev/null and b/marina/logo/metal9.png differ
diff --git a/marina/logo/photo.jpeg b/marina/logo/photo.jpeg
new file mode 100644 (file)
index 0000000..2e1ba65
Binary files /dev/null and b/marina/logo/photo.jpeg differ
diff --git a/marina/logo/sun.logo.pdf b/marina/logo/sun.logo.pdf
new file mode 100644 (file)
index 0000000..455499c
Binary files /dev/null and b/marina/logo/sun.logo.pdf differ
diff --git a/marina/logo/sun.logo.png b/marina/logo/sun.logo.png
new file mode 100644 (file)
index 0000000..1a1426a
Binary files /dev/null and b/marina/logo/sun.logo.png differ
diff --git a/marina/logo/title.png b/marina/logo/title.png
new file mode 100644 (file)
index 0000000..6db4b4e
Binary files /dev/null and b/marina/logo/title.png differ
diff --git a/marina/logo/viram.logo.png b/marina/logo/viram.logo.png
new file mode 100644 (file)
index 0000000..ff74052
Binary files /dev/null and b/marina/logo/viram.logo.png differ
diff --git a/marina/tapeout.jpeg b/marina/tapeout.jpeg
new file mode 100644 (file)
index 0000000..ca0ccf5
Binary files /dev/null and b/marina/tapeout.jpeg differ
diff --git a/marina/tapeout2.jpeg b/marina/tapeout2.jpeg
new file mode 100644 (file)
index 0000000..a9ed101
Binary files /dev/null and b/marina/tapeout2.jpeg differ
similarity index 100%
rename from testCode/cfg
rename to marina/testCode/cfg
similarity index 100%
rename from testCode/runOne.sh
rename to marina/testCode/runOne.sh
diff --git a/misc/Makefile b/misc/Makefile
new file mode 100644 (file)
index 0000000..8a21424
--- /dev/null
@@ -0,0 +1,38 @@
+#Add -DFORCE_PC3_IDENT to CFLAGS to force the identification of
+#a Parallel Cable III
+CFLAGS=-Wall -fPIC -DUSB_DRIVER_VERSION="\"$(shell stat -c '%y' usb-driver.c |cut -d\. -f1)\"" #-DFORCE_PC3_IDENT
+
+LIBS=-ldl -lusb -lpthread
+
+SRC=usb-driver.c parport.c config.c jtagmon.c
+HEADER=usb-driver.h parport.h jtagkey.h config.h jtagmon.h
+
+ifeq ($(LIBVER),32)
+CFLAGS += -m32
+endif
+
+FTDI := $(shell libftdi-config --libs 2>/dev/null)
+ifneq ($(FTDI),)
+SRC += jtagkey.c
+CFLAGS += -DJTAGKEY
+LIBS += $(FTDI)
+endif
+
+SOBJECTS=libusb-driver.so libusb-driver-DEBUG.so
+
+all: $(SOBJECTS)
+       @file libusb-driver.so | grep x86-64 >/dev/null && echo Built library is 64 bit. Run \`make lib32\' to build a 32 bit version || true
+
+libusb-driver.so: $(SRC) $(HEADER) Makefile
+       $(CC) $(CFLAGS) $(SRC) -o $@ $(LIBS) -shared
+
+libusb-driver-DEBUG.so: $(SRC) $(HEADER) Makefile
+       $(CC) -DDEBUG $(CFLAGS) $(SRC) -o $@ $(LIBS) -shared
+
+lib32:
+       $(MAKE) LIBVER=32 clean all
+
+clean:
+       rm -f $(SOBJECTS)
+
+.PHONY: clean all lib32
diff --git a/misc/README b/misc/README
new file mode 100644 (file)
index 0000000..f69cadd
--- /dev/null
@@ -0,0 +1,151 @@
+This library emulates Jungo Windrvr USB and parallel port functions in
+userspace which are required by XILINX impact to access the Platform cable USB
+and Parallel Cable III.
+With this library it is possible to access the cables without loading a
+proprietary kernel module which breaks with every new kernel release. It uses
+the functionality provided by the libusb userspace library for USB access and
+the kernel interface at /dev/parport0 for parallel port access instead and
+should work on every kernel version which is supported by libusb and supports
+ppdev. It was written against impact from ISE Webpack 9.1SP1 and tested with
+the following software:
+
+ * ISE Webpack 9.2SP1, SP2, SP3
+ * ISE Webpack 9.1SP1, SP2, SP3
+ * ISE Webpack 8.2SP3
+ * ISE Webpack 8.1SP3
+ * ChipScope 9.2.01i, 9.2.02i
+ * ChipScope 9.1.02i, 9.1.03i
+ * ChipScope 8.2.04i
+ * EDK 9.2.01i
+ * EDK 9.1.01i, 9.1.02i
+ * EDK 8.2.02i
+ * EDK 8.1.02i
+ * Synplicity Identify
+
+In addition to the XILINX USB and parallel cables, devices based on the FTDI
+2232 serial converter chip are also experimentally supported. This includes
+devices like the Amontec JTAGkey(-Tiny).
+
+Build the library by calling `make'. If you are on a 64 bit system but want
+to build a 32 bit library, run `make lib32' instead.
+
+To use this library you have to preload the library before starting impact:
+
+$ LD_PRELOAD=/path/to/libusb-driver.so impact
+or
+$ export LD_PRELOAD=/path/to/libusb-driver.so  (for sh shells)
+$ setenv LD_PRELOAD /path/to/libusb-driver.so  (for csh shells)
+$ impact
+
+The source for this library can be found at:
+http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver
+
+The main website is located at:
+http://www.rmdir.de/~michael/xilinx/
+
+The Git repository can be cloned with:
+git clone git://git.zerfleddert.de/usb-driver
+
+
+Notes for the USB cable
+=======================
+
+To use the device as an ordinary user, put the following line in a new
+file "libusb-driver.rules" in /etc/udev/rules.d/ and restart udev:
+ACTION=="add", BUS=="usb", SYSFS{idVendor}=="03fd", MODE="666"
+
+
+If your cable does not have the ID 03fd:0008 in the output of lsusb,
+the initial firmware has not been loaded (loading it changes the
+product-ID from another value to 8). To load the firmware follow
+these steps:
+
+1. If you have no /etc/udev/rules.d/xusbdfwu.rules file, copy it from
+   /path/to/ISE/bin/lin/xusbdfwu.rules to /etc/udev/rules.d/xusbdfwu.rules
+
+2. Install the package containing /sbin/fxload from your linux distribution.
+   It is usually called "fxload"
+
+3. copy the files /path/to/ISE/bin/lin/xusb*.hex to /usr/share/
+
+4. restart udev and re-plug the cable
+
+
+If you have multiple cables connected, you can specify the cable to use
+in the XILINX_USB_DEV environment-variable as "bus:device".
+These identifiers are available in the output of lsusb:
+Bus 001 Device 004: ID 03fd:0008 Xilinx, Inc.
+    ^^^        ^^^
+To use this cable, set the XILINX_USB_DEV variable to "001:004".
+
+
+Notes for the parallel cable
+============================
+
+To access the parallel port from userspace, the kernel needs to be built with
+the features "Parallel port support" (CONFIG_PARPORT), "PC-style hardware"
+(CONFIG_PARPORT_PC) and "Support for user-space parallel port device drivers"
+(CONFIG_PPDEV) builtin or as modules. If these features are built as modules,
+they need to be loaded before using this library.
+These modules are called:
+parport
+parport_pc
+ppdev
+
+
+To use the device as an ordinary user, put the user in the group 'lp'
+
+
+If you have an almost compatible cable which works with other software but not
+with Impact, try adding -DFORCE_PC3_IDENT to the CFLAGS line in the Makefile.
+This enables a hack by Stefan Ziegenbalg to force detection of a parallel cable.
+
+
+Parallel Cable IV is currently only supported in 'compatibility mode', as no
+attempt to configure the ECP registers is done by this library.
+
+
+If you get "Programming failed" or "DONE did not go high" when programming
+through the parallel cable with Impact 9.1, make sure to have the option "Use
+HIGHZ instead of BYPASS" enabled in Edit -> Preferences -> iMPACT Configuration
+Preferences.
+If you are using batch mode, add the following line to your cmd file:
+setPreference -pref UseHighz:TRUE
+(This problem also occurs on windows and when using the real windrvr in linux
+and is solved with the same workaround. Impact 8.2 is working fine with the same
+boards and designs)
+
+
+Notes for FTDI 2232 based cables
+================================
+
+To build the driver with FTDI 2232 support, you need to have libftdi and
+the libftdi development package installed. On debian, you can install both
+by installing 'libftdi-dev'.
+
+To set-up the device:
+1. Find out the vendor and product id of your cable using lsusb:
+   Bus 003 Device 005: ID 0403:cff8 Future Technology Devices ...
+                          ~~~~~~~~~
+
+2. Copy the sample libusb-driverrc to ~/.libusb-driverrc, edit it and replace
+   the vendor and product-id in the example file with the values provided in
+   the lsusb-output. You can also change the 'parallel port' which is mapped to
+   this cable. Impact sees the device at that port as a Parallel Cable III.
+
+3. To use the device as an ordinary user, put the following line in a new file
+   in /etc/udev/rules.d/ and restart udev:
+   ACTION=="add", BUS=="usb", SYSFS{idVendor}=="0403", SYSFS{idProduct}=="cff8", MODE="666"
+   (replace the vendor and product id with your values)
+
+The support for FTDI 2232 based devices is experimental and they are currently
+significantly slower than the other supported cables.
+
+
+Locked cables
+=============
+
+If you get the message 'The cable is being used by another application.' from
+impact, try running the following command:
+
+echo -e 'cleancablelock\nexit' | impact -batch
diff --git a/misc/config.c b/misc/config.c
new file mode 100644 (file)
index 0000000..a39902e
--- /dev/null
@@ -0,0 +1,245 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include "usb-driver.h"
+#include "parport.h"
+#ifdef JTAGKEY
+#include "jtagkey.h"
+#endif
+#include "config.h"
+
+#define LINELEN 1024
+
+#define PARSEERROR fprintf(stderr,"LIBUSB-DRIVER WARNING: Invalid config statement at line %d\n", line)
+
+static struct parport_config pp_config[4];
+
+static void read_config() {
+       int i;
+       static int config_read = 0;
+       FILE *cfg;
+       char buf[LINELEN];
+#ifdef JTAGKEY
+       char *pbuf;
+       unsigned short vid, pid;
+       int line, len, num;
+#endif
+
+       if (config_read)
+               return;
+       
+       config_read = 1;
+
+       for (i=0; i<sizeof(pp_config)/sizeof(struct parport_config); i++) {
+               pp_config[i].num = i;
+               pp_config[i].ppbase = i*0x10;
+               pp_config[i].real = 1;
+               pp_config[i].open = parport_open;
+               pp_config[i].close = parport_close;
+               pp_config[i].transfer = parport_transfer;
+       }
+
+       snprintf(buf, sizeof(buf), "%s/.libusb-driverrc", getenv("HOME"));
+
+       cfg = fopen(buf, "r");
+       if (cfg) {
+#ifdef JTAGKEY
+               line = 0;
+               do {
+                       pbuf = fgets(buf, sizeof(buf), cfg);
+                       if (!pbuf)
+                               break;
+
+                       line++;
+
+                       len = strlen(buf);
+
+                       if (len > 0 && buf[len-1] == '\n') {
+                               buf[len-1] = '\0';
+                               len--;
+                       }
+                       if (len > 0 && buf[len-1] == '\r') {
+                               buf[len-1] = '\0';
+                               len--;
+                       }
+                       
+                       for (i = 0; i < len; i++) {
+                               if (buf[i] != ' ' && buf[i] != '\t')
+                                       break;
+                       }
+
+                       if (buf[i] == '#' || buf[i] == ';' || buf[i] == '\0')
+                               continue;
+
+                       if (!strncasecmp(buf+i, "LPT", 3)) {
+                               unsigned char equal_seen = 0;
+
+                               i += 3;
+                               pbuf = buf+i;
+                               for (; i < len; i++) {
+                                       if (buf[i] == ' ' || buf[i] == '\t' || buf[i] == '=') {
+                                               if (buf[i] == '=')
+                                                       equal_seen = 1;
+
+                                               buf[i] = '\0';
+                                               i++;
+                                               break;
+                                       }
+                               }
+
+                               if (*pbuf == '\0') {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               num = 0;
+                               num = strtol(pbuf, NULL, 10);
+                               if (num < 1) {
+                                       PARSEERROR;
+                                       continue;
+                               }
+                               num--;
+
+                               for (; (i < len) && (!equal_seen) ; i++) {
+                                       if (buf[i] == '=') {
+                                               equal_seen = 1;
+                                               i++;
+                                               break;
+                                       } else if (buf[i] != ' ' && buf[i] != '\t') {
+                                               break;
+                                       }
+                               }
+
+                               if (!equal_seen) {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               for (; i < len; i++) {
+                                       if (buf[i] != ' ' && buf[i] != '\t')
+                                               break;
+                               }
+
+                               if (strncasecmp(buf+i, "FTDI:", 5)) {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               i += 5;
+                               pbuf = buf + i;
+
+                               for (; i < len; i++) {
+                                       if (buf[i] == ':')
+                                               break;
+                               }
+
+                               if (buf[i] != ':') {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               buf[i] = '\0';
+
+                               vid = 0;
+                               vid = strtol(pbuf, NULL, 16);
+                               if (!vid) {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               i++;
+                               pbuf = buf + i;
+
+                               for (; i < len; i++) {
+                                       if (buf[i] == ' ' || buf[i] == '\t')
+                                               break;
+                               }
+
+                               pid = 0;
+                               pid = strtol(pbuf, NULL, 16);
+                               if (!pid) {
+                                       PARSEERROR;
+                                       continue;
+                               }
+
+                               pp_config[num].real = 0;
+                               pp_config[num].usb_vid = vid;
+                               pp_config[num].usb_pid = pid;
+                               pp_config[num].open = jtagkey_open;
+                               pp_config[num].close = jtagkey_close;
+                               pp_config[num].transfer = jtagkey_transfer;
+                       } else {
+                               PARSEERROR;
+                       }
+               } while (pbuf);
+#else
+               fprintf(stderr,"libusb-driver not compiled with FTDI2232-support, config file ignored!\n");
+#endif
+               fclose(cfg);
+       }
+}
+
+struct parport_config *config_get(int num) {
+       struct parport_config *ret = NULL;
+       int i;
+
+       read_config();
+       
+       for (i=0; i<sizeof(pp_config)/sizeof(struct parport_config); i++) {
+               if (pp_config[i].num == num) {
+                       ret = &(pp_config[i]);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+unsigned char config_is_real_pport(int num) {
+       int ret = 1;
+       int i;
+
+       read_config();
+       
+       for (i=0; i<sizeof(pp_config)/sizeof(struct parport_config); i++) {
+               if (pp_config[i].num == num) {
+                       ret = pp_config[i].real;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+unsigned short config_usb_vid(int num) {
+       unsigned short ret = 0x00;
+       int i;
+       
+       read_config();
+       
+       for (i=0; i<sizeof(pp_config)/sizeof(struct parport_config); i++) {
+               if (pp_config[i].num == num) {
+                       ret = pp_config[i].usb_vid;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+unsigned short config_usb_pid(int num) {
+       unsigned short ret = 0x00;
+       int i;
+       
+       read_config();
+       
+       for (i=0; i<sizeof(pp_config)/sizeof(struct parport_config); i++) {
+               if (pp_config[i].num == num) {
+                       ret = pp_config[i].usb_pid;
+                       break;
+               }
+       }
+
+       return ret;
+}
diff --git a/misc/config.h b/misc/config.h
new file mode 100644 (file)
index 0000000..e3e42ea
--- /dev/null
@@ -0,0 +1,15 @@
+struct parport_config {
+       int num;
+       unsigned long ppbase;
+       unsigned char real;
+       unsigned short usb_vid;
+       unsigned short usb_pid;
+       int (*open) (int num);
+       void (*close) (int handle);
+       int (*transfer) (WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num);
+};
+
+struct parport_config *config_get(int num);
+unsigned char config_is_real_pport(int num);
+unsigned short config_usb_vid(int num);
+unsigned short config_usb_pid(int num);
diff --git a/misc/index.html b/misc/index.html
new file mode 100644 (file)
index 0000000..9066731
--- /dev/null
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML>
+       <HEAD>
+               <TITLE>XILINX USB/Parallel JTAG cables on Linux without windrvr</TITLE>
+       </HEAD>
+       <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
+               <H1>XILINX JTAG tools on Linux without proprietary kernel modules</H1>
+               <H2>About</H2>
+               <P>
+               When using <a href="http://www.xilinx.com">XILINX</a> JTAG software like Impact, Chipscope and XMD
+               on Linux, the proprietary kernel module <i>windrvr</i> from <a href="http://www.jungo.com">Jungo</a>
+               is needed to access the parallel- or usb-cable.
+               As this module does not work with current linux kernel versions (&gt; 2.6.18) a library was developed,
+               which emulates the module in userspace and allows the tools to access the JTAG cable without the need
+               for a proprietary kernel module.
+               </P>
+               <P>
+               The library uses <a href="http://libusb.sourceforge.net/">libusb</a> to access USB devices and the
+               <a href="http://people.redhat.com/twaugh/parport/html/x623.html">ppdev</a> interface to communicate
+               with parallel cables. The parallel part currently only supports Parallel Cable III mode (and PCIV in
+               PCIII compatibility mode) as the faster PCIV modes use another kernel module which is not emulated by
+               this library. So you are limited to a 200kHz JTAG clock when using Parallel Cable IV with this software.
+               The USB cable is supported at full speed.
+               </P>
+               <P>
+               Experimental support for FTDI 2232 based devices has been added. They are seen by Impact as a Parallel
+               Cable III. These devices are currently significantly slower than every other supported cable.
+               </P>
+               <P>
+               The library is called <i>libusb-driver</i> as it was developed to support the USB cable, but later
+               extended to also support parallel cables.
+               </P>
+               <H2>Supported Cables</H2>
+               The following cables are reported to work with this driver:
+               <ul>
+                       <li><a href="http://direct.xilinx.com/bvdocs/publications/ds300.pdf">XILINX Platform Cable USB DLC9, DLC9LP and DLC9G</a></li>
+                       <li><a href="http://www.xilinx.com/s3estarter">Integrated Platform Cable USB on Spartan 3E starter kit</a></li>
+                       <li><a href="http://www.xilinx.com/s3astarter">Integrated Platform Cable USB on Spartan 3A starter kit</a></li>
+                       <li><a href="http://www.digilentinc.com/Products/Detail.cfm?Nav1=Products&Nav2=Programmable&Prod=XUPV2P">Integrated Platform Cable USB on XUP-V2Pro</a></li>
+                       <li><a href="http://direct.xilinx.com/bvdocs/publications/ds097.pdf">XILINX Parallel Cable IV</a> (in Parallel Cable III compatibility mode)</li>
+                       <li><a href="http://www.enterpoint.co.uk/">Enterpoint Prog2</a> Parallel Cable III clone</li>
+                       <li><a href="http://www.trenz-electronic.de/">Trenz TE0149-01</a> Parallel Cable III clone</li>
+                       <li><a href="http://www.digilentinc.com/Products/Catalog.cfm?Nav1=Products&amp;Nav2=Cables&amp;Cat=Cable">Digilent JTAG3</a> Parallel Cable III clone</li>
+                       <li><a href="http://www.amontec.com/">Amontec JTAGkey-Tiny</a> (experimental)</li>
+               </ul>
+               These cables should work but have not yet been tested:
+               <ul>
+                       <li>Integrated Platform Cable USB on other development boards</li>
+                       <li>other Parallel Cable III clones</li>
+                       <li>other FTDI2232 based devices which use the chips standard JTAG pinout (experimental)</li>
+               </ul>
+               <H2>Supported Software</H2>
+               The following software is reported to work with this driver:
+               <ul>
+                       <li><a href="http://www.xilinx.com/ise/logic_design_prod/webpack.htm">ISE Webpack 9.2 SP1, SP2 and SP3</a></li>
+                       <li><a href="http://www.xilinx.com/ise/logic_design_prod/webpack.htm">ISE Webpack 9.1 SP1, SP2 and SP3</a></li>
+                       <li><a href="http://www.xilinx.com/ise/logic_design_prod/webpack.htm">ISE Webpack 8.2 SP3</a></li>
+                       <li><a href="http://www.xilinx.com/ise/logic_design_prod/webpack.htm">ISE Webpack 8.1 SP3</a></li>
+                       <li><a href="http://www.xilinx.com/ise/optional_prod/cspro.htm">ChipScope Pro 9.2.01i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/optional_prod/cspro.htm">ChipScope Pro 9.1.02i and 9.1.03i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/optional_prod/cspro.htm">ChipScope Pro 8.2.04i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/embedded_design_prod/platform_studio.htm">EDK 9.2.01i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/embedded_design_prod/platform_studio.htm">EDK 9.1.01i and 9.1.02i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/embedded_design_prod/platform_studio.htm">EDK 8.2.02i</a></li>
+                       <li><a href="http://www.xilinx.com/ise/embedded_design_prod/platform_studio.htm">EDK 8.1.02i</a></li>
+                       <li><a href="http://www.synplicity.com/products/identify/index.html">Synplicity Identify Debugger</a></li>
+               </ul>
+               <H2>Download</H2>
+               <ul>
+                       <li>Download <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver?a=snapshot;h=HEAD;sf=tgz">usb-driver-HEAD.tar.gz</a> (to build it, you need to have the libusb development package installed. It is called libusb-dev on Debian.)</li>
+                       <li>Read the <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver?a=blob_plain;f=README;hb=HEAD">README</a></li>
+                       <li>Browse the <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver?a=tree">Git repository</a> (<a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver">Summary</a>)</li>
+                       <li>Precompiled <a href="libusb-driver.so">libusb-driver.so</a> for Debian Etch, but better build your own</li>
+                       <li>Clone the <a href="http://git.or.cz/">Git</a> repository with: <kbd>git clone git://git.zerfleddert.de/usb-driver</kbd></li>
+               </ul>
+               <H2>Links</H2>
+               <ul>
+                       <li><a href="http://groups.google.com/group/comp.arch.fpga/msg/94d8bb1f52e06b44">XILINX listened</a></li>
+                       <li><a href="http://svenand.blogdrive.com/archive/55.html">Installation instructions using a MacBook running Ubuntu in VMware by Sven Andersson</a></li>
+                       <li><a href="http://groups.google.com/group/comp.arch.fpga/browse_thread/thread/954a145428ec2c54/555f6bfb766a3a93#555f6bfb766a3a93">Using the libusb-driver on a 64bit system with a 32bit ISE by Ken Ryan</a></li>
+                       <li><a href="http://groups.google.com/group/comp.arch.fpga/msg/2dfa36541174a4f2">Ubuntu installation instructions by Luzerne</a></li>
+                       <li><a href="http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/archive/2007/03/msg00101.html">Ubuntu installation instructions by Paul-Armand Verhaegen</a></li>
+                       <li><a href="http://groups.google.com/group/comp.arch.fpga/browse_frm/thread/f149e5b6028e2c70">Initial announcement on comp.arch.fpga</a></li>
+                       <li><a href="http://inisyn.org/src/xup/">XUP</a> by inisyn research, opensource JTAG programming for Spartan 3E starter kit USB cable</li>
+                       <li><a href="http://www.ixo.de/info/usb_jtag/">USB JTAG adapter</a> by Kolja Waschk, opensource integration of the XILINX platform cable USB into OpenOCD and openwince JTAG Tools</li>
+                       <li><a href="http://www.rogerstech.co.uk/xc3sprog/">Spartan3 JTAG download tools for GNU/Linux (xc3sprog)</a></li>
+               </ul>
+               <HR>
+               <FONT SIZE="-1"><I><A HREF="mailto:cabledriver@zerfleddert.de">Michael Gernoth</A></I></FONT>
+       </BODY>
+</HTML>
diff --git a/misc/jtagkey.c b/misc/jtagkey.c
new file mode 100644 (file)
index 0000000..fc9587c
--- /dev/null
@@ -0,0 +1,376 @@
+#include <stdio.h>
+#include <ftdi.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <inttypes.h>
+#include "usb-driver.h"
+#include "config.h"
+#include "jtagkey.h"
+#include "jtagmon.h"
+
+#define USBBUFSIZE 1048576
+#define JTAG_SPEED 100000
+#define BULK_LATENCY 2
+#define OTHER_LATENCY 1
+
+static struct ftdi_context ftdic;
+
+static int jtagkey_latency(int latency) {
+       static int current = 0;
+       int ret;
+
+       if (current != latency) {
+               DPRINTF("switching latency\n");
+               if ((ret = ftdi_set_latency_timer(&ftdic, latency))  != 0) {
+                       fprintf(stderr, "unable to set latency timer: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+                       return ret;
+               }
+               
+               current = latency;
+       }
+
+       return ret;
+}
+
+static int jtagkey_init(unsigned short vid, unsigned short pid) {
+       int ret = 0;
+       unsigned char c;
+
+       if ((ret = ftdi_init(&ftdic)) != 0) {
+               fprintf(stderr, "unable to initialise libftdi: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+       
+       if ((ret = ftdi_usb_open(&ftdic, vid, pid)) != 0) {
+               fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_usb_reset(&ftdic)) != 0) {
+               fprintf(stderr, "unable reset device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_set_interface(&ftdic, INTERFACE_A)) != 0) {
+               fprintf(stderr, "unable to set interface: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_write_data_set_chunksize(&ftdic, USBBUFSIZE))  != 0) {
+               fprintf(stderr, "unable to set write chunksize: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_read_data_set_chunksize(&ftdic, USBBUFSIZE))  != 0) {
+               fprintf(stderr, "unable to set read chunksize: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = jtagkey_latency(OTHER_LATENCY)) != 0)
+               return ret;
+
+       c = 0x00;
+       ftdi_write_data(&ftdic, &c, 1);
+
+       if ((ret = ftdi_set_bitmode(&ftdic, JTAGKEY_TCK|JTAGKEY_TDI|JTAGKEY_TMS|JTAGKEY_OEn, BITMODE_SYNCBB))  != 0) {
+               fprintf(stderr, "unable to enable bitbang mode: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_set_baudrate(&ftdic, JTAG_SPEED))  != 0) {
+               fprintf(stderr, "unable to set baudrate: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       if ((ret = ftdi_usb_purge_buffers(&ftdic))  != 0) {
+               fprintf(stderr, "unable to purge buffers: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+               return ret;
+       }
+
+       return ret;
+}
+
+int jtagkey_open(int num) {
+       int ret;
+
+       ret = jtagkey_init(config_usb_vid(num), config_usb_pid(num));
+
+       if (ret >= 0)
+               ret = 0xff;
+
+       return ret;
+}
+
+void jtagkey_close(int handle) {
+       if (handle == 0xff) {
+               ftdi_disable_bitbang(&ftdic);
+               ftdi_usb_close(&ftdic);
+               ftdi_deinit(&ftdic);
+       }
+}
+
+#ifdef DEBUG
+static void jtagkey_state(unsigned char data) {
+       fprintf(stderr,"Pins high: ");
+
+       if (data & JTAGKEY_TCK)
+               fprintf(stderr,"TCK ");
+
+       if (data & JTAGKEY_TDI)
+               fprintf(stderr,"TDI ");
+
+       if (data & JTAGKEY_TDO)
+               fprintf(stderr,"TDO ");
+
+       if (data & JTAGKEY_TMS)
+               fprintf(stderr,"TMS ");
+
+       if (data & JTAGKEY_VREF)
+               fprintf(stderr,"VREF ");
+       
+       fprintf(stderr,"\n");
+}
+#endif
+
+struct jtagkey_reader_arg {
+       int             num;
+       unsigned char   *buf;
+};
+
+static void *jtagkey_reader(void *thread_arg) {
+       struct jtagkey_reader_arg *arg = (struct jtagkey_reader_arg*)thread_arg;
+       int i;
+
+       i = 0;
+       DPRINTF("reader for %d bytes\n", arg->num);
+       while (i < arg->num) {
+               i += ftdi_read_data(&ftdic, arg->buf + i, arg->num - i);
+       }
+       
+       pthread_exit(NULL);
+}
+
+/* TODO: Interpret JTAG commands and transfer in MPSSE mode */
+int jtagkey_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num) {
+       int ret = 0;
+       int i;
+       int nread = 0;
+       unsigned long port;
+       unsigned char val;
+       static unsigned char last_data = 0;
+       static unsigned char last_write = 0x00;
+       static unsigned char writebuf[USBBUFSIZE], *writepos = writebuf;
+       static unsigned char readbuf[USBBUFSIZE], *readpos;
+       unsigned char data, prev_data, last_cyc_write;
+       struct jtagkey_reader_arg targ;
+       pthread_t reader_thread;
+
+       /* Count reads */
+       for (i = 0; i < num; i++)
+               if (tr[i].cmdTrans == PP_READ)
+                       nread++;
+
+       /* Write combining */
+       if ((writepos-writebuf > sizeof(writebuf)-num) || (nread && writepos-writebuf)) {
+               unsigned char *pos = writebuf;
+               int len;
+
+               DPRINTF("writing %d bytes due to %d following reads in %d chunks or full buffer\n", writepos-writebuf, nread, num);
+               jtagkey_latency(BULK_LATENCY);
+
+               targ.num = writepos-pos;
+               targ.buf = readbuf;
+               pthread_create(&reader_thread, NULL, &jtagkey_reader, &targ);
+
+               while (pos < writepos) {
+                       len = writepos-pos;
+
+                       if (len > USBBUFSIZE)
+                               len = USBBUFSIZE;
+
+                       DPRINTF("combined write of %d/%d\n",len,writepos-pos);
+                       ftdi_write_data(&ftdic, pos, len);
+                       pos += len;
+               }
+               pthread_join(reader_thread, NULL);
+
+               writepos = writebuf;
+       }
+
+       last_cyc_write = last_write;
+
+       for (i = 0; i < num; i++) {
+               DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
+                               (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
+                               tr[i].fAutoinc, tr[i].dwOptions);
+
+               port = (unsigned long)tr[i].dwPort;
+               val = tr[i].Data.Byte;
+
+#ifdef DEBUG
+               if (tr[i].cmdTrans == 13)
+                       DPRINTF("write byte: %d\n", val);
+
+               if (tr[i].cmdTrans == 13)
+                       jtagmon(val & PP_TCK, val & PP_TMS, val & PP_TDI);
+#endif
+
+               /* Pad writebuf for read-commands in stream */
+               *writepos = last_data;
+               prev_data = last_data;
+
+               if (port == ppbase + PP_DATA) {
+                       DPRINTF("data port\n");
+
+                       data = 0x00;
+                       switch(tr[i].cmdTrans) {
+                               case PP_READ:
+                                       ret = 0; /* We don't support reading of the data port */
+                                       break;
+
+                               case PP_WRITE:
+                                       if (val & PP_TDI) {
+                                               data |= JTAGKEY_TDI;
+                                               DPRINTF("TDI\n");
+                                       } else {
+                                               DPRINTF("!TDI\n");
+                                       }
+                                       if (val & PP_TCK) {
+                                               data |= JTAGKEY_TCK;
+                                               DPRINTF("TCK\n");
+                                       } else {
+                                               DPRINTF("!TCK\n");
+                                       }
+                                       if (val & PP_TMS) {
+                                               data |= JTAGKEY_TMS;
+                                               DPRINTF("TMS\n");
+                                       } else {
+                                               DPRINTF("!TMS\n");
+                                       }
+                                       if (val & PP_CTRL) {
+                                               data = JTAGKEY_OEn;
+                                               DPRINTF("CTRL\n");
+                                       } else {
+                                               DPRINTF("!CTRL\n");
+                                       }
+
+                                       if (val & PP_PROG) {
+                                               DPRINTF("PROG\n");
+                                       } else {
+                                               DPRINTF("!PROG\n");
+                                       }
+
+                                       *writepos = data;
+
+                                       last_data = data;
+                                       last_write = val;
+                                       break;
+
+                               default:
+                                       fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
+                                       ret = -1;
+                                       break;
+                       }
+               }
+
+               if ((tr[i].cmdTrans == PP_READ) || (*writepos != prev_data) || (i == num-1))
+                       writepos++;
+       }
+
+       if (nread)
+       {
+               DPRINTF("writing %d bytes\n", writepos-writebuf);
+
+               *writepos = last_data;
+               writepos++;
+
+               jtagkey_latency(OTHER_LATENCY);
+
+               targ.num = writepos-writebuf;
+               targ.buf = readbuf;
+               pthread_create(&reader_thread, NULL, &jtagkey_reader, &targ);
+               ftdi_write_data(&ftdic, writebuf, writepos-writebuf);
+               pthread_join(reader_thread, NULL);
+
+#ifdef DEBUG
+               DPRINTF("write: ");
+               hexdump(writebuf, writepos-writebuf);
+               DPRINTF("read: ");
+               hexdump(readbuf, i);
+#endif
+
+               writepos = writebuf;
+       } else {
+               return ret;
+       }
+
+       readpos = readbuf;
+       last_write = last_cyc_write;
+
+       for (i = 0; i < num; i++) {
+               DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
+                               (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
+                               tr[i].fAutoinc, tr[i].dwOptions);
+
+               port = (unsigned long)tr[i].dwPort;
+               val = tr[i].Data.Byte;
+
+               if ((tr[i].cmdTrans != PP_READ) && (val == last_write) && (i != num-1))
+                       continue;
+
+               readpos++;
+
+               if (port == ppbase + PP_DATA) {
+                       if (tr[i].cmdTrans == PP_WRITE) {
+                               last_write = val;
+                       }
+               } else if (port == ppbase + PP_STATUS) {
+                       DPRINTF("status port (last write: 0x%x)\n", last_write);
+                       switch(tr[i].cmdTrans) {
+                               case PP_READ:
+                                       data = *readpos;
+
+#ifdef DEBUG
+                                       DPRINTF("READ: 0x%x\n", data);
+                                       jtagkey_state(data);
+#endif
+
+                                       val = 0x00;
+                                       if ((data & JTAGKEY_TDO) && (last_write & PP_PROG))
+                                               val |= PP_TDO;
+
+                                       if (~last_write & PP_PROG)
+                                               val |= 0x08;
+
+                                       if (last_write & 0x40)
+                                               val |= 0x20;
+                                       else
+                                               val |= 0x80;
+                                       break;
+
+                               case PP_WRITE:
+                                       ret = 0; /* Status Port is readonly */
+                                       break;
+
+                               default:
+                                       fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
+                                       ret = -1;
+                                       break;
+                       }
+               } else {
+                       ret = 0;
+               }
+
+               tr[i].Data.Byte = val;
+
+               DPRINTF("dwPortReturn: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
+                               (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
+                               tr[i].fAutoinc, tr[i].dwOptions);
+#ifdef DEBUG
+               if (tr[i].cmdTrans == 10)
+                       DPRINTF("read byte: %d\n", tr[i].Data.Byte);
+#endif
+       }
+
+       return ret;
+}
diff --git a/misc/jtagkey.h b/misc/jtagkey.h
new file mode 100644 (file)
index 0000000..2c13260
--- /dev/null
@@ -0,0 +1,10 @@
+#define JTAGKEY_TCK    0x01
+#define JTAGKEY_TDI    0x02
+#define JTAGKEY_TDO    0x04
+#define JTAGKEY_TMS    0x08
+#define JTAGKEY_VREF   0x20
+#define JTAGKEY_OEn    0x10
+
+int jtagkey_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num);
+int jtagkey_open(int num);
+void jtagkey_close(int handle);
diff --git a/misc/jtagmon.c b/misc/jtagmon.c
new file mode 100644 (file)
index 0000000..1a71ce0
--- /dev/null
@@ -0,0 +1,214 @@
+#include <string.h>
+#include <stdio.h>
+#include "jtagmon.h"
+
+enum tap_states {
+       TEST_LOGIC_RESET,
+       RUN_TEST_IDLE,
+       SELECT_DR,
+       CAPTURE_DR,
+       SHIFT_DR,
+       EXIT1_DR,
+       PAUSE_DR,
+       EXIT2_DR,
+       UPDATE_DR,
+       SELECT_IR,
+       CAPTURE_IR,
+       SHIFT_IR,
+       EXIT1_IR,
+       PAUSE_IR,
+       EXIT2_IR,
+       UPDATE_IR
+};
+
+void jtagmon(unsigned char tck, unsigned char tms, unsigned char tdi) {
+       static unsigned char last_tck = 1;
+       static char tdi_written = 0;
+       static int state = TEST_LOGIC_RESET;
+       static char state_text[32] = "Test Logic Reset";
+       char last_state_text[32];
+       int last_state = state;
+
+       strcpy(last_state_text, state_text);
+
+       if (!last_tck && tck) {
+               switch(state) {
+                       case TEST_LOGIC_RESET:
+                               if (tms) {
+                                       state = TEST_LOGIC_RESET;
+                               } else {
+                                       state = RUN_TEST_IDLE;
+                               }
+                               break;
+                       case RUN_TEST_IDLE:
+                               if (tms) {
+                                       state = SELECT_DR;
+                               } else {
+                                       state = RUN_TEST_IDLE;
+                               }
+                               break;
+                       case SELECT_DR:
+                               if (tms) {
+                                       state = SELECT_IR;
+                               } else {
+                                       state = CAPTURE_DR;
+                               }
+                               break;
+                       case CAPTURE_DR:
+                               if (tms) {
+                                       state = EXIT1_DR;
+                               } else {
+                                       state = SHIFT_DR;
+                               }
+                               break;
+                       case SHIFT_DR:
+                               if (tms) {
+                                       state = EXIT1_DR;
+                               } else {
+                                       state = SHIFT_DR;
+                               }
+                               break;
+                       case EXIT1_DR:
+                               if (tms) {
+                                       state = UPDATE_DR;
+                               } else {
+                                       state = PAUSE_DR;
+                               }
+                               break;
+                       case PAUSE_DR:
+                               if (tms) {
+                                       state = EXIT2_DR;
+                               } else {
+                                       state = PAUSE_DR;
+                               }
+                               break;
+                       case EXIT2_DR:
+                               if (tms) {
+                                       state = UPDATE_DR;
+                               } else {
+                                       state = SHIFT_DR;
+                               }
+                               break;
+                       case UPDATE_DR:
+                               if (tms) {
+                                       state = SELECT_DR;
+                               } else {
+                                       state = RUN_TEST_IDLE;
+                               }
+                               break;
+                       case SELECT_IR:
+                               if (tms) {
+                                       state = TEST_LOGIC_RESET;
+                               } else {
+                                       state = CAPTURE_IR;
+                               }
+                               break;
+                       case CAPTURE_IR:
+                               if (tms) {
+                                       state = EXIT1_IR;
+                               } else {
+                                       state = SHIFT_IR;
+                               }
+                               break;
+                       case SHIFT_IR:
+                               if (tms) {
+                                       state = EXIT1_IR;
+                               } else {
+                                       state = SHIFT_IR;
+                               }
+                               break;
+                       case EXIT1_IR:
+                               if (tms) {
+                                       state = UPDATE_IR;
+                               } else {
+                                       state = PAUSE_IR;
+                               }
+                               break;
+                       case PAUSE_IR:
+                               if (tms) {
+                                       state = EXIT2_IR;
+                               } else {
+                                       state = PAUSE_IR;
+                               }
+                               break;
+                       case EXIT2_IR:
+                               if (tms) {
+                                       state = UPDATE_IR;
+                               } else {
+                                       state = SHIFT_IR;
+                               }
+                               break;
+                       case UPDATE_IR:
+                               if (tms) {
+                                       state = SELECT_DR;
+                               } else {
+                                       state = RUN_TEST_IDLE;
+                               }
+                               break;
+               }
+
+               switch(state) {
+                       case TEST_LOGIC_RESET:
+                               strcpy(state_text, "Test Logic Reset");
+                               break;
+                       case RUN_TEST_IDLE:
+                               strcpy(state_text, "Run-Test / Idle");
+                               break;
+                       case SELECT_DR:
+                               strcpy(state_text, "Select-DR");
+                               break;
+                       case CAPTURE_DR:
+                               strcpy(state_text, "Capture-DR");
+                               break;
+                       case SHIFT_DR:
+                               strcpy(state_text, "Shift-DR");
+                               break;
+                       case EXIT1_DR:
+                               strcpy(state_text, "Exit1-DR");
+                               break;
+                       case PAUSE_DR:
+                               strcpy(state_text, "Pause-DR");
+                               break;
+                       case EXIT2_DR:
+                               strcpy(state_text, "Exit2-DR");
+                               break;
+                       case UPDATE_DR:
+                               strcpy(state_text, "Update-DR");
+                               break;
+                       case SELECT_IR:
+                               strcpy(state_text, "Select-IR");
+                               break;
+                       case CAPTURE_IR:
+                               strcpy(state_text, "Capture-IR");
+                               break;
+                       case SHIFT_IR:
+                               strcpy(state_text, "Shift-IR");
+                               break;
+                       case EXIT1_IR:
+                               strcpy(state_text, "Exit1-IR");
+                               break;
+                       case PAUSE_IR:
+                               strcpy(state_text, "Pause-IR");
+                               break;
+                       case EXIT2_IR:
+                               strcpy(state_text, "Exit2-IR");
+                               break;
+                       case UPDATE_IR:
+                               strcpy(state_text, "Update-IR");
+                               break;
+               }
+
+               if (last_state != state) {
+                       if (tdi_written)
+                               fprintf(stderr,"\n");
+
+                       fprintf(stderr,"TAP state transition from %s to %s\n", last_state_text, state_text);
+                       tdi_written = 0;
+               } else {
+                       fprintf(stderr,"%d",(tdi ? 1 : 0));
+                       tdi_written = 1;
+               }
+       }
+
+       last_tck = tck;
+}
diff --git a/misc/jtagmon.h b/misc/jtagmon.h
new file mode 100644 (file)
index 0000000..030db23
--- /dev/null
@@ -0,0 +1 @@
+void jtagmon(unsigned char tck, unsigned char tms, unsigned char tdi);
diff --git a/misc/libusb-driverrc b/misc/libusb-driverrc
new file mode 100644 (file)
index 0000000..98d0e31
--- /dev/null
@@ -0,0 +1,6 @@
+# Copy this file to ~/.libusb-driverrc if you want to use FTDI2232 cables
+# All parallel ports not defined in this file are mapped to real ports on the
+# system
+
+# Amontec Jtagkey
+LPT2 = FTDI:0403:cff8
diff --git a/misc/obsolete-ships/Alu1.ship b/misc/obsolete-ships/Alu1.ship
new file mode 100644 (file)
index 0000000..524fb8e
--- /dev/null
@@ -0,0 +1,119 @@
+ship: Alu1
+
+== Ports ===========================================================
+data  in:   in
+data  in:   inOp
+  constant NEG: 0
+  constant INC: 1
+  constant DEC: 2
+  constant ABS: 3
+
+data  out:  out
+
+== TeX ==============================================================
+
+{\tt Alu1} is a ``one-input'' arithmetic logic unit.  It includes
+logic for performing arithmetic operations on a single argument.
+Currently this includes
+negate ({\sc neg}),
+increment ({\sc inc}),
+decrement ({\sc dec}), and
+absolute value ({\sc abs}).
+
+\subsection*{Semantics}
+
+When a value is present at each of {\tt in} and {\tt inOp}, these two
+values are consumed.  Based on the value consumed at {\tt inOp}, the
+requested operation is performed on the value consumed from {\tt in}.
+The result of this operation is then made available at {\tt out}.
+
+== Fleeterpreter ====================================================
+    public void service() {
+        if (box_in.dataReadyForShip() && box_inOp.dataReadyForShip() && box_out.readyForDataFromShip()) {
+            long data   = box_in.removeDataForShip();
+            long opcode = box_inOp.removeDataForShip();
+            switch((int)opcode) {
+                case 0: box_out.addDataFromShip(-1 * data);      // NEG
+                    break;
+                case 1: box_out.addDataFromShip(data+1);         // INC
+                    break;
+                case 2: box_out.addDataFromShip(data-1);         // DEC
+                    break;
+                case 3: box_out.addDataFromShip(Math.abs(data)); // ABS
+                    break;
+                default: box_out.addDataFromShip(0);
+                    break;
+            }
+        }
+    }
+
+== FleetSim ==============================================================
+== FPGA ==============================================================
+
+  always @(posedge clk) begin
+    if (!rst) begin
+      `reset
+    end else begin
+      if (out_r    && out_a)    out_r    <= 0;
+      if (!in_r    && in_a)     in_a     <= 0;
+      if (!inOp_r  && inOp_a)   inOp_a   <= 0;
+      if (!out_r && !out_a && in_r && !in_a && inOp_r && !inOp_a) begin
+        out_r <= 1;
+        in_a <= 1;
+        inOp_a <= 1;
+        case (inOp_d)
+          0: out_d <= -in_d;
+          1: out_d <= in_d+1;
+          2: out_d <= in_d-1;
+          3: out_d <= (in_d<0) ? (-in_d) : in_d;
+          default: out_d <= 0;
+        endcase        
+      end
+    end
+  end
+
+== Test ==============================================================================
+// expected output
+
+#expect 10
+#expect 8
+#expect 9
+#expect -9
+#expect 9
+
+#ship debug        : Debug
+#ship alu1         : Alu1
+#ship fifo         : Fifo
+
+debug.in:
+  [*] take, deliver;
+
+alu1.in:
+  literal 9;
+  load repeat counter with 4;
+  deliver;
+  take, deliver;
+
+alu1.out:
+  load repeat counter with 4;
+  take, sendto debug.in;
+  sendto alu1.in;
+  take, sendto debug.in;
+
+alu1.inOp:
+  notify fifo.out;
+  [*] take, deliver, notify fifo.out;
+
+fifo.out:
+  [*] wait, take, sendto alu1.inOp;
+
+fifo.in:
+   literal 1; deliver;
+   literal 2; deliver;
+   literal 3; deliver;
+   literal 0; deliver;
+   literal 0; deliver;
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/misc/obsolete-ships/Alu3.ship b/misc/obsolete-ships/Alu3.ship
new file mode 100644 (file)
index 0000000..578d155
--- /dev/null
@@ -0,0 +1,360 @@
+ship: Alu3
+
+== Ports ===========================================================
+data  in:   in1
+data  in:   in2
+data  in:   in3
+
+data  out:  out1
+  shortcut to: in1
+data  out:  out2
+  shortcut to: in2
+data  out:  outBits
+
+== Constants ========================================================
+== TeX ==============================================================
+
+{\tt Alu3} is a three-input adder which produces a pair of outputs in
+carry-save form.  It has no opcode input.
+
+This ship also contains a private ``bit fifo'' similar to the {\tt
+BitFifo} ship, except that only the dequeueing (output) interface is
+exposed to the programmer.  Each addition operation performed causes
+the lowest bit of the {\it save} output to be enqueued into the bit
+fifo.  This can be used to produce a very efficient multiplier; see
+the test case for this ship for more details.
+
+\subsection*{Semantics}
+
+When a value is present at each of {\tt in1}, {\tt in2} and {\tt in3},
+these three values are consumed.  The {\it carry} result of carry-save
+addition is placed in {\tt out1}, and the {\it save} result of
+carry-save addition is placed in {\tt out2}.
+
+\subsection*{To Do}
+
+Is the second output supposed to be shifted?
+
+Provide a way to clear/flush the internal bitfifo.
+
+Do we even need this?  Can we do the same thing with {\tt Lut3} and
+{\tt BitFifo} together?
+
+
+== Fleeterpreter ====================================================
+static class BitStorage {
+  long[] bits;
+  int numbits = 0;
+  int start = 0;
+  BitStorage(int size) {
+    bits = new long[size / 64 + (size % 64 != 0 ? 1 : 0)];
+  }
+  int size() {
+    return numbits;
+  }
+  boolean hasSpace(int num) {
+    return bits.length * 64 - numbits >= num;
+  }
+  boolean peekTailBit() {
+    int entry = (((numbits-1) + start) / 64) % bits.length;
+    int off = ((numbits-1) + start) % 64;
+    int maxadd = 64 - off;
+    long mask = maxadd < 64 ? (-1L >>> maxadd) : 0L;
+    return (bits[entry] & ~mask) != 0;
+  }
+  boolean add(long data, int num) {
+    if (!hasSpace(num)) return false;
+    int entry = ((numbits + start) / 64) % bits.length;
+    int off = (numbits + start) % 64;
+    int maxadd = 64 - off;
+    long mask = maxadd < 64 ? (-1L >>> maxadd) : 0L;
+    bits[entry] = (bits[entry] & mask) | (data << off);
+    if (num > maxadd) {
+      numbits += maxadd;
+      return add(data >>> maxadd, num - maxadd);
+    } else {
+      numbits += num;
+      return true;
+    }
+  }
+  long get(int num) {
+    assert size() >= num : "too few bits in storage";
+    int entry = start / 64;
+    int off = start % 64;
+    int max = 64 - off;
+    int n = num > max ? max : num;
+    long mask = n > 0 ? (-1L >>> (64 - n)) : 0L;
+    long res = (bits[entry] >>> off) & mask;
+    int oldstart = start;
+    if (n < num) {
+      int n2 = num - n;
+      long mask2 = n2 > 0 ? (-1L >>> (64 - n2)) : 0L;
+      res |= (bits[(entry + 1) % bits.length] & mask2) << n;
+    }
+    start = (start + num) % (64 * bits.length);
+    numbits -= num;
+    return res;
+  }
+  int capacity() {
+    return 64 * bits.length;
+  }
+  // Test code for BitStorage
+  static void test3(String[] args) {
+      BitStorage bs = new BitStorage(37);
+      Random rand = new Random();
+      Vector ins = new Vector();
+      Vector ret = new Vector();
+      StringBuffer sbi = new StringBuffer();
+      StringBuffer sbr = new StringBuffer();
+      System.out.println("==== Test #3 ====");
+      System.out.println("inserting...");
+      long data = rand.nextLong();
+      bs.add(data, 0);
+      ins.add(new Integer(0));
+      data = rand.nextLong();
+      int num = rand.nextInt(37);
+      int s = bs.size();
+      bs.add(data, num);
+      assert bs.size() - s == num : "bad size: " + s + " + " + num + " != " + bs.size();
+      ins.add(new Integer(num));
+      add(sbi, data, num);
+      print(data, num);
+      System.out.println("\nretrieving...");
+      num = bs.size();
+      data = bs.get(num);
+      ret.add(new Integer(num));
+      add(sbr, data, num);
+      print(data, num);
+      System.out.println("\ninsertion sequence:");
+      for (int i = 0; i < ins.size(); i++) {
+         System.out.print(" " + ins.get(i));
+      }
+      System.out.println("\nretrieval sequence:");
+      for (int i = 0; i < ret.size(); i++) {
+         System.out.print(" " + ret.get(i));
+      }
+      System.out.println();
+      check(sbi, sbr);
+  }
+  static void test2(String[] args) {
+      int iters = (args.length > 0 ? Integer.parseInt(args[0]) : 10);
+      BitStorage bs = new BitStorage(37 * iters);
+      Random rand = new Random();
+      Vector ins = new Vector();
+      Vector ret = new Vector();
+      StringBuffer sbi = new StringBuffer();
+      StringBuffer sbr = new StringBuffer();
+      System.out.println("==== Test #2 ====");
+      for (int i = 0; i < iters; i++) {
+         long data = rand.nextLong();
+         int num = rand.nextInt(37);
+         int s = bs.size();
+         bs.add(data, num);
+         assert bs.size() - s == num : "bad size: " + s + " + " + num + " != " + bs.size();
+         ins.add(new Integer(num));
+         add(sbi, data, num);
+         num = rand.nextInt(Math.min(37, bs.size()));
+         s = bs.size();
+         data = bs.get(num);
+         assert s - bs.size() == num : "bad size: " + s + " - " + num + " != " + bs.size();
+         ret.add(new Integer(num));
+         add(sbr, data, num);
+      }
+      //for (int i = 0; i < iters; i++) {
+      while (bs.size() > 0) {
+         int num = Math.min(rand.nextInt(37), bs.size());
+         //int num = Math.min(33, bs.size());
+         int s = bs.size();
+         long data = bs.get(num);
+         assert s - bs.size() == num : "bad size: " + s + " - " + num + " != " + bs.size();
+         ret.add(new Integer(num));
+         add(sbr, data, num);
+      }
+      System.out.println("inserted:");
+      System.out.println(sbi);
+      System.out.println("retrieved:");
+      System.out.println(sbr);
+      System.out.println("insertion sequence:");
+      for (int i = 0; i < ins.size(); i++) {
+         System.out.print(" " + ins.get(i));
+      }
+      System.out.println("\nretrieval sequence:");
+      for (int i = 0; i < ret.size(); i++) {
+         System.out.print(" " + ret.get(i));
+      }
+      System.out.println();
+      check(sbi, sbr);
+  }
+  static void test1(String[] args) {
+      int iters = (args.length > 0 ? Integer.parseInt(args[0]) : 10);
+      BitStorage bs = new BitStorage(37 * iters);
+      Random rand = new Random();
+      Vector ins = new Vector();
+      Vector ret = new Vector();
+      StringBuffer sbi = new StringBuffer();
+      StringBuffer sbr = new StringBuffer();
+      System.out.println("==== Test #1 ====");
+      System.out.println("inserting...");
+      for (int i = 0; i < iters; i++) {
+         long data = rand.nextLong();
+         int num = rand.nextInt(37);
+         int s = bs.size();
+         bs.add(data, num);
+         assert bs.size() - s == num : "bad size: " + s + " + " + num + " != " + bs.size();
+         ins.add(new Integer(num));
+         add(sbi, data, num);
+         print(data, num);
+      }
+      System.out.println("\nretrieving...");
+      //for (int i = 0; i < iters; i++) {
+      while (bs.size() > 0) {
+         int num = Math.min(rand.nextInt(37), bs.size());
+         //int num = Math.min(33, bs.size());
+         int s = bs.size();
+         long data = bs.get(num);
+         assert s - bs.size() == num : "bad size: " + s + " - " + num + " != " + bs.size();
+         ret.add(new Integer(num));
+         add(sbr, data, num);
+         print(data, num);
+      }
+      System.out.println("\ninsertion sequence:");
+      for (int i = 0; i < ins.size(); i++) {
+         System.out.print(" " + ins.get(i));
+      }
+      System.out.println("\nretrieval sequence:");
+      for (int i = 0; i < ret.size(); i++) {
+         System.out.print(" " + ret.get(i));
+      }
+      System.out.println();
+      check(sbi, sbr);
+  }
+  static void print(long data, int num) {
+      for (int i = 0; i < num; i++) {
+         System.out.print((data >>> i) & 0x1);
+      }
+  }
+  static void add(StringBuffer sb, long data, int num) {
+      for (int i = 0; i < num; i++) {
+         sb.append((int) ((data >>> i) & 0x1));
+      }
+  }
+  static void check(StringBuffer sb1, StringBuffer sb2) {
+      int len = sb2.length();
+      if (len > sb1.length()) {
+         System.out.println("error: retrieval sequence is longer than insertion sequence");
+         len = sb1.length();
+      }
+      for (int i = 0; i < sb2.length(); i++) {
+         if (sb1.charAt(i) != sb2.charAt(i)) {
+             System.out.println("error: bit at position " + i + " does not match");
+         }
+      }
+  }
+}
+boolean mode = false;
+BitStorage outBits = new BitStorage(74);
+public void service() {
+  if (outBits.size() >= 37) {
+    if (box_outBits.readyForDataFromShip()) {
+        box_outBits.addDataFromShip(outBits.get(37));
+    }
+  } else
+  if (box_in1.dataReadyForShip() &&
+      box_in2.dataReadyForShip() &&
+      box_in3.dataReadyForShip() &&
+      outBits.hasSpace(1) &&
+      box_out1.readyForDataFromShip() &&
+      box_out2.readyForDataFromShip()) {
+      long v1 = box_in1.removeDataForShip();
+      long v2 = box_in2.removeDataForShip();
+      long v3 = box_in3.removeDataForShip();
+      long o1, o2, o3;
+      o1 = ((v1 & v2) | (v2 & v3) | (v1 & v3))/* << 1*/;
+      o2 = (v1 ^ v2 ^ v3) >> 1;
+      outBits.add((v1 ^ v2 ^ v3) & 0x1L, 1);
+      box_out1.addDataFromShip(o1);
+      box_out2.addDataFromShip(o2);
+  }
+}
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  reg [73:0] bitstorage;               initial bitstorage = 0;
+  reg [7:0] bitstorage_count;          initial bitstorage_count = 0;
+
+  always @(posedge clk) begin
+    if (!rst) begin
+      `reset
+      bitstorage       <= 0;
+      bitstorage_count <= 0;
+    end else begin
+      if (out1_r    && out1_a)    out1_r    <= 0;
+      if (out2_r    && out2_a)    out2_r    <= 0;
+      if (outBits_r && outBits_a) outBits_r <= 0;
+      if (!in1_r    && in1_a)     in1_a     <= 0;
+      if (!in2_r    && in2_a)     in2_a     <= 0;
+      if (!in3_r    && in3_a)     in3_a     <= 0;
+      if (!out1_r && !out2_r && !outBits_r && in1_r && in2_r && in3_r) begin
+          out1_d  <= { ((in1_d & in2_d)
+                      | (in2_d & in3_d)
+                      | (in1_d & in3_d)) };
+          out2_d  <= { 1'b0, (in1_d[(`DATAWIDTH-1):1] ^
+                              in2_d[(`DATAWIDTH-1):1] ^
+                              in3_d[(`DATAWIDTH-1):1]) };
+        if (bitstorage_count >= `DATAWIDTH-1) begin
+          outBits_d <= bitstorage[(`DATAWIDTH-1):0];
+          outBits_r <= 1;
+          bitstorage_count <= 0;
+          bitstorage       <= bitstorage >> `DATAWIDTH;
+        end
+        bitstorage[bitstorage_count] <= (in1_d[0] ^ in2_d[0] ^ in3_d[0]);
+        bitstorage_count             <= bitstorage_count+1;
+        out1_r <= 1;
+        out2_r <= 1;
+        in1_a  <= 1;
+        in2_a  <= 1;
+        in3_a  <= 1;
+      end
+    end
+  end
+
+
+
+== Test ========================================================================
+#skip
+#ship alu3    : Alu3
+#ship lut3    : Lut3
+#ship debug   : Debug
+#ship fifo    : Fifo
+#ship rotator : Rotator
+
+#expect 0
+#expect 2
+#expect 1
+
+// 0:  100100100111110000000
+// sel 011110100001001000000
+// 1:  111000101000011000011
+// r:  111000100110111000000
+
+alu3.in1:      literal 1; deliver;            load repeat counter with 36; deliver;
+alu3.in2:      literal 0; deliver; literal 1; load repeat counter with 36; deliver;
+alu3.in3:      literal 4; deliver;            load repeat counter with 36; deliver;
+
+alu3.out1:    take;       sendto debug.in; [*] take;
+alu3.out2:    take; wait; sendto debug.in; [*] take;
+alu3.outBits: take; wait; sendto debug.in;
+
+debug.in:
+  take, deliver;
+  notify alu3.out2;
+  take, deliver;
+  notify alu3.outBits;
+  take, deliver;
+
+
+== Contributors =========================================================
+Amir Kamil <kamil@cs.berkeley.edu>
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/misc/obsolete-ships/ArithmeticShip.java b/misc/obsolete-ships/ArithmeticShip.java
new file mode 100644 (file)
index 0000000..3335c26
--- /dev/null
@@ -0,0 +1,162 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+/*
+You should note the following:
+I haven't implemented all the link-out policies.
+You can give the SHIP a single cmd with up to four operations.  For
+example, "ADD ZERO 0 SUBTRACT SIGN 1 MAX MAX 0".  These will be done
+in left-to-right order.
+You can use any link-out policy with any operation, though some don't
+make much sense.
+*/
+
+/**
+ * @author Dominic Antonelli <dantonel@berkeley.edu>
+ */
+public class ArithmeticShip extends InterpreterShip {
+
+    private int link;
+
+    DataInbox A = new DataInbox(this, "A");
+    DataInbox B = new DataInbox(this, "B");
+    DataInbox cmd = new DataInbox(this, "cmd");
+    DataOutbox out = new DataOutbox(this, "out");
+
+    public ArithmeticShip(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public enum Operation {
+        // NOTE: NOP is not to be used, but rather simply prevents other ops from using opcode 0
+        // This is so that we can detect the "end" of a command - when the command is all zero
+        NOP       { int eval(int a, int b, int link) { System.out.println("ERROR: Arith_NOP\n"); return 0; } },
+        ADD       { int eval(int a, int b, int link) { return a + b + link;            } },
+        SUBTRACT  { int eval(int a, int b, int link) { return a - b + link;            } },
+        COPY_A    { int eval(int a, int b, int link) { return a + link;                } },
+        COPY_B    { int eval(int a, int b, int link) { return b + link;                } },
+        SELECT    { int eval(int a, int b, int link) { return ((link==1) ? b : a);     } },
+        NEGATE_A  { int eval(int a, int b, int link) { return -(a+link);               } },
+        NEGATE_B  { int eval(int a, int b, int link) { return -(b+link);               } },
+        ABS_A     { int eval(int a, int b, int link) { a+=link; return (a<0 ? -a : a); } },
+        ABS_B     { int eval(int a, int b, int link) { b+=link; return (b<0 ? -b : b); } },
+        MAX       { int eval(int a, int b, int link) { return (a>b ?  a : b) + link;   } },
+        MIN       { int eval(int a, int b, int link) { return (a<b ?  a : b) + link;   } },
+        INC_A     { int eval(int a, int b, int link) { return a+1+link;                } },
+        INC_B     { int eval(int a, int b, int link) { return b+1+link;                } },
+        RESERVED1 { int eval(int a, int b, int link) { System.out.println("ERROR: Arith_RESERVED0\n"); return 0; } },
+        RESERVED2 { int eval(int a, int b, int link) { System.out.println("ERROR: Arith_RESERVED1\n"); return 0; } };
+
+
+
+        // Do arithmetic op represented by this constant
+        abstract int eval(int a, int b, int link);
+        public static Operation convertInt( int i ) {
+            return values()[i];
+        }
+    }
+
+    public enum LinkOutPolicy {
+        LINK_IN, ZERO, CARRY, SIGN, OLD_SIGN, OVERFLOW, MAX, MIN;
+        public static LinkOutPolicy convertInt( int i ) {
+            return values()[i];
+        }
+    }
+
+    private long savedCommand = 0;
+
+    public void service() {
+        if (!out.readyForDataFromShip()) return;
+        if (!A.dataReadyForShip()) return;
+        if (!B.dataReadyForShip()) return;
+
+        long command;
+
+        if (savedCommand != 0) {
+            command = savedCommand;
+        } else if (!cmd.dataReadyForShip()) {
+            return;
+        } else {
+            command = cmd.removeDataForShip();
+        }
+
+        int inA = A.removeDataForShip();
+        int inB = B.removeDataForShip();
+        int linkInPolicy = (int)(command & 0x1);
+        LinkOutPolicy linkOutPolicy = LinkOutPolicy.convertInt((int)((command >> 1) & 0x7));
+        Operation op = Operation.convertInt((int)((command >> 4) & 0xf));
+        int result = 0;
+
+        int oldLink = link;
+        if (op == Operation.SELECT) {
+            link = link ^ linkInPolicy; // LinkInPolicy = 1 mean flip the selection for the SELECT op.
+        } else {
+            link = link & linkInPolicy; // If linkInPolicy is zero, unset the link bit for the upcoming computation.
+                                        // NOTE: The final value of link will be computed after eval.
+        }
+
+        result = op.eval(inA, inB, link);
+
+        switch (linkOutPolicy) {
+            case LINK_IN:
+                link = oldLink;
+                break;
+            case ZERO:
+                link = (result == 0) ? 1 : 0;
+//                link = 0;
+                break;
+            case SIGN:
+                link = (result >> 31) & 0x1;
+                break;
+            case MAX:
+                if (inA > inB) link = 1; else link = 0;
+                break;
+            case MIN:
+                if (inA < inB) link = 1; else link = 0;
+                break;
+            case CARRY:
+            case OLD_SIGN:
+            case OVERFLOW:
+                System.out.println("ERROR: non-implemented linkOutPolicy selected");
+                break;
+            default:
+                System.out.println("ERROR: Unknown linkOutPolicy selected");
+                break;
+        };
+        out.addDataFromShip(result);
+
+        savedCommand = command >> 8;
+
+//        System.out.println("Link is now " + link);
+    }
+
+    public int resolveShipSpecificConstant(String shipSpecificData) {
+        String[] data = shipSpecificData.split("\\s");
+        int result = 0;
+
+        if ((data.length % 3) != 0) {
+            System.out.println("ERROR: ArithmeticShip received invalid ShipSpecificConstant");
+        }
+        for (int i = data.length - 1; i >= 2; i-=3) {
+            result <<= 8;
+            if (data[i].equals("1")) {
+                result |= 1;
+            }
+            for (LinkOutPolicy policy : LinkOutPolicy.values()) {
+                if (data[i-1].equals(policy.toString())) {
+                    result |= (policy.ordinal() << 1);
+                }
+            }
+            for (Operation op : Operation.values()) {
+                if (data[i-2].equals(op.toString())) {
+                    result |= (op.ordinal() << 4);
+                }
+            }
+        }
+        return result;
+    }
+}
diff --git a/misc/obsolete-ships/Counter.java b/misc/obsolete-ships/Counter.java
new file mode 100644 (file)
index 0000000..921a2b3
--- /dev/null
@@ -0,0 +1,35 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class Counter extends InterpreterShip {
+
+    private int count = 0;
+
+    DataInbox   load      = new DataInbox(this, "load");
+    TokenInbox  decrement = new TokenInbox(this, "decrement");
+    TokenOutbox zero      = new TokenOutbox(this, "zero");
+
+    public Counter(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public String getBalsaName() { return "counter"; }
+    public void service() {
+        if (!zero.readyForTokenFromShip()) return;
+        if (count==0 && load.dataReadyForShip()) {
+            count = load.removeDataForShip();
+            return;
+        }
+        if (count>0 && decrement.tokenReadyForShip()) {
+            decrement.removeTokenForShip();
+            count--;
+            if (count==0)
+                zero.addTokenFromShip();
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/DDR2.ship b/misc/obsolete-ships/DDR2.ship
new file mode 100644 (file)
index 0000000..b594c87
--- /dev/null
@@ -0,0 +1,79 @@
+ship: DDR2
+
+== Ports ===========================================================
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+    public void service() { }
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  reg         ddr2_addr_r;
+  reg         ddr2_isread;
+  reg         ddr2_write_data_push;
+  reg         ddr2_read_data_pop;
+  reg  [`DATAWIDTH:0]  out_d;
+
+  assign ddr2_addr_r_ = ddr2_addr_r;
+  assign ddr2_isread_ = ddr2_isread;
+  assign ddr2_addr_ = !ddr2_isread ? inAddrWrite_d[31:0] : inAddrRead_d[31:0];
+  assign ddr2_write_data_push_ = ddr2_write_data_push;
+  assign ddr2_read_data_pop_ = ddr2_read_data_pop;
+  assign ddr2_write_data_ = { inDataWrite_d[31:5], inDataWrite_d[4], inDataWrite_d[35:0] };
+//  assign ddr2_write_data_ = inDataWrite_d[(`DATAWIDTH-1):0];
+  assign out_d_ = out_d;
+
+  always @(posedge clk) begin
+
+    if (!rst) begin
+      `reset
+      ddr2_isread <= 0;
+      ddr2_addr_r <= 0;
+      ddr2_read_data_pop <= 0;
+
+    end else begin
+      `flush
+
+      if (!inAddrRead_r_  && inAddrRead_a)  inAddrRead_a  <= 0;
+      if (!inDataWrite_r_ && inDataWrite_a) inDataWrite_a <= 0;
+      if (!inAddrWrite_r_ && inAddrWrite_a) inAddrWrite_a <= 0;
+      if ( out_r          && out_a)         out_r <= 0;
+
+      if (ddr2_addr_r && !ddr2_addr_a) begin
+         // busy
+      end else if (ddr2_addr_r &&  ddr2_addr_a && !ddr2_isread) begin
+          ddr2_addr_r <= 0;
+          inAddrWrite_a <= 1;
+          inDataWrite_a <= 1;
+          out_d <= { 1'b1, 37'b0 };
+          out_r <= 1;
+      end else if (ddr2_addr_r &&  ddr2_addr_a && ddr2_isread) begin
+          ddr2_addr_r <= 0;
+          inAddrRead_a <= 1;
+          out_d <= { 1'b0, ddr2_read_data[36:0] };
+          out_r <= 1;
+      end else if (!out_r && !out_a && inAddrWrite_r && !inAddrWrite_a && inDataWrite_r && !inDataWrite_a && !ddr2_addr_r && !ddr2_addr_a) begin
+          ddr2_addr_r <= 1;
+          ddr2_isread <= 0;
+      end else if (!out_r && !out_a && inAddrRead_r && !inAddrRead_a && !ddr2_addr_r && !ddr2_addr_a) begin
+          ddr2_addr_r <= 1;
+          ddr2_isread <= 1;
+      end
+    end
+  end
+
+
+== Test ========================================================
+#skip
+
+== Constants ========================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/misc/obsolete-ships/DeMux.java b/misc/obsolete-ships/DeMux.java
new file mode 100644 (file)
index 0000000..3006dd9
--- /dev/null
@@ -0,0 +1,34 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class DeMux extends InterpreterShip {
+
+    DataInbox   inp  = new DataInbox(this,  "in");
+    DataInbox   selp = new DataInbox(this,  "select");
+    DataOutbox  truep   = new DataOutbox(this, "true");
+    DataOutbox  falsep   = new DataOutbox(this, "false");
+
+    public String getBalsaName() { return "demux"; }
+
+    public DeMux (Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (inp.dataReadyForShip() && selp.dataReadyForShip() &&
+            truep.readyForDataFromShip() && falsep.readyForDataFromShip()) {
+            int in = inp.removeDataForShip();
+            int sel = selp.removeDataForShip();
+            if (sel==0)
+                falsep.addDataFromShip(in);
+            else
+                truep.addDataFromShip(in);
+        }
+    }
+
+}
+
diff --git a/misc/obsolete-ships/Dup.java b/misc/obsolete-ships/Dup.java
new file mode 100644 (file)
index 0000000..e78273a
--- /dev/null
@@ -0,0 +1,29 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class Dup extends InterpreterShip {
+
+    DataInbox   in  = new DataInbox(this, "in");
+    DataOutbox  a   = new DataOutbox(this, "a");
+    DataOutbox  b   = new DataOutbox(this, "b");
+
+    public String getBalsaName() { return "dup"; }
+
+    public Dup (Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (in.dataReadyForShip() && a.readyForDataFromShip() && b.readyForDataFromShip()) {
+            int data = in.removeDataForShip();
+            a.addDataFromShip(data);
+            b.addDataFromShip(data);
+        }
+    }
+
+}
+
diff --git a/misc/obsolete-ships/Dup3.java b/misc/obsolete-ships/Dup3.java
new file mode 100644 (file)
index 0000000..1820970
--- /dev/null
@@ -0,0 +1,31 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class Dup3 extends InterpreterShip {
+
+    DataInbox   in  = new DataInbox(this, "in");
+    DataOutbox  a   = new DataOutbox(this, "a");
+    DataOutbox  b   = new DataOutbox(this, "b");
+    DataOutbox  c   = new DataOutbox(this, "c");
+
+    public String getBalsaName() { return "dup3"; }
+
+    public Dup3 (Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (in.dataReadyForShip() && a.readyForDataFromShip() && b.readyForDataFromShip() && c.readyForDataFromShip()) {
+            int data = in.removeDataForShip();
+            a.addDataFromShip(data);
+            b.addDataFromShip(data);
+            c.addDataFromShip(data);
+        }
+    }
+
+}
+
diff --git a/misc/obsolete-ships/DuplicatorShip.java b/misc/obsolete-ships/DuplicatorShip.java
new file mode 100644 (file)
index 0000000..70d3e5e
--- /dev/null
@@ -0,0 +1,36 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * @author Dominic Antonelli <dantonel@berkeley.edu>
+ */
+public class DuplicatorShip extends InterpreterShip {
+
+    DataInbox   in  = new DataInbox(this, "in");
+    DataOutbox  out0 = new DataOutbox(this, "out0");
+    DataOutbox  out1 = new DataOutbox(this, "out1");
+    DataOutbox  out2 = new DataOutbox(this, "out2");
+    DataOutbox  out3 = new DataOutbox(this, "out3");
+
+    public DuplicatorShip (Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (in.dataReadyForShip()       && out0.readyForDataFromShip() && 
+            out1.readyForDataFromShip() && out2.readyForDataFromShip() &&
+            out3.readyForDataFromShip()) {
+            int data = in.removeDataForShip();
+            out0.addDataFromShip(data);
+            out1.addDataFromShip(data);
+            out2.addDataFromShip(data);
+            out3.addDataFromShip(data);
+        }
+    }
+
+}
+
diff --git a/misc/obsolete-ships/HomeworkCounter.java b/misc/obsolete-ships/HomeworkCounter.java
new file mode 100644 (file)
index 0000000..0aa8be8
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class HomeworkCounter extends InterpreterShip {
+
+    private int count = -1;
+
+    TokenOutbox zero     = new TokenOutbox(this, "zero");
+    TokenOutbox positive = new TokenOutbox(this, "positive");
+    DataInbox    load     = new DataInbox(this, "load");
+    TokenInbox  ask      = new TokenInbox(this, "ask");
+
+    public HomeworkCounter(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (!zero.readyForTokenFromShip()) return;
+        if (!positive.readyForTokenFromShip()) return;
+        if (load.dataReadyForShip()) {
+            count = load.removeDataForShip();
+            return;
+        }
+        if (ask.tokenReadyForShip()) {
+            ask.removeTokenForShip();
+            if (count > 0) {
+                count--;
+                positive.addTokenFromShip();
+            } else if (count<=0) {
+                zero.addTokenFromShip();
+            }
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/MemoryReadShip.java b/misc/obsolete-ships/MemoryReadShip.java
new file mode 100644 (file)
index 0000000..ffe4511
--- /dev/null
@@ -0,0 +1,47 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+
+import edu.berkeley.fleet.*;
+import java.util.*;
+import java.io.*;
+
+public class MemoryReadShip extends InterpreterShip {
+
+    boolean _loaded = false;
+    int _count = 0;
+    int _stride = 0;
+    int _addr = 0;
+
+    DataInbox  addr   = new DataInbox(this, "addr");
+    DataInbox  stride = new DataInbox(this, "stride");
+    DataInbox  count  = new DataInbox(this, "count");
+    DataOutbox data   = new DataOutbox(this, "data");
+    TokenOutbox done  = new TokenOutbox(this, "done");
+
+    public MemoryReadShip(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (_count > 0) {
+            if (!data.readyForDataFromShip()) return;
+            data.addDataFromShip(_addr>=getInterpreter().mem.length ? 0 : getInterpreter().mem[_addr]);
+            _count--;
+            _addr += _stride;
+            if (_count==0)
+                done.addTokenFromShip();
+        } else {
+            if (count.dataReadyForShip() &&
+                addr.dataReadyForShip() &&
+                stride.dataReadyForShip() &&
+                done.readyForTokenFromShip() &&
+                data.readyForDataFromShip()) {
+
+                _count  = count.removeDataForShip();
+                _addr   = addr.removeDataForShip();
+                _stride = stride.removeDataForShip();
+            }
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/MemoryWriteShip.java b/misc/obsolete-ships/MemoryWriteShip.java
new file mode 100644 (file)
index 0000000..7e33936
--- /dev/null
@@ -0,0 +1,49 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+
+import edu.berkeley.fleet.*;
+import java.util.*;
+import java.io.*;
+
+/**
+ *  @author Thomas Kho <tkho@eecs.berkeley.edu>
+ */
+public class MemoryWriteShip extends InterpreterShip {
+
+    int _count = 0;
+    int _stride = 0;
+    int _addr = 0;
+
+    DataInbox  addr   = new DataInbox(this, "addr");
+    DataInbox  stride = new DataInbox(this, "stride");
+    DataInbox  count  = new DataInbox(this, "count");
+    DataInbox  data   = new DataInbox(this, "data");
+    TokenOutbox done  = new TokenOutbox(this, "done");
+
+    public MemoryWriteShip(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (_count > 0) {
+            if (!data.dataReadyForShip()) return;
+            //getInterpreter().writeMem(_addr, data.removeDataForShip());
+            _count--;
+            _addr += _stride;
+            if (_count==0)
+                done.addTokenFromShip();
+        } else {
+            if (count.dataReadyForShip() &&
+                addr.dataReadyForShip() &&
+                stride.dataReadyForShip() &&
+                done.readyForTokenFromShip() &&
+                data.dataReadyForShip()) {
+
+                _count  = count.removeDataForShip();
+                _addr   = addr.removeDataForShip();
+                _stride = stride.removeDataForShip();
+            }
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/MultiplierShip.java b/misc/obsolete-ships/MultiplierShip.java
new file mode 100644 (file)
index 0000000..3efd5da
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * @author Dominic Antonelli <dantonel@berkeley.edu>
+ */
+public class MultiplierShip extends InterpreterShip {
+
+    private int link;
+
+    DataInbox A = new DataInbox(this, "A");
+    DataInbox B = new DataInbox(this, "B");
+    DataOutbox out0 = new DataOutbox(this, "out0");
+    DataOutbox out1 = new DataOutbox(this, "out1");
+
+    public MultiplierShip(Interpreter fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (!out0.readyForDataFromShip()) return;
+        if (!out1.readyForDataFromShip()) return;
+        if (!A.dataReadyForShip()) return;
+        if (!B.dataReadyForShip()) return;
+
+        long inA = (long)A.removeDataForShip();
+        long inB = (long)B.removeDataForShip();
+        long result = inA * inB;
+        int result0 = (int)(result >> 32);
+        int result1 = (int)(result & 0xffffffff);
+
+        out0.addDataFromShip(result0);
+        out1.addDataFromShip(result1);
+    }
+}
diff --git a/misc/obsolete-ships/Mux.java b/misc/obsolete-ships/Mux.java
new file mode 100644 (file)
index 0000000..86a2822
--- /dev/null
@@ -0,0 +1,28 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class Mux extends InterpreterShip {
+
+    DataInbox   ap      = new DataInbox(this,  "a");
+    DataInbox   bp      = new DataInbox(this,  "b");
+    DataInbox   choicep = new DataInbox(this, "select");
+    DataOutbox  out     = new DataOutbox(this, "out");
+
+    public Mux(Interpreter fleet, String name) { super(fleet, name); }
+
+    public String getBalsaName() { return "mux"; }
+
+    public void service() {
+        if (ap.dataReadyForShip() && bp.dataReadyForShip() && choicep.dataReadyForShip()) {
+            int a      = ap.removeDataForShip();
+            int b      = bp.removeDataForShip();
+            int choice = choicep.removeDataForShip();
+            out.addDataFromShip(choice==0 ? a : b);
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/ScatterShip.java b/misc/obsolete-ships/ScatterShip.java
new file mode 100644 (file)
index 0000000..4f6b892
--- /dev/null
@@ -0,0 +1,44 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * @author Dominic Antonelli <dantonel@berkeley.edu>
+ */
+public class ScatterShip extends InterpreterShip {
+
+    DataInbox   in  = new DataInbox(this, "in");
+    Vector<DataOutbox> out = new Vector<DataOutbox>();
+
+    private int size = 2;
+    private int state = 0;
+
+    public ScatterShip(Interpreter fleet, String name) {
+        super(fleet, name);
+        init();
+    }
+
+    private boolean initialized = false;
+    private void init() {
+        for (int i = 0; i < size; i++) {
+            out.add(new DataOutbox(this, "out" + i));
+        }
+        initialized = true;
+    }
+
+    public void service() {
+        if (!initialized) init();
+        if (in.dataReadyForShip() && out.get(state).readyForDataFromShip()) {
+            out.get(state).addDataFromShip(in.removeDataForShip());
+            state = (state + 1) % size;
+        }
+    }
+
+    public int resolveShipSpecificConstant(String shipSpecificData) {
+        return 0;
+    }
+
+}
diff --git a/misc/obsolete-ships/Sort2.java b/misc/obsolete-ships/Sort2.java
new file mode 100644 (file)
index 0000000..90cb3e4
--- /dev/null
@@ -0,0 +1,28 @@
+package edu.berkeley.fleet.interpreter.ships;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class Sort2 extends InterpreterShip {
+
+    DataInbox   ap  = new DataInbox(this,  "a");
+    DataInbox   bp  = new DataInbox(this,  "b");
+    DataOutbox  min = new DataOutbox(this, "min");
+    DataOutbox  max = new DataOutbox(this, "max");
+
+    public Sort2(Interpreter fleet, String name) { super(fleet, name); }
+
+    public String getBalsaName() { return "sort2"; }
+
+    public void service() {
+        if (ap.dataReadyForShip() && bp.dataReadyForShip()) {
+            int a      = ap.removeDataForShip();
+            int b      = bp.removeDataForShip();
+            max.addDataFromShip(Math.max(a,b));
+            min.addDataFromShip(Math.min(a,b));
+        }
+    }
+
+}
diff --git a/misc/obsolete-ships/Stack.ship b/misc/obsolete-ships/Stack.ship
new file mode 100644 (file)
index 0000000..bd639ff
--- /dev/null
@@ -0,0 +1,108 @@
+ship: Stack
+
+== Ports ===========================================================
+data  in:   push
+data  out:  pop
+
+== Constants ========================================================
+
+== TeX ==============================================================
+A stack ship with capacity for at least 16 elements.
+
+Push operations are executed as soon as an inbound datum is delivered
+to the {\tt push} port.  Completion of a push can be confirmed by
+sending a token from the {\tt push} port after {\tt deliver}ing.
+
+Pop operations are executed no earlier than the time at which the {\tt
+pop} port attempts to {\tt take} data from the ship.
+
+When the stack becomes full, it will simply not process any new {\tt
+push} operations.  When the stack becomes empty, it will simply not
+process any new {\tt pop} operations.  Phrased another way, if a {\tt
+pop} is issued to an empty stack, that operation will wait for a {\tt
+push} to occur; at some point after that, the {\tt pop} will proceed
+to pop the pushed value.  There is no ``underflow'' or ``overflow.''
+
+\subsection*{To Do}
+
+There is some difficulty here when it comes to arbitration -- does the
+execution of the instruction after the {\tt deliver} to the {\tt push}
+port indicate that the value has been safely pushed?  This is much
+tricker than it seems.
+
+Perhaps there should be a single port, {\tt operation}, to which
+either a {\sc PUSH} or {\sc POP} command is sent.  This would simplify
+the arbitration issues.
+
+== Fleeterpreter ====================================================
+    private ArrayList<Long> stack = new ArrayList<Long>();
+    public void service() {
+        if (box_push.dataReadyForShip() && stack.size()<32) {
+            stack.add(box_push.removeDataForShip());
+        }
+        if (box_pop.readyForDataFromShip() && stack.size() > 0) {
+            box_pop.addDataFromShip(stack.get(stack.size()-1));
+            stack.remove(stack.size()-1);
+        }
+    }
+
+== FleetSim ==============================================================
+== FPGA ==============================================================
+/* FIXME: inefficient */
+  reg    [(`DATAWIDTH-1):0] mem [4:0];
+  reg    [5:0]              depth;
+  reg    skip;
+  initial depth = 0;
+
+  always @(posedge clk or negedge rst) begin
+    if (!rst) depth <= 0;
+    else begin
+    skip = 0;
+    if (depth > 0) begin
+      `onwrite(pop_r, pop_a)
+        if (depth > 1) begin
+          pop_d <= mem[depth-2];
+        end
+        depth <= depth - 1;
+        skip = 1;
+      end
+    end
+    if (!skip && depth < 32) begin
+      `onread(push_r, push_a)
+        pop_d      <= push_d;
+        mem[depth] <= push_d;
+        depth      <= depth + 1;
+      end
+    end
+    end
+  end
+
+
+== Test ====================================================
+#skip
+#ship stack : Stack
+#ship stack : Debug
+
+#expect 4
+#expect 3
+#expect 2
+#expect 1
+#expect 0
+
+debug.in:  [*] take, deliver;
+
+stack.pop: wait; [*] take, sendto debug.in;
+
+stack.push:
+  literal 0; deliver;
+  literal 1; deliver;
+  literal 2; deliver;
+  literal 3; deliver;
+  literal 4; deliver;
+  notify stack.pop;
+
+
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/misc/parport.c b/misc/parport.c
new file mode 100644 (file)
index 0000000..57ab083
--- /dev/null
@@ -0,0 +1,168 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/parport.h>
+#include <linux/ppdev.h>
+#include "usb-driver.h"
+#include "parport.h"
+
+static int parportfd = -1;
+
+int parport_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num) {
+       int ret = 0;
+       int i;
+       unsigned long port;
+       unsigned char val;
+       static unsigned char last_pp_write = 0;
+
+       for (i = 0; i < num; i++) {
+               DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
+                               (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
+                               tr[i].fAutoinc, tr[i].dwOptions);
+
+               port = (unsigned long)tr[i].dwPort;
+               val = tr[i].Data.Byte;
+
+#ifdef DEBUG
+               if (tr[i].cmdTrans == 13)
+                       DPRINTF("write byte: %d\n", val);
+#endif
+
+               if (parportfd < 0)
+                       return ret;
+
+               if (port == ppbase + PP_DATA) {
+                       DPRINTF("data port\n");
+                       switch(tr[i].cmdTrans) {
+                               case PP_READ:
+                                       ret = 0; /* We don't support reading of the data port */
+                                       break;
+
+                               case PP_WRITE:
+                                       ret = ioctl(parportfd, PPWDATA, &val);
+                                       last_pp_write = val;
+                                       break;
+
+                               default:
+                                       fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
+                                       ret = -1;
+                                       break;
+                       }
+               } else if (port == ppbase + PP_STATUS) {
+                       DPRINTF("status port (last write: %d)\n", last_pp_write);
+                       switch(tr[i].cmdTrans) {
+                               case PP_READ:
+                                       ret = ioctl(parportfd, PPRSTATUS, &val);
+#ifdef FORCE_PC3_IDENT
+                                       val &= 0x5f;
+                                       if (last_pp_write & 0x40)
+                                               val |= 0x20;
+                                       else
+                                               val |= 0x80;
+#endif
+                                       break;
+
+                               case PP_WRITE:
+                                       ret = 0; /* Status Port is readonly */
+                                       break;
+
+                               default:
+                                       fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
+                                       ret = -1;
+                                       break;
+                       }
+               } else if (port == ppbase + PP_CONTROL) {
+                       DPRINTF("control port\n");
+                       switch(tr[i].cmdTrans) {
+                               case PP_READ:
+                                       ret = ioctl(parportfd, PPRCONTROL, &val);
+                                       break;
+
+                               case PP_WRITE:
+                                       ret = ioctl(parportfd, PPWCONTROL, &val);
+                                       break;
+
+                               default:
+                                       fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
+                                       ret = -1;
+                                       break;
+                       }
+               } else if ((port == ecpbase + PP_ECP_CFGA) && ecpbase) {
+                       DPRINTF("ECP_CFGA port\n");
+               } else if ((port == ecpbase + PP_ECP_CFGB) && ecpbase) {
+                       DPRINTF("ECP_CFGB port\n");
+               } else if ((port == ecpbase + PP_ECP_ECR) && ecpbase) {
+                       DPRINTF("ECP_ECR port\n");
+               } else {
+                       DPRINTF("access to unsupported address range!\n");
+                       ret = 0;
+               }
+
+               tr[i].Data.Byte = val;
+
+               DPRINTF("dwPortReturn: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
+                               (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
+                               tr[i].fAutoinc, tr[i].dwOptions);
+#ifdef DEBUG
+               if (tr[i].cmdTrans == 10)
+                       DPRINTF("read byte: %d\n", tr[i].Data.Byte);
+#endif
+       }
+
+       return ret;
+}
+
+int parport_open(int num) {
+       char ppdev[32];
+
+       if (parportfd < 0) {
+               snprintf(ppdev, sizeof(ppdev), "/dev/parport%u", num);
+               DPRINTF("opening %s\n", ppdev);
+               parportfd = open(ppdev, O_RDWR|O_EXCL);
+
+               if (parportfd < 0)
+                       fprintf(stderr,"Can't open %s: %s\n", ppdev, strerror(errno));
+       }
+
+       if (parportfd >= 0) {
+               int pmode;
+
+               if (ioctl(parportfd, PPCLAIM) == -1)
+                       return -1;
+
+               pmode = IEEE1284_MODE_COMPAT;
+               if (ioctl(parportfd, PPNEGOT, &pmode) == -1)
+                       return -1;
+
+#if 0
+               if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr) {
+                       DPRINTF("ECP mode requested\n");
+                       ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr;
+                       /* TODO: Implement ECP mode */
+                       pmode = IEEE1284_MODE_ECP;
+
+                       if (ioctl(parportfd, PPNEGOT, &pmode) == -1) {
+                               ecpbase = 0;
+                               pmode = IEEE1284_MODE_COMPAT;
+                               if (ioctl(parportfd, PPNEGOT, &pmode) == -1)
+                                       return ret;
+                       }
+               }
+#endif
+       }
+
+       return parportfd;
+}
+
+void parport_close(int handle) {
+       if (parportfd == handle && parportfd >= 0) {
+               ioctl(parportfd, PPRELEASE);
+               close(parportfd);
+               parportfd = -1;
+       }
+}
diff --git a/misc/parport.h b/misc/parport.h
new file mode 100644 (file)
index 0000000..ee46098
--- /dev/null
@@ -0,0 +1,3 @@
+int parport_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num);
+int parport_open(int num);
+void parport_close(int handle);
diff --git a/misc/program.sh b/misc/program.sh
new file mode 100755 (executable)
index 0000000..588b9f5
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+export XILINX=/usr/local/xilinx/ise/
+
+
+DEVICE=`lsusb | grep Xilinx | sed 's_Bus __' | sed 's_ Device _/_' | sed 's_:.*__'`
+
+sudo sh -c 'cat > /etc/udev/rules.d/xusbdfwu.rules' <<EOF
+# version 0002
+SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="0008", MODE="666"
+BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="0007", RUN+="/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusbdfwu.hex -D $TEMPNODE"
+BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="0009", RUN+="/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusb_xup.hex -D $TEMPNODE"
+BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="000d", RUN+="/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusb_emb.hex -D $TEMPNODE"
+BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="000f", RUN+="/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusb_xlp.hex -D $TEMPNODE"
+BUS=="usb", ACTION=="add", SYSFS{idVendor}=="03fd", SYSFS{idProduct}=="0013", RUN+="/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusb_xpr.hex -D $TEMPNODE"
+EOF
+
+(lsusb | grep '000f Xilinx') && \
+ (/sbin/fxload -v -t fx2 -I $XILINX/bin/lin/xusb_xlp.hex -D /proc/bus/usb/$DEVICE;\
+  sudo /etc/init.d/udev stop;\
+  sudo /etc/init.d/udev start)
+
+export BITFILE=$1
+
+sudo rmmod xpc4drvr
+sudo rmmod windrvr6
+#sudo insmod /lib/modules/2.6.22.9goliath/kernel/drivers/misc/xpc4drvr.ko
+#sudo insmod /lib/modules/2.6.22.9goliath/kernel/drivers/misc/windrvr6.ko
+#DEVNUM=`grep windrvr /proc/devices | sed 's_ .*__'`
+#sudo rm -f /dev/windrvr6
+#sudo mknod /dev/windrvr6 c $DEVNUM 0
+
+export LD_PRELOAD=`pwd`/misc/libusb-driver.so
+
+sudo ln -sf $XILINX/bin/lin/xusbdfwu.hex /usr/share/xusbdfwu.hex
+
+# ml410: use -p 2
+# ml505: use -p 5
+
+$XILINX/bin/lin/impact -batch <<EOF
+cleancablelock
+setMode -bs
+setCable -port usb21 -baud 12000000
+identify
+setMode -bs
+assignFile -p 5 -file $BITFILE
+program -p 5
+quit
+EOF
+
+sudo rm _impact*
+sudo rm /usr/share/xusbdfwu.hex
+#rm /etc/udev/rules.d/xusbdfwu.rules
diff --git a/misc/usb-driver.c b/misc/usb-driver.c
new file mode 100644 (file)
index 0000000..34fa02c
--- /dev/null
@@ -0,0 +1,939 @@
+/* libusb/ppdev connector for XILINX impact
+ *
+ * Copyright (c) 2007 Michael Gernoth <michael@gernoth.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#define _GNU_SOURCE 1
+
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <usb.h>
+#include <signal.h>
+#include <pthread.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include "usb-driver.h"
+#include "config.h"
+
+static int (*ioctl_func) (int, int, void *) = NULL;
+static int windrvrfd = -1;
+static unsigned long ppbase = 0;
+static unsigned long ecpbase = 0;
+static struct parport_config *pport = NULL;
+static FILE *modulesfp = NULL;
+static FILE *baseaddrfp = NULL;
+static int baseaddrnum = 0;
+static int modules_read = 0;
+static struct usb_bus *busses = NULL;
+static struct usb_device *usbdevice;
+static usb_dev_handle *usb_devhandle = NULL;
+static int usbinterface = -1;
+static unsigned long card_type;
+static int ints_enabled = 0;
+static pthread_mutex_t int_wait = PTHREAD_MUTEX_INITIALIZER;
+
+#define NO_WINDRVR 1
+
+void hexdump(unsigned char *buf, int len) {
+       int i;
+
+       for(i=0; i<len; i++) {
+               fprintf(stderr,"%02x ", buf[i]);
+               if ((i % 16) == 15)
+                       fprintf(stderr,"\n");
+       }
+       fprintf(stderr,"\n");
+}
+
+static int usb_deviceinfo(unsigned char *buf) {
+       int i,j,k,l;
+       int len = 0;
+       WDU_CONFIGURATION **pConfigs, **pActiveConfig;
+       WDU_INTERFACE **pActiveInterface;
+
+       if (buf) {
+               struct usb_device_info *udi = (struct usb_device_info*)(buf+len);
+
+               udi->Descriptor.bLength = sizeof(WDU_DEVICE_DESCRIPTOR);
+               udi->Descriptor.bDescriptorType = usbdevice->descriptor.bDescriptorType;
+               udi->Descriptor.bcdUSB = usbdevice->descriptor.bcdUSB;
+               udi->Descriptor.bDeviceClass = usbdevice->descriptor.bDeviceClass;
+               udi->Descriptor.bDeviceSubClass = usbdevice->descriptor.bDeviceSubClass;
+               udi->Descriptor.bDeviceProtocol = usbdevice->descriptor.bDeviceProtocol;
+               udi->Descriptor.bMaxPacketSize0 = usbdevice->descriptor.bMaxPacketSize0;
+               udi->Descriptor.idVendor = usbdevice->descriptor.idVendor;
+               udi->Descriptor.idProduct = usbdevice->descriptor.idProduct;
+               udi->Descriptor.bcdDevice = usbdevice->descriptor.bcdDevice;
+               udi->Descriptor.iManufacturer = usbdevice->descriptor.iManufacturer;
+               udi->Descriptor.iProduct = usbdevice->descriptor.iProduct;
+               udi->Descriptor.iSerialNumber = usbdevice->descriptor.iSerialNumber;
+               udi->Descriptor.bNumConfigurations = usbdevice->descriptor.bNumConfigurations;
+
+               /* TODO: Fix Pipe0! */
+               udi->Pipe0.dwNumber = 0x00;
+               udi->Pipe0.dwMaximumPacketSize = usbdevice->descriptor.bMaxPacketSize0;
+               udi->Pipe0.type = 0;
+               udi->Pipe0.direction = WDU_DIR_IN_OUT;
+               udi->Pipe0.dwInterval = 0;
+
+               pConfigs = &(udi->pConfigs);
+               pActiveConfig = &(udi->pActiveConfig);
+               pActiveInterface = &(udi->pActiveInterface[0]);
+       }
+
+       len = sizeof(struct usb_device_info);
+
+       for (i=0; i<usbdevice->descriptor.bNumConfigurations; i++)
+       {
+               struct usb_config_descriptor *conf_desc = &usbdevice->config[i];
+               WDU_INTERFACE **pInterfaces;
+               WDU_ALTERNATE_SETTING **pAlternateSettings[conf_desc->bNumInterfaces];
+               WDU_ALTERNATE_SETTING **pActiveAltSetting[conf_desc->bNumInterfaces];
+
+               if (buf) {
+                       WDU_CONFIGURATION *cfg = (WDU_CONFIGURATION*)(buf+len);
+
+                       *pConfigs = cfg;
+                       *pActiveConfig = cfg;
+
+                       cfg->Descriptor.bLength = conf_desc->bLength;
+                       cfg->Descriptor.bDescriptorType = conf_desc->bDescriptorType;
+                       cfg->Descriptor.wTotalLength = conf_desc->wTotalLength;
+                       cfg->Descriptor.bNumInterfaces = conf_desc->bNumInterfaces;
+                       cfg->Descriptor.bConfigurationValue = conf_desc->bConfigurationValue;
+                       cfg->Descriptor.iConfiguration = conf_desc->iConfiguration;
+                       cfg->Descriptor.bmAttributes = conf_desc->bmAttributes;
+                       cfg->Descriptor.MaxPower = conf_desc->MaxPower;
+
+                       cfg->dwNumInterfaces = conf_desc->bNumInterfaces;
+
+                       pInterfaces = &(cfg->pInterfaces);
+               }
+               len += sizeof(WDU_CONFIGURATION);
+
+               if (buf) {
+                       *pInterfaces = (WDU_INTERFACE*)(buf+len);
+                       for (j=0; j<conf_desc->bNumInterfaces; j++) {
+                               WDU_INTERFACE *iface = (WDU_INTERFACE*)(buf+len);
+
+                               pActiveInterface[j] = iface;
+
+                               pAlternateSettings[j] = &(iface->pAlternateSettings);
+                               iface->dwNumAltSettings = usbdevice->config[i].interface[j].num_altsetting;
+                               pActiveAltSetting[j] = &(iface->pActiveAltSetting);
+
+                               len += sizeof(WDU_INTERFACE);
+                       }
+               } else {
+                       len += sizeof(WDU_INTERFACE) * conf_desc->bNumInterfaces;
+               }
+
+               for (j=0; j<conf_desc->bNumInterfaces; j++)
+               {
+                       struct usb_interface *interface = &usbdevice->config[i].interface[j];
+
+                       if (buf) {
+                               *pAlternateSettings[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
+                               /* FIXME: */
+                               *pActiveAltSetting[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
+                       }
+
+                       for(k=0; k<interface->num_altsetting; k++)
+                       {
+                               unsigned char bNumEndpoints = interface->altsetting[k].bNumEndpoints;
+                               WDU_ENDPOINT_DESCRIPTOR **pEndpointDescriptors;
+                               WDU_PIPE_INFO **pPipes;
+
+                               if (buf) {
+                                       WDU_ALTERNATE_SETTING *altset = (WDU_ALTERNATE_SETTING*)(buf+len);
+
+                                       altset->Descriptor.bLength = interface->altsetting[k].bLength;
+                                       altset->Descriptor.bDescriptorType = interface->altsetting[k].bDescriptorType;
+                                       altset->Descriptor.bInterfaceNumber = interface->altsetting[k].bInterfaceNumber;
+                                       altset->Descriptor.bAlternateSetting = interface->altsetting[k].bAlternateSetting;
+                                       altset->Descriptor.bNumEndpoints = interface->altsetting[k].bNumEndpoints;
+                                       altset->Descriptor.bInterfaceClass = interface->altsetting[k].bInterfaceClass;
+                                       altset->Descriptor.bInterfaceSubClass = interface->altsetting[k].bInterfaceSubClass;
+                                       altset->Descriptor.bInterfaceProtocol = interface->altsetting[k].bInterfaceProtocol;
+                                       altset->Descriptor.iInterface = interface->altsetting[k].iInterface;
+                                       pEndpointDescriptors = &(altset->pEndpointDescriptors);
+                                       pPipes = &(altset->pPipes);
+
+                               }
+                               len +=sizeof(WDU_ALTERNATE_SETTING);
+
+                               if (buf) {
+                                       *pEndpointDescriptors = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
+                                       for (l = 0; l < bNumEndpoints; l++) {
+                                               WDU_ENDPOINT_DESCRIPTOR *ed = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
+
+                                               ed->bLength = interface->altsetting[k].endpoint[l].bLength;
+                                               ed->bDescriptorType = interface->altsetting[k].endpoint[l].bDescriptorType;
+                                               ed->bEndpointAddress = interface->altsetting[k].endpoint[l].bEndpointAddress;
+                                               ed->bmAttributes = interface->altsetting[k].endpoint[l].bmAttributes;
+                                               ed->wMaxPacketSize = interface->altsetting[k].endpoint[l].wMaxPacketSize;
+                                               ed->bInterval = interface->altsetting[k].endpoint[l].bInterval;
+
+                                               len += sizeof(WDU_ENDPOINT_DESCRIPTOR);
+                                       }
+                                               
+                                       *pPipes = (WDU_PIPE_INFO*)(buf+len);
+                                       for (l = 0; l < bNumEndpoints; l++) {
+                                               WDU_PIPE_INFO *pi = (WDU_PIPE_INFO*)(buf+len);
+
+                                               pi->dwNumber = interface->altsetting[k].endpoint[l].bEndpointAddress;
+                                               pi->dwMaximumPacketSize = WDU_GET_MAX_PACKET_SIZE(interface->altsetting[k].endpoint[l].wMaxPacketSize);
+                                               pi->type = interface->altsetting[k].endpoint[l].bmAttributes & USB_ENDPOINT_TYPE_MASK;
+                                               if (pi->type == PIPE_TYPE_CONTROL)
+                                                       pi->direction = WDU_DIR_IN_OUT;
+                                               else
+                                               {
+                                                       pi->direction = interface->altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK ?  WDU_DIR_IN : WDU_DIR_OUT;
+                                               }
+
+                                               pi->dwInterval = interface->altsetting[k].endpoint[l].bInterval;
+
+                                               len += sizeof(WDU_PIPE_INFO);
+                                       }
+                               } else {
+                                       len +=(sizeof(WDU_ENDPOINT_DESCRIPTOR)+sizeof(WDU_PIPE_INFO))*bNumEndpoints;
+                               }
+                       }
+               }
+       }
+
+       return len;
+}
+
+static int do_wdioctl(int fd, unsigned int request, unsigned char *wdioctl) {
+       struct header_struct* wdheader = (struct header_struct*)wdioctl;
+       struct version_struct *version;
+       int ret = 0;
+
+       if (wdheader->magic != MAGIC) {
+               fprintf(stderr,"!!!ERROR: magic header does not match!!!\n");
+               return (*ioctl_func) (fd, request, wdioctl);
+       }
+
+       switch(request & ~(0xc0000000)) {
+               case VERSION:
+                       version = (struct version_struct*)(wdheader->data);
+                       strcpy(version->version, "libusb-driver.so version: " USB_DRIVER_VERSION);
+                       version->versionul = 802;
+                       DPRINTF("VERSION\n");
+                       break;
+
+               case LICENSE:
+                       DPRINTF("LICENSE\n");
+                       break;
+
+               case CARD_REGISTER_OLD:
+               case CARD_REGISTER:
+                       DPRINTF("CARD_REGISTER\n");
+                       {
+                               struct card_register* cr = (struct card_register*)(wdheader->data);
+
+                               DPRINTF("Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
+                               cr->Card.dwItems,
+                               (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
+                               cr->Card.Item[0].I.IO.dwBytes,
+                               cr->Card.Item[0].I.IO.dwBar);
+                               
+                               DPRINTF("Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
+                               cr->Card.dwItems,
+                               (unsigned long)cr->Card.Item[1].I.IO.dwAddr,
+                               cr->Card.Item[1].I.IO.dwBytes,
+                               cr->Card.Item[1].I.IO.dwBar);
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+
+                               pport = config_get((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
+                               if (!pport)
+                                       break;
+
+                               ret = pport->open((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
+
+                               ppbase = (unsigned long)cr->Card.Item[0].I.IO.dwAddr;
+
+                               if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr)
+                                       ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr;
+
+                               if (ret >= 0) {
+                                       cr->hCard = ret;
+                               } else {
+                                       cr->hCard = 0;
+                               }
+#endif
+                               DPRINTF("hCard: %lu\n", cr->hCard);
+                       }
+                       break;
+
+               case USB_TRANSFER:
+                       DPRINTF("in USB_TRANSFER");
+                       {
+                               struct usb_transfer *ut = (struct usb_transfer*)(wdheader->data);
+
+#ifdef DEBUG
+                               DPRINTF(" unique: %lu, pipe: %lu, read: %lu, options: %lx, size: %lu, timeout: %lx\n",
+                               ut->dwUniqueID, ut->dwPipeNum, ut->fRead,
+                               ut->dwOptions, ut->dwBufferSize, ut->dwTimeout);
+                               DPRINTF("setup packet: ");
+                               hexdump(ut->SetupPacket, 8);
+
+                               if (!ut->fRead && ut->dwBufferSize)
+                               {
+                                       hexdump(ut->pBuffer, ut->dwBufferSize);
+                               }
+#endif
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               /* http://www.jungo.com/support/documentation/windriver/802/wdusb_man_mhtml/node55.html#SECTION001213000000000000000 */
+                               if (ut->dwPipeNum == 0) { /* control pipe */
+                                       int requesttype, request, value, index, size;
+                                       requesttype = ut->SetupPacket[0];
+                                       request = ut->SetupPacket[1];
+                                       value = ut->SetupPacket[2] | (ut->SetupPacket[3] << 8);
+                                       index = ut->SetupPacket[4] | (ut->SetupPacket[5] << 8);
+                                       size = ut->SetupPacket[6] | (ut->SetupPacket[7] << 8);
+                                       DPRINTF("requesttype: %x, request: %x, value: %u, index: %u, size: %u\n", requesttype, request, value, index, size);
+                                       ret = usb_control_msg(usb_devhandle, requesttype, request, value, index, ut->pBuffer, size, ut->dwTimeout);
+                               } else {
+                                       if (ut->fRead) {
+                                               ret = usb_bulk_read(usb_devhandle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
+
+                                       } else {
+                                               ret = usb_bulk_write(usb_devhandle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
+                                       }
+                               }
+
+                               if (ret < 0) {
+                                       fprintf(stderr, "usb_transfer: %d (%s)\n", ret, usb_strerror());
+                               } else {
+                                       ut->dwBytesTransferred = ret;
+                                       ret = 0;
+                               }
+#endif
+
+#ifdef DEBUG
+                               DPRINTF("Transferred: %lu (%s)\n",ut->dwBytesTransferred, (ut->fRead?"read":"write"));
+                               if (ut->fRead && ut->dwBytesTransferred)
+                               {
+                                       DPRINTF("Read: ");
+                                       hexdump(ut->pBuffer, ut->dwBytesTransferred);
+                               }
+#endif
+                       }
+                       break;
+
+               case INT_ENABLE_OLD:
+               case INT_ENABLE:
+                       DPRINTF("INT_ENABLE\n");
+                       {
+                               struct interrupt *it = (struct interrupt*)(wdheader->data);
+
+                               DPRINTF("Handle: %lu, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
+                               it->hInterrupt, it->dwOptions,
+                               it->dwCmds, it->fEnableOk, it->dwCounter,
+                               it->dwLost, it->fStopped);
+
+                               it->fEnableOk = 1;
+                               it->fStopped = 0;
+                               ints_enabled = 1;
+                               pthread_mutex_trylock(&int_wait);
+                       }
+
+                       break;
+                       
+               case INT_DISABLE:
+                       DPRINTF("INT_DISABLE\n");
+                       {
+                               struct interrupt *it = (struct interrupt*)(wdheader->data);
+
+                               DPRINTF("Handle: %lu, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
+                               it->hInterrupt, it->dwOptions,
+                               it->dwCmds, it->fEnableOk, it->dwCounter,
+                               it->dwLost, it->fStopped);
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               it->dwCounter = 0;
+                               it->fStopped = 1;
+                               ints_enabled = 0;
+                               if (pthread_mutex_trylock(&int_wait) == EBUSY)
+                                       pthread_mutex_unlock(&int_wait);
+#endif
+                               DPRINTF("Handle: %lu, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
+                               it->hInterrupt, it->dwOptions,
+                               it->dwCmds, it->fEnableOk, it->dwCounter,
+                               it->dwLost, it->fStopped);
+                       }
+                       break;
+
+               case USB_SET_INTERFACE:
+                       DPRINTF("USB_SET_INTERFACE\n");
+                       {
+                               struct usb_set_interface *usi = (struct usb_set_interface*)(wdheader->data);
+
+                               DPRINTF("unique: %lu, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
+                               usi->dwUniqueID, usi->dwInterfaceNum,
+                               usi->dwAlternateSetting, usi->dwOptions);
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               if (usbdevice) {
+                                  if (!usb_devhandle)
+                                    usb_devhandle = usb_open(usbdevice);
+
+                                       /* FIXME: Select right interface! */
+                                       ret = usb_claim_interface(usb_devhandle, usbdevice->config[0].interface[usi->dwInterfaceNum].altsetting[usi->dwAlternateSetting].bInterfaceNumber);
+                                       if (!ret) {
+                                               if(!ret) {
+                                                       usbinterface = usbdevice->config[0].interface[usi->dwInterfaceNum].altsetting[usi->dwAlternateSetting].bInterfaceNumber;
+                                                       ret = usb_set_altinterface(usb_devhandle, usi->dwAlternateSetting);
+                                                       if (ret)
+                                                               fprintf(stderr, "usb_set_altinterface: %d\n", ret);
+                                               } else {
+                                                       fprintf(stderr, "usb_set_configuration: %d (%s)\n", ret, usb_strerror());
+                                               }
+                                       } else {
+                                               fprintf(stderr, "usb_claim_interface: %d -> %d (%s)\n",
+                                               usbdevice->config[0].interface[usi->dwInterfaceNum].altsetting[usi->dwAlternateSetting].bInterfaceNumber,
+                                               ret, usb_strerror());
+                                       }
+                               }
+#endif
+                               DPRINTF("unique: %lu, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
+                               usi->dwUniqueID, usi->dwInterfaceNum,
+                               usi->dwAlternateSetting, usi->dwOptions);
+                       }
+                       break;
+
+               case USB_GET_DEVICE_DATA_OLD:
+               case USB_GET_DEVICE_DATA:
+                       DPRINTF("USB_GET_DEVICE_DATA\n");
+                       {
+                               struct usb_get_device_data *ugdd = (struct usb_get_device_data*)(wdheader->data);
+                               int pSize;
+
+                               DPRINTF("unique: %lu, bytes: %lu, options: %lx\n",
+                               ugdd->dwUniqueID, ugdd->dwBytes,
+                               ugdd->dwOptions);
+
+                               pSize = ugdd->dwBytes;
+                               if (!ugdd->dwBytes) {
+                                       if (usbdevice) {
+                                               ugdd->dwBytes = usb_deviceinfo(NULL);
+                                       }
+                               } else {
+                                       usb_deviceinfo((unsigned char*)ugdd->pBuf);
+                               }
+                       }
+                       break;
+
+               case EVENT_REGISTER_OLD:
+               case EVENT_REGISTER:
+                       DPRINTF("EVENT_REGISTER\n");
+                       {
+                               struct event *e = (struct event*)(wdheader->data);
+                               struct usb_bus *bus;
+                               char* devpos;
+                               int busnum = -1, devnum = -1;
+                               int i;
+
+                               DPRINTF("handle: %lu, action: %lu, status: %lu, eventid: %lu, cardtype: %lu, kplug: %lu, options: %lu, dev: %lx:%lx, unique: %lu, ver: %lu, nummatch: %lu\n",
+                               e->handle, e->dwAction,
+                               e->dwStatus, e->dwEventId, e->dwCardType,
+                               e->hKernelPlugIn, e->dwOptions,
+                               e->u.Usb.deviceId.dwVendorId,
+                               e->u.Usb.deviceId.dwProductId,
+                               e->u.Usb.dwUniqueID, e->dwEventVer,
+                               e->dwNumMatchTables);
+
+                               devpos = getenv("XILINX_USB_DEV");
+                               if (devpos != NULL) {
+                                       int j;
+                                       char *devstr = NULL, *remainder;
+
+                                       DPRINTF("XILINX_USB_DEV=%s\n", devpos);
+
+                                       for (j = 0; j < strlen(devpos) && devpos[j] != 0; j++) {
+                                               if (devpos[j] == ':') {
+                                                       devpos[j] = 0;
+                                                       devstr = &(devpos[j+1]);
+                                               }
+                                       }
+
+                                       if (devstr && strlen(devstr) > 0) {
+                                               busnum = strtol(devpos, &remainder, 10);
+                                               if (devpos == remainder) {
+                                                       busnum = -1;
+                                               } else {
+                                                       devnum = strtol(devstr, &remainder, 10);
+                                                       if (devstr == remainder) {
+                                                               busnum = -1;
+                                                               devnum = -1;
+                                                       } else {
+                                                               fprintf(stderr,"Using XILINX platform cable USB at %03d:%03d\n",
+                                                               busnum, devnum);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               for (i = 0; i < e->dwNumMatchTables; i++) {
+
+                                       DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
+                                       e->matchTables[i].VendorId,
+                                       e->matchTables[i].ProductId,
+                                       e->matchTables[i].bDeviceClass,
+                                       e->matchTables[i].bDeviceSubClass,
+                                       e->matchTables[i].bInterfaceClass,
+                                       e->matchTables[i].bInterfaceSubClass,
+                                       e->matchTables[i].bInterfaceProtocol);
+
+                                       for (bus = busses; bus; bus = bus->next) {
+                                               struct usb_device *dev;
+
+                                               if ((devnum != -1) && (strtol(bus->dirname, NULL, 10) != busnum))
+                                                       continue;
+
+                                               for (dev = bus->devices; dev; dev = dev->next) {
+                                                       struct usb_device_descriptor *desc = &(dev->descriptor);
+
+                                                       if((desc->idVendor == e->matchTables[i].VendorId) &&
+                                                          (desc->idProduct == e->matchTables[i].ProductId) &&
+                                                          (desc->bDeviceClass == e->matchTables[i].bDeviceClass) &&
+                                                          (desc->bDeviceSubClass == e->matchTables[i].bDeviceSubClass) &&
+                                                          ((devnum == -1) || (strtol(dev->filename, NULL, 10) == devnum)) ) {
+                                                                  int ac;
+                                                                  for (ac = 0; ac < desc->bNumConfigurations; ac++) {
+                                                                          struct usb_interface *interface = dev->config[ac].interface;
+                                                                          int ai;
+
+                                                                          for (ai = 0; ai < interface->num_altsetting; ai++) {
+
+                                                                                  DPRINTF("intclass: %x, intsubclass: %x, intproto: %x\n",
+                                                                                  interface->altsetting[i].bInterfaceClass,
+                                                                                  interface->altsetting[i].bInterfaceSubClass,
+                                                                                  interface->altsetting[i].bInterfaceProtocol);
+
+                                                                                  if ((interface->altsetting[ai].bInterfaceSubClass == e->matchTables[i].bInterfaceSubClass) &&
+                                                                                                  (interface->altsetting[ai].bInterfaceProtocol == e->matchTables[i].bInterfaceProtocol)){
+                                                                                          /* TODO: check interfaceClass! */
+                                                                                          DPRINTF("found device with libusb\n");
+                                                                                          usbdevice = dev;
+                                                                                          card_type = e->dwCardType;
+                                                                                  }
+                                                                          }
+                                                                  }
+                                                       }
+                                               }
+                                       }
+                               }
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               e->handle++;
+#endif
+
+#ifdef DEBUG
+                               DPRINTF("handle: %lu, action: %lu, status: %lu, eventid: %lu, cardtype: %lu, kplug: %lu, options: %lu, dev: %lx:%lx, unique: %lu, ver: %lu, nummatch: %lu\n",
+                               e->handle, e->dwAction,
+                               e->dwStatus, e->dwEventId, e->dwCardType,
+                               e->hKernelPlugIn, e->dwOptions,
+                               e->u.Usb.deviceId.dwVendorId,
+                               e->u.Usb.deviceId.dwProductId,
+                               e->u.Usb.dwUniqueID, e->dwEventVer,
+                               e->dwNumMatchTables);
+
+                               for (i = 0; i < e->dwNumMatchTables; i++)
+                                       DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
+                                       e->matchTables[i].VendorId,
+                                       e->matchTables[i].ProductId,
+                                       e->matchTables[i].bDeviceClass,
+                                       e->matchTables[i].bDeviceSubClass,
+                                       e->matchTables[i].bInterfaceClass,
+                                       e->matchTables[i].bInterfaceSubClass,
+                                       e->matchTables[i].bInterfaceProtocol);
+#endif
+                       }
+                       break;
+
+               case TRANSFER_OLD:
+               case TRANSFER:
+                       DPRINTF("TRANSFER\n");
+                       {
+                               WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               ret = pport->transfer(tr, fd, request, ppbase, ecpbase, 1);
+#endif
+                       }
+                       break;
+
+               case MULTI_TRANSFER_OLD:
+               case MULTI_TRANSFER:
+                       DPRINTF("MULTI_TRANSFER\n");
+                       {
+                               WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
+                               unsigned long num = wdheader->size/sizeof(WD_TRANSFER);
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               ret = pport->transfer(tr, fd, request, ppbase, ecpbase, num);
+#endif
+                       }
+                       break;
+
+               case EVENT_UNREGISTER:
+                       DPRINTF("EVENT_UNREGISTER\n");
+#ifndef NO_WINDRVR
+                       ret = (*ioctl_func) (fd, request, wdioctl);
+#endif
+                       break;
+
+               case INT_WAIT:
+                       DPRINTF("INT_WAIT\n");
+                       {
+                               struct interrupt *it = (struct interrupt*)(wdheader->data);
+
+                               DPRINTF("Handle: %lu, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
+                               it->hInterrupt, it->dwOptions,
+                               it->dwCmds, it->fEnableOk, it->dwCounter,
+                               it->dwLost, it->fStopped);
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               if (usbdevice) {
+                                       if (it->dwCounter == 0) {
+                                               it->dwCounter = 1;
+                                       } else {
+                                               pthread_mutex_lock(&int_wait);
+                                               pthread_mutex_unlock(&int_wait);
+                                       }
+                               } else {
+                                       pthread_mutex_lock(&int_wait);
+                                       pthread_mutex_unlock(&int_wait);
+                               }
+#endif
+
+                               DPRINTF("INT_WAIT_RETURN: Handle: %lu, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
+                               it->hInterrupt, it->dwOptions, it->dwCmds,
+                               it->fEnableOk, it->dwCounter, it->dwLost,
+                               it->fStopped);
+                       }
+                       break;
+
+               case CARD_UNREGISTER:
+                       DPRINTF("CARD_UNREGISTER\n");
+                       {
+                               struct card_register* cr = (struct card_register*)(wdheader->data);
+
+                               DPRINTF("Addr: 0x%lx, bytes: %lu, bar: %lu\n",
+                               (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
+                               cr->Card.Item[0].I.IO.dwBytes,
+                               cr->Card.Item[0].I.IO.dwBar);
+
+                               DPRINTF("hCard: %lu\n", cr->hCard);
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               if (pport)
+                                       pport->close(cr->hCard);
+
+                               pport = NULL;
+#endif
+                       }
+                       break;
+
+               case EVENT_PULL:
+                       DPRINTF("EVENT_PULL\n");
+                       {
+                               struct event *e = (struct event*)(wdheader->data);
+#ifdef DEBUG
+                               int i;
+
+                               DPRINTF("handle: %lu, action: %lu, status: %lu, eventid: %lu, cardtype: %lx, kplug: %lu, options: %lu, dev: %lx:%lx, unique: %lu, ver: %lu, nummatch: %lu\n",
+                               e->handle, e->dwAction, e->dwStatus,
+                               e->dwEventId, e->dwCardType, e->hKernelPlugIn,
+                               e->dwOptions, e->u.Usb.deviceId.dwVendorId,
+                               e->u.Usb.deviceId.dwProductId,
+                               e->u.Usb.dwUniqueID, e->dwEventVer,
+                               e->dwNumMatchTables);
+
+                               for (i = 0; i < e->dwNumMatchTables; i++)
+                                       DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
+                                       e->matchTables[i].VendorId,
+                                       e->matchTables[i].ProductId,
+                                       e->matchTables[i].bDeviceClass,
+                                       e->matchTables[i].bDeviceSubClass,
+                                       e->matchTables[i].bInterfaceClass,
+                                       e->matchTables[i].bInterfaceSubClass,
+                                       e->matchTables[i].bInterfaceProtocol);
+#endif
+
+#ifndef NO_WINDRVR
+                               ret = (*ioctl_func) (fd, request, wdioctl);
+#else
+                               if (usbdevice) {
+                                       struct usb_interface *interface = usbdevice->config->interface;
+
+                                       e->dwCardType = card_type;
+                                       e->dwAction = 1;
+                                       e->dwEventId = 109;
+                                       e->u.Usb.dwUniqueID = 110;
+                                       e->matchTables[0].VendorId = usbdevice->descriptor.idVendor;
+                                       e->matchTables[0].ProductId = usbdevice->descriptor.idProduct;
+                                       e->matchTables[0].bDeviceClass = usbdevice->descriptor.bDeviceClass;
+                                       e->matchTables[0].bDeviceSubClass = usbdevice->descriptor.bDeviceSubClass;
+                                       e->matchTables[0].bInterfaceClass = interface->altsetting[0].bInterfaceClass;
+                                       e->matchTables[0].bInterfaceSubClass = interface->altsetting[0].bInterfaceSubClass;
+                                       e->matchTables[0].bInterfaceProtocol = interface->altsetting[0].bInterfaceProtocol;
+                               }
+#endif
+
+#ifdef DEBUG
+                               DPRINTF("handle: %lu, action: %lu, status: %lu, eventid: %lu, cardtype: %lx, kplug: %lu, options: %lu, dev: %lx:%lx, unique: %lu, ver: %lu, nummatch: %lu\n",
+                               e->handle, e->dwAction, e->dwStatus,
+                               e->dwEventId, e->dwCardType, e->hKernelPlugIn,
+                               e->dwOptions, e->u.Usb.deviceId.dwVendorId,
+                               e->u.Usb.deviceId.dwProductId,
+                               e->u.Usb.dwUniqueID, e->dwEventVer,
+                               e->dwNumMatchTables);
+
+                               for (i = 0; i < e->dwNumMatchTables; i++)
+                                       DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
+                                       e->matchTables[i].VendorId,
+                                       e->matchTables[i].ProductId,
+                                       e->matchTables[i].bDeviceClass,
+                                       e->matchTables[i].bDeviceSubClass,
+                                       e->matchTables[i].bInterfaceClass,
+                                       e->matchTables[i].bInterfaceSubClass,
+                                       e->matchTables[i].bInterfaceProtocol);
+#endif
+
+                       }
+                       break;
+
+               default:
+                       fprintf(stderr,"!!!Unsupported IOCTL: %x!!!\n", request);
+#ifndef NO_WINDRVR
+                       ret = (*ioctl_func) (fd, request, wdioctl);
+#endif
+                       break;
+       }
+
+       return ret;
+}
+
+int ioctl(int fd, unsigned long int request, ...) {
+       va_list args;
+       void *argp;
+       int ret;
+
+       if (!ioctl_func)                                                                    
+               ioctl_func = (int (*) (int, int, void *)) dlsym (RTLD_NEXT, "ioctl");             
+
+       va_start (args, request);
+       argp = va_arg (args, void *);
+       va_end (args);
+
+       if (fd == windrvrfd)
+               ret = do_wdioctl(fd, request, argp);
+       else
+               ret = (*ioctl_func) (fd, request, argp);
+
+       return ret;
+}
+
+int open (const char *pathname, int flags, ...) {
+       static int (*func) (const char *, int, mode_t) = NULL;
+       mode_t mode = 0;
+       va_list args;
+       int fd;
+
+       if (!func)
+               func = (int (*) (const char *, int, mode_t)) dlsym (RTLD_NEXT, "open");
+
+       if (flags & O_CREAT) {
+               va_start(args, flags);
+               mode = va_arg(args, mode_t);
+               va_end(args);
+       }
+
+       if (!strcmp (pathname, "/dev/windrvr6")) {
+               DPRINTF("opening windrvr6\n");
+#ifdef NO_WINDRVR
+               windrvrfd = fd = (*func) ("/dev/null", flags, mode);
+#else
+               windrvrfd = fd = (*func) (pathname, flags, mode);
+#endif
+               if (!busses) {
+                       usb_init();
+                       usb_find_busses();
+                       usb_find_devices();
+
+                       busses = usb_get_busses();
+               }
+
+               return fd;
+       }
+
+       return (*func) (pathname, flags, mode);
+}
+
+int close(int fd) {
+       static int (*func) (int) = NULL;
+
+       if (!func)
+               func = (int (*) (int)) dlsym(RTLD_NEXT, "close");
+       
+       if (fd == windrvrfd && windrvrfd >= 0) {
+               DPRINTF("close windrvrfd\n");
+               if (usbinterface >= 0)
+                       usb_release_interface(usb_devhandle, usbinterface);
+
+               if (usb_devhandle)
+                       usb_close(usb_devhandle);
+
+               usb_devhandle = NULL;
+               usbinterface = -1;
+               windrvrfd = -1;
+       }
+
+       return (*func) (fd);
+}
+
+FILE *fopen(const char *path, const char *mode) {
+       FILE *ret;
+       static FILE* (*func) (const char*, const char*) = NULL;
+       char buf[256];
+       int i;
+
+       if (!func)
+               func = (FILE* (*) (const char*, const char*)) dlsym(RTLD_NEXT, "fopen");
+
+       for (i = 0; i < 4; i++) {
+               snprintf(buf, sizeof(buf), "/proc/sys/dev/parport/parport%d/base-addr", i);
+               if (!strcmp(path, buf)) {
+                       DPRINTF("open base-addr of parport%d\n", i);
+                       if (config_is_real_pport(i)) {
+                               ret = (*func) (path, mode);
+                       } else {
+                               ret = (*func) ("/dev/null", mode);
+                       }
+
+                       if (ret) {
+                               baseaddrfp = ret;
+                               baseaddrnum = i;
+                       }
+
+                       return ret;
+               }
+       }
+
+       ret = (*func) (path, mode);
+
+       if (!strcmp(path, "/proc/modules")) {
+               DPRINTF("opening /proc/modules\n");
+#ifdef NO_WINDRVR
+               modulesfp = ret;
+               modules_read = 0;
+#endif
+       }
+
+       return ret;
+}
+
+char *fgets(char *s, int size, FILE *stream) {
+        static char* (*func) (char*, int, FILE*) = NULL;
+       const char modules[][256] = {"windrvr6 1 0 - Live 0xdeadbeef\n", "parport_pc 1 0 - Live 0xdeadbeef\n"};
+       char buf[256];
+       char *ret = NULL;
+
+
+       if (!func)
+               func = (char* (*) (char*, int, FILE*)) dlsym(RTLD_NEXT, "fgets");
+       
+       if (modulesfp == stream) {
+               if (modules_read < sizeof(modules) / sizeof(modules[0])) {
+                       strcpy(s, modules[modules_read]);
+                       ret = s;
+                       modules_read++;
+               }
+       } else if (baseaddrfp == stream) {
+               snprintf(s, sizeof(buf), "%d\t%d\n",
+                       (baseaddrnum) * 0x10,
+                       ((baseaddrnum) * 0x10) + 0x400);
+               ret = s;
+       } else {
+               ret = (*func)(s,size,stream);
+       }
+
+       return ret;
+}
+
+int fclose(FILE *fp) {
+       static int (*func) (FILE*) = NULL;
+
+       if (!func)
+               func = (int (*) (FILE*)) dlsym(RTLD_NEXT, "fclose");
+
+       if (fp == modulesfp) {
+               modulesfp = NULL;
+       }
+
+       if (fp == baseaddrfp) {
+               baseaddrfp = NULL;
+       }
+       
+       return (*func)(fp);
+}
+
+int access(const char *pathname, int mode) {
+       static int (*func) (const char*, int);
+
+       if (!func)
+               func = (int (*) (const char*, int)) dlsym(RTLD_NEXT, "access");
+
+       if (pathname && !strcmp(pathname, "/dev/windrvr6")) {
+               return 0;
+       } else {
+               return (*func)(pathname, mode);
+       }
+}
diff --git a/misc/usb-driver.h b/misc/usb-driver.h
new file mode 100644 (file)
index 0000000..baddf4a
--- /dev/null
@@ -0,0 +1,398 @@
+#define VERSION                        0x910
+#define LICENSE                        0x952
+#define TRANSFER               0x98c
+#define MULTI_TRANSFER         0x98d
+#define USB_TRANSFER           0x983
+#define EVENT_UNREGISTER       0x987
+#define INT_DISABLE            0x91f
+#define INT_WAIT               0x94b
+#define CARD_REGISTER          0x9a4
+#define EVENT_REGISTER         0x9a5
+#define CARD_UNREGISTER                0x92b
+#define USB_GET_DEVICE_DATA    0x9a7
+#define INT_ENABLE             0x98e
+#define EVENT_PULL             0x988
+#define USB_SET_INTERFACE      0x981
+#define CARD_REGISTER_OLD      0x97d
+#define INT_ENABLE_OLD         0x91e
+#define USB_GET_DEVICE_DATA_OLD        0x980
+#define EVENT_REGISTER_OLD     0x986
+#define TRANSFER_OLD           0x903
+#define MULTI_TRANSFER_OLD     0x904
+
+#define MAGIC 0xa410b413UL
+
+#define PP_DATA                        0
+#define PP_STATUS              1
+#define PP_CONTROL             2
+#define PP_ECP_CFGA            0
+#define PP_ECP_CFGB            1
+#define PP_ECP_ECR             2
+#define PP_READ                        10
+#define PP_WRITE               13
+
+#define PP_TDI                 0x01
+#define PP_TDO                 0x10
+#define PP_PROG                        0x10
+#define PP_TCK                 0x02
+#define PP_TMS                 0x04
+#define PP_CTRL                        0x08
+
+#ifdef DEBUG
+#define DPRINTF(format, args...) fprintf(stderr, format, ##args)
+#else
+#define DPRINTF(format, args...)
+#endif
+
+void hexdump(unsigned char *buf, int len);
+
+#define WDU_GET_MAX_PACKET_SIZE(x)                ((unsigned short) (((x) & 0x7ff) * (1 + (((x) & 0x1800) >> 11))))
+
+/* http://www.jungo.com/support/documentation/windriver/811/wdusb_man_mhtml/node78.html#SECTION001734000000000000000 */
+
+struct header_struct {
+       unsigned long magic;
+       void* data;
+       unsigned long size;
+};
+
+struct version_struct {
+       unsigned long versionul;
+       char version[128];
+};
+
+struct license_struct {
+       char cLicense[128]; // Buffer with license string to put.
+       // If empty string then get current license setting
+       // into dwLicense.
+       unsigned long dwLicense;  // Returns license settings: LICENSE_DEMO, LICENSE_WD
+       // etc..., or 0 for invalid license.
+       unsigned long dwLicense2; // Returns additional license settings, if dwLicense
+       // could not hold all the information.
+       // Then dwLicense will return 0.
+};
+
+typedef struct
+{
+       unsigned long dwVendorId;
+       unsigned long dwDeviceId;
+} WD_PCI_ID;
+
+typedef struct
+{
+       unsigned long dwBus;
+       unsigned long dwSlot;
+       unsigned long dwFunction;
+} WD_PCI_SLOT;
+
+typedef struct
+{
+       unsigned long dwVendorId;
+       unsigned long dwProductId;
+} WD_USB_ID;
+
+typedef struct
+{
+       unsigned short VendorId;
+       unsigned short ProductId;
+       unsigned char bDeviceClass;
+       unsigned char bDeviceSubClass;
+       unsigned char bInterfaceClass;
+       unsigned char bInterfaceSubClass;
+       unsigned char bInterfaceProtocol;
+} WDU_MATCH_TABLE;
+
+typedef struct
+{
+       unsigned long dwNumber;        // Pipe 0 is the default pipe
+       unsigned long dwMaximumPacketSize;
+       unsigned long type;            // USB_PIPE_TYPE
+       unsigned long direction;       // WDU_DIR
+       // Isochronous, Bulk, Interrupt are either USB_DIR_IN or USB_DIR_OUT
+       // Control are USB_DIR_IN_OUT
+       unsigned long dwInterval;      // interval in ms relevant to Interrupt pipes
+} WD_USB_PIPE_INFO, WD_USB_PIPE_INFO_V43, WDU_PIPE_INFO;
+
+#define WD_USB_MAX_PIPE_NUMBER 32
+
+typedef struct
+{
+       unsigned long dwPipes;
+       WD_USB_PIPE_INFO Pipe[WD_USB_MAX_PIPE_NUMBER];
+} WD_USB_DEVICE_INFO, WD_USB_DEVICE_INFO_V43;
+
+struct usb_transfer
+{
+       unsigned long dwUniqueID;
+       unsigned long dwPipeNum;    // Pipe number on device.
+       unsigned long fRead;        // TRUE for read (IN) transfers; FALSE for write (OUT) transfers.
+       unsigned long dwOptions;    // USB_TRANSFER options:
+       // USB_ISOCH_FULL_PACKETS_ONLY - For isochronous
+       // transfers only. If set, only full packets will be
+       // transmitted and the transfer function will return
+       // when the amount of bytes left to transfer is less
+       // than the maximum packet size for the pipe (the
+       // function will return without transmitting the
+       // remaining bytes).
+       void* pBuffer;    // Pointer to buffer to read/write.
+       unsigned long dwBufferSize; // Amount of bytes to transfer.
+       unsigned long dwBytesTransferred; // Returns the number of bytes actually read/written
+       unsigned char SetupPacket[8];          // Setup packet for control pipe transfer.
+       unsigned long dwTimeout;    // Timeout for the transfer in milliseconds. Set to 0 for infinite wait.
+};
+
+
+
+
+struct event {
+       unsigned long handle;
+       unsigned long dwAction; // WD_EVENT_ACTION
+       unsigned long dwStatus; // EVENT_STATUS
+       unsigned long dwEventId;
+       unsigned long dwCardType; //WD_BUS_PCI, WD_BUS_USB, WD_BUS_PCMCIA
+       unsigned long hKernelPlugIn;
+       unsigned long dwOptions; // WD_EVENT_OPTION
+       union
+       {
+               struct
+               {
+                       WD_PCI_ID cardId;
+                       WD_PCI_SLOT pciSlot;
+               } Pci;
+               struct
+               {
+                       WD_USB_ID deviceId;
+                       unsigned long dwUniqueID;
+               } Usb;
+       } u;
+       unsigned long dwEventVer;
+       unsigned long dwNumMatchTables;
+       WDU_MATCH_TABLE matchTables[1];
+};
+
+typedef struct
+{
+       unsigned long dwBusType;        // Bus Type: ISA, EISA, PCI, PCMCIA.
+       unsigned long dwBusNum;         // Bus number.
+       unsigned long dwSlotFunc;       // Slot number on Bus.
+} WD_BUS, WD_BUS_V30;
+
+typedef struct
+{
+       unsigned long item; // ITEM_TYPE
+       unsigned long fNotSharable;
+       unsigned long dwReserved; // Reserved for internal use
+       unsigned long dwOptions; // WD_ITEM_OPTIONS
+       union
+       {
+               struct
+               { // ITEM_MEMORY
+                       unsigned long dwPhysicalAddr;     // Physical address on card.
+                       unsigned long dwBytes;            // Address range.
+                       void* dwTransAddr;         // Returns the address to pass on to transfer commands.
+                       void* dwUserDirectAddr;   // Returns the address for direct user read/write.
+                       unsigned long dwCpuPhysicalAddr;  // Returns the CPU physical address
+                       unsigned long dwBar;              // Base Address Register number of PCI card.
+               } Mem;
+               struct
+               { // ITEM_IO
+                       void* dwAddr;          // Beginning of io address.
+                       unsigned long dwBytes;        // IO range.
+                       unsigned long dwBar;          // Base Address Register number of PCI card.
+               } IO;
+               struct
+               { // ITEM_INTERRUPT
+                       unsigned long dwInterrupt; // Number of interrupt to install.
+                       unsigned long dwOptions;   // Interrupt options. For level sensitive
+                       // interrupts - set to: INTERRUPT_LEVEL_SENSITIVE.
+                       unsigned long hInterrupt;  // Returns the handle of the interrupt installed.
+               } Int;
+               WD_BUS Bus; // ITEM_BUS
+               struct
+               {
+                       unsigned long dw1, dw2, dw3, dw4; // Reserved for internal use
+                       void* dw5; // Reserved for internal use
+               } Val;
+       } I;
+} WD_ITEMS, WD_ITEMS_V30;
+
+#define WD_CARD_ITEMS  20
+
+typedef struct
+{
+       unsigned long dwItems;
+       WD_ITEMS Item[WD_CARD_ITEMS];
+} WD_CARD, WD_CARD_V30;
+
+enum { CARD_VX_NO_MMU_INIT = 0x4000000 };
+
+struct card_register
+{
+       WD_CARD Card;           // Card to register.
+       unsigned long fCheckLockOnly;   // Only check if card is lockable, return hCard=1 if OK.
+       unsigned long hCard;            // Handle of card.
+       unsigned long dwOptions;        // Should be zero.
+       char cName[32];         // Name of card.
+       char cDescription[100]; // Description.
+};
+
+typedef struct
+{
+       void* dwPort;       // IO port for transfer or kernel memory address.
+       unsigned long cmdTrans;    // Transfer command WD_TRANSFER_CMD.
+
+       // Parameters used for string transfers:
+       unsigned long dwBytes;     // For string transfer.
+       unsigned long fAutoinc;    // Transfer from one port/address
+       // or use incremental range of addresses.
+       unsigned long dwOptions;   // Must be 0.
+       union
+       {
+               unsigned char Byte;     // Use for 8 bit transfer.
+               unsigned short Word;     // Use for 16 bit transfer.
+               uint32_t Dword;   // Use for 32 bit transfer.
+               uint64_t Qword;  // Use for 64 bit transfer.
+               void* pBuffer; // Use for string transfer.
+       } Data;
+} WD_TRANSFER, WD_TRANSFER_V61;
+
+typedef struct
+{
+       unsigned long hKernelPlugIn;
+       unsigned long dwMessage;
+       void* pData;
+       unsigned long dwResult;
+} WD_KERNEL_PLUGIN_CALL, WD_KERNEL_PLUGIN_CALL_V40;
+
+
+struct interrupt
+{
+       unsigned long hInterrupt;    // Handle of interrupt.
+       unsigned long dwOptions;     // Interrupt options: can be INTERRUPT_CMD_COPY
+
+       WD_TRANSFER *Cmd;    // Commands to do on interrupt.
+       unsigned long dwCmds;        // Number of commands.
+
+       // For WD_IntEnable():
+       WD_KERNEL_PLUGIN_CALL kpCall; // Kernel PlugIn call.
+       unsigned long fEnableOk;     // TRUE if interrupt was enabled (WD_IntEnable() succeed).
+
+       // For WD_IntWait() and WD_IntCount():
+       unsigned long dwCounter;     // Number of interrupts received.
+       unsigned long dwLost;        // Number of interrupts not yet dealt with.
+       unsigned long fStopped;      // Was interrupt disabled during wait.
+};
+
+struct usb_set_interface
+{
+       unsigned long dwUniqueID;
+       unsigned long dwInterfaceNum;
+       unsigned long dwAlternateSetting;
+       unsigned long dwOptions;
+};
+
+struct usb_get_device_data
+{
+       unsigned long dwUniqueID;
+       void* pBuf;
+       unsigned long dwBytes;
+       unsigned long dwOptions;
+};
+
+#define WD_USB_MAX_INTERFACES 30
+
+typedef struct
+{
+       unsigned char bLength;
+       unsigned char bDescriptorType;
+       unsigned char bInterfaceNumber;
+       unsigned char bAlternateSetting;
+       unsigned char bNumEndpoints;
+       unsigned char bInterfaceClass;
+       unsigned char bInterfaceSubClass;
+       unsigned char bInterfaceProtocol;
+       unsigned char iInterface;
+} WDU_INTERFACE_DESCRIPTOR;
+
+typedef struct
+{
+       unsigned char bLength;
+       unsigned char bDescriptorType;
+       unsigned char bEndpointAddress;
+       unsigned char bmAttributes;
+       unsigned short wMaxPacketSize;
+       unsigned char bInterval;
+} WDU_ENDPOINT_DESCRIPTOR;
+
+typedef struct
+{
+       unsigned char bLength;
+       unsigned char bDescriptorType;
+       unsigned short wTotalLength;
+       unsigned char bNumInterfaces;
+       unsigned char bConfigurationValue;
+       unsigned char iConfiguration;
+       unsigned char bmAttributes;
+       unsigned char MaxPower;
+} WDU_CONFIGURATION_DESCRIPTOR;
+
+typedef struct
+{
+       unsigned char bLength;
+       unsigned char bDescriptorType;
+       unsigned short bcdUSB;
+       unsigned char bDeviceClass;
+       unsigned char bDeviceSubClass;
+       unsigned char bDeviceProtocol;
+       unsigned char bMaxPacketSize0;
+
+       unsigned short idVendor;
+       unsigned short idProduct;
+       unsigned short bcdDevice;
+       unsigned char iManufacturer;
+       unsigned char iProduct;
+       unsigned char iSerialNumber;
+       unsigned char bNumConfigurations;
+} WDU_DEVICE_DESCRIPTOR;
+
+typedef struct
+{
+       WDU_INTERFACE_DESCRIPTOR Descriptor;
+       WDU_ENDPOINT_DESCRIPTOR *pEndpointDescriptors;
+       WDU_PIPE_INFO *pPipes;
+} WDU_ALTERNATE_SETTING;
+
+typedef struct
+{
+       WDU_ALTERNATE_SETTING *pAlternateSettings;
+       unsigned long dwNumAltSettings;
+       WDU_ALTERNATE_SETTING *pActiveAltSetting;
+} WDU_INTERFACE;
+
+typedef struct
+{
+       WDU_CONFIGURATION_DESCRIPTOR Descriptor;
+       unsigned long dwNumInterfaces;
+       WDU_INTERFACE *pInterfaces;
+} WDU_CONFIGURATION;
+
+struct usb_device_info {
+       WDU_DEVICE_DESCRIPTOR Descriptor;
+       WDU_PIPE_INFO Pipe0;
+       WDU_CONFIGURATION *pConfigs;
+       WDU_CONFIGURATION *pActiveConfig;
+       WDU_INTERFACE *pActiveInterface[WD_USB_MAX_INTERFACES];
+};
+
+typedef enum {
+       WDU_DIR_IN     = 1,
+       WDU_DIR_OUT    = 2,
+       WDU_DIR_IN_OUT = 3
+} WDU_DIR;
+
+typedef enum {
+       PIPE_TYPE_CONTROL     = 0,
+       PIPE_TYPE_ISOCHRONOUS = 1,
+       PIPE_TYPE_BULK        = 2,
+       PIPE_TYPE_INTERRUPT   = 3
+} USB_PIPE_TYPE;
diff --git a/ships/Alu.ship b/ships/Alu.ship
new file mode 100644 (file)
index 0000000..ddd3a4e
--- /dev/null
@@ -0,0 +1,305 @@
+ship: Alu
+
+== Ports ===========================================================
+data  in:   in1
+data  in:   in2
+data  in:   inOp
+  constant IN1: 0
+  constant IN2: 1
+  constant ADD: 2
+  constant SUB: 3
+  constant MAX: 4
+  constant MIN: 5
+  constant CMP: 6
+  constant DROP1: 7
+  constant DROP2: 8
+  constant MAXMERGE: 9
+  constant AND: 10
+  constant OR: 11
+  constant XOR: 12
+
+data  out:  out
+
+
+== TeX ==============================================================
+
+{\tt Alu} is a ``two-input'' arithmetic logic unit.  It includes
+logic for performing arithmetic operations on a pair of arguments.
+Currently this includes
+addition ({\sc add}),
+subtraction ({\sc sub}),
+maximum ({\sc max}), and
+minimum ({\sc min}).
+
+\subsection*{Semantics}
+
+When a value is present at each of {\tt in1}, {\tt in2} and {\tt
+inOp}, these three values are consumed.  Based on the value consumed
+at {\tt inOp}, the requested operation is performed on the values
+consumed from {\tt in1} and {\tt in2}.  The result of this operation
+is then made available at {\tt out}.
+
+\subsection*{C-Flag}
+
+\begin{verbatim}
+IN1      - undefined; drain in1 only
+IN2      - undefined; drain in2 only
+ADD      - carry-out
+SUB      - undefined
+MAX      - if in1>in2 cflag=0 and drain in1, else cflag=1 and drain in2
+MIN      - if in1>in2 cflag=1 and drain in2, else cflag=0 and drain in1
+CMP      - if in1==in2 cflag=1, else cflag=0
+DROP1    - consume in1, produce no output
+DROP2    - consume in2, produce no output
+MAXMERGE - if (in1<0 && in2<0) consume both, emit either, cflag=undef else act as MAX
+\end{verbatim}
+
+\subsection*{To Do}
+
+The {\it link bit} and other features of \cite{ies31} are not yet
+implemented.
+
+The carry-in, carry-out, zero-test, negative-test, and overflow-test
+flags typically present in a conventional processor ALU are also not
+yet implemented.
+
+== Fleeterpreter ====================================================
+public void service() {
+  if (box_inOp.dataReadyForShip() &&
+      box_in1.dataReadyForShip() &&
+      box_in2.dataReadyForShip() &&
+      box_out.readyForDataFromShip()) {
+      long a;
+      long b;
+      long op     = box_inOp.removeDataForShip();
+      switch((int)op) {
+          case 0:
+              a = box_in1.removeDataForShip();
+              box_out.addDataFromShip(a); // IN1
+              break;
+          case 1:
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(b); // IN2
+              break;
+          case 2:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(a+b); // ADD
+              break;
+          case 3:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(a-b); // SUB
+              break;
+
+          case 9: // MAXMERGE
+              if (box_in1.peekDataForShip()<0 && box_in2.peekDataForShip()<0) {
+                a = box_in1.removeDataForShip();
+                b = box_in2.removeDataForShip();
+                box_out.addDataFromShip(a, false);
+                break;
+              }
+              // fall through to MAX
+          case 4:
+              a = box_in1.peekDataForShip();
+              b = box_in2.peekDataForShip();
+              box_out.addDataFromShip(Math.max(a,b), !(a>b)); // MAX
+              if (a>b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+              break;
+
+          case 5:
+              a = box_in1.peekDataForShip();
+              b = box_in2.peekDataForShip();
+              box_out.addDataFromShip(Math.min(a,b), a>b); // MIN
+              if (a<b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+              break;
+          case 6:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(0, a==b); // CMP
+              break;
+/*
+          case 7:
+              box_in1.removeDataForShip();      // DROP1
+              break;
+          case 8:
+              box_in2.removeDataForShip();      // DROP2
+              break;
+*/
+          case 10:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(a & b); // CMP
+              break;
+          case 11:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(a | b); // CMP
+              break;
+          case 12:
+              a = box_in1.removeDataForShip();
+              b = box_in2.removeDataForShip();
+              box_out.addDataFromShip(a ^ b); // CMP
+              break;
+          default:
+              throw new RuntimeException("invalid opcode: " + op);
+      }
+  }
+}
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  wire [`WORDWIDTH:0]     sum;
+  wire                    cin;
+  wire [(`WORDWIDTH-1):0] in2_inverted;
+
+  wire [(`WORDWIDTH-1):0] res;
+  wire                    isplus;
+  wire                    eq;
+  wire                    cout;
+
+  wire [4:0]              inOp_d_trunc;
+  assign                  inOp_d_trunc = inOp_d[4:0];
+
+  assign isplus        = inOp_d_trunc[4:0]==2;
+  assign cin           = isplus ? 0 : 1;
+  assign in2_inverted  = isplus ? in2_d : ~in2_d;
+  assign sum           = {in1_d,cin} + {in2_inverted,cin};
+  assign res           = sum[`WORDWIDTH:1];
+  assign greater       = !res[`WORDWIDTH-1];
+  assign both_negative = in1_d[`WORDWIDTH-1] && in2_d[`WORDWIDTH-1];
+  assign eq            = in1_d == in2_d;
+  assign cout          = sum[`WORDWIDTH];
+
+  reg out_draining;
+
+  assign out_d_[`WORDWIDTH] =
+          (inOp_d_trunc==0) ? 1'b0 :
+          (inOp_d_trunc==1) ? 1'b0 :
+          (inOp_d_trunc==2) ? cout :
+          (inOp_d_trunc==3) ? cout :
+          (inOp_d_trunc==4) ? ~greater :
+          (inOp_d_trunc==5) ?  greater :
+          (inOp_d_trunc==6) ?  eq :
+          (inOp_d_trunc==9) ? ~greater :
+          0;
+
+  assign out_d_[(`WORDWIDTH-1):0] =
+          (inOp_d_trunc==0) ? (in1_d)  :
+          (inOp_d_trunc==1) ? (in2_d)  :
+          (inOp_d_trunc==2) ? (res)  :
+          (inOp_d_trunc==3) ? (res)  :
+          (inOp_d_trunc==4) ? (greater ? in1_d : in2_d)  :
+          (inOp_d_trunc==5) ? (greater ? in2_d : in1_d)  :
+          (inOp_d_trunc==6) ? {{ (`WORDWIDTH-1) {1'b0 }}, eq  } :
+          (inOp_d_trunc==9) ? (both_negative ? in1_d : (greater ? in1_d : in2_d)) :
+          (inOp_d_trunc==10) ? (in1_d & in2_d) :
+          (inOp_d_trunc==11) ? (in1_d | in2_d) :
+          (inOp_d_trunc==12) ? (in1_d ^ in2_d) :
+          0;
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      out_draining <= 0;
+    end else begin
+      `cleanup
+      if (out_draining && `out_empty) begin
+        `drain_inOp
+        out_draining <= 0;
+        if      (inOp_d_trunc==0) `drain_in1
+        else if (inOp_d_trunc==1) `drain_in2
+        else if (inOp_d_trunc==9 &&  both_negative) begin `drain_in1 `drain_in2 end
+        else if (inOp_d_trunc==4 &&  greater) `drain_in1
+        else if (inOp_d_trunc==5 &&  greater) `drain_in2
+        else if (inOp_d_trunc==9 &&  greater) `drain_in1
+        else if (inOp_d_trunc==4 && !greater) `drain_in2
+        else if (inOp_d_trunc==5 && !greater) `drain_in1
+        else if (inOp_d_trunc==9 && !greater) `drain_in2
+        else begin
+          `drain_in1
+          `drain_in2
+        end
+      end
+      if (!out_draining && `out_empty && `in1_full && `in2_full && `inOp_full) begin
+        `fill_out
+        out_draining <= 1;
+      end
+    end
+  end
+
+== Test ==============================================================================
+
+// FIXME: need test for ADD carry-out c-flag
+
+#ship debug : Debug
+#ship alu   : Alu
+
+#expect 17
+#expect 1
+#expect 9
+#expect 8
+#expect 8
+#expect 1
+#expect 9
+#expect 0
+#expect 0
+#expect 1
+
+debug.in:   set ilc=*;  recv, deliver;
+alu.in1:
+  set word= 9;
+  set ilc=5;
+  deliver;
+  set word= 9;
+  deliver;
+
+alu.in2:
+  set word= 8;
+  set ilc=5;
+  deliver;
+  set word= 9;
+  deliver;
+
+alu.out:
+  set ilc=4;
+  collect, send to debug.in;
+alu.inOp:
+ set word= Alu.inOp[ADD]; deliver;
+ set word= Alu.inOp[SUB]; deliver;
+ set word= Alu.inOp[IN1]; deliver;
+ set word= Alu.inOp[IN2]; deliver;
+ set word= Alu.inOp[MIN]; deliver;
+ set word= Alu.inOp[MAX]; deliver;
+ set word= Alu.inOp[CMP]; deliver;
+ set word= Alu.inOp[CMP]; deliver;
+
+alu.out:
+  collect, send to debug.in;        // MIN
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+  collect, send to debug.in;        // MAX
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+  collect;        // CMP
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+  collect;        // CMP
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Button.ship b/ships/Button.ship
new file mode 100644 (file)
index 0000000..1a963eb
--- /dev/null
@@ -0,0 +1,61 @@
+ship: Null
+
+== Ports ===========================================================
+data  out:  out
+
+percolate down:  gpio_sw_c    1
+
+
+== Constants ========================================================
+
+== UCF ==============================================================================
+NET  gpio_sw_c            LOC="AJ6" | IOSTANDARD="LVCMOS33";   # Bank 18, Vcco=3.3V, No DCI
+
+== TeX ==============================================================
+== Fleeterpreter ====================================================
+    public void service() {
+    }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  assign out_d_ = 0;
+  reg [20:0] count;
+  reg last_state;
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      last_state <= gpio_sw_c;
+    end else begin
+      `cleanup
+      if (count==0) begin
+        if (`out_empty && gpio_sw_c && !last_state) begin
+          `fill_out
+        end
+        count <= 51200;
+        last_state <= gpio_sw_c;
+      end else begin
+        count <= count-1;
+      end
+    end
+  end
+
+== Test =================================================================
+
+#skip
+#expect 0
+
+#ship button : Button
+#ship debug : Debug
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+button.out:
+  collect, send to debug.in;
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/CarrySaveAdder.ship b/ships/CarrySaveAdder.ship
new file mode 100644 (file)
index 0000000..03722c6
--- /dev/null
@@ -0,0 +1,153 @@
+ship: CarrySaveAdder
+
+== Ports ===========================================================
+in:   in
+
+out:  out
+
+  
+== TeX ==============================================================
+
+The Carry-Save Adder computes the carry-save sum of three input
+values, provided sequentially at {\tt in}, and produces.
+
+
+== Fleeterpreter ====================================================
+
+int state = 0;
+long temp;
+long out;
+public void reset() {
+  super.reset();
+  state = 0;
+  temp = 0;
+  out = 0;
+}
+private long maj(long a, long b, long c) {
+  long ret = 0;
+  for(int i=0; i<64; i++) {
+    boolean a_ = (a&(1L<<i))!=0L;
+    boolean b_ = (b&(1L<<i))!=0L;
+    boolean c_ = (c&(1L<<i))!=0L;
+    if ( (a_ && b_) || (b_ && c_) || (a_ && c_) )
+      ret |= (1L << i);
+  }
+  return ret;
+}
+public void service() {
+  if (!box_out.readyForDataFromShip()) return;
+  if (state!=3 && !box_in.dataReadyForShip()) return;
+  switch(state) {
+    case 0: out = box_in.removeDataForShip(); break;
+    case 1: temp = box_in.removeDataForShip(); break;
+    case 2:
+      long in = box_in.removeDataForShip();
+      long mm = maj(temp, out, in);
+      box_out.addDataFromShip(mm << 1, ((mm >> (getFleet().getWordWidth()-1)) & 1L)!=0);
+      temp = (temp ^ out) ^ in;
+      break;
+    case 3: box_out.addDataFromShip(temp, false); break;
+  }
+  state = (state+1) % 4;
+}
+
+
+== FPGA ==============================================================
+
+  reg [(`WORDWIDTH-1):0] temp;
+  reg [(`WORDWIDTH):0]   out_d;
+  reg [1:0] state;
+  initial state = 0;
+  assign out_d_ = out_d;
+
+  wire [(`WORDWIDTH-1):0] majority;
+  wire [(`WORDWIDTH-1):0] xors;
+  genvar i;
+  generate
+    for(i=0; i<`WORDWIDTH; i=i+1) begin : OUT
+      assign majority[i] = (temp[i] & out_d[i]) | (in_d[i] & out_d[i]) | (temp[i] & in_d[i]);
+      assign xors[i]     = temp[i] ^ out_d[i] ^ in_d[i];
+    end
+  endgenerate
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      state <= 0;
+    end else begin
+      `cleanup
+      if (`out_empty && state==3) begin
+        out_d <= { 1'b0, temp };
+        `fill_out
+        state <= state + 1;
+      end else if (`in_full && `out_empty) begin
+        if (state == 0) begin
+          out_d <= { 1'b0, in_d };
+        end else if (state == 1) begin
+          temp <= in_d;
+        end else if (state == 2) begin
+          out_d <= { majority[`WORDWIDTH-1:0], 1'b0 };
+          temp  <= xors;
+          `fill_out
+        end
+        state <= state + 1;
+        `drain_in
+      end
+    end
+  end
+
+== Test ==============================================================
+// expected output
+#expect 0x3c4bc6
+#expect 0x1796d2
+#expect 0x24b4f4
+#expect 0x3c4bc6
+
+// ships required in order to run this code
+#ship debug        : Debug
+#ship csa          : CarrySaveAdder
+#ship alu          : Alu
+#ship fifo         : Fifo
+
+fifo.in:
+   set word=1018217;  deliver;
+   set word=771820;   deliver;
+   set word=2161521;  deliver;
+fifo.out:
+   collect, send to csa.in; send to alu.in1;
+   collect, send to csa.in; send to alu.in2;
+   collect, send to csa.in; send to alu.in2;
+
+alu.in1: set ilc=4; recv, deliver;
+alu.in2: set ilc=4; recv, deliver;
+alu.inOp:
+   set word=Alu.inOp[ADD];
+   set ilc=4; deliver;   
+alu.out:
+   collect, send to alu.in1;
+   collect; send to debug.in;
+   recv token;
+   collect; send to debug.in;
+
+csa.in:
+   set ilc=*;
+   recv, deliver;
+
+csa.out:
+   recv token;
+   collect, send to debug.in;
+   send to alu.in1;
+   collect, send to debug.in;
+   send to alu.in2;
+
+debug.in:
+   recv, deliver;
+   send token to csa.out;
+   set ilc=2;
+   recv, deliver;
+   send token to alu.out;
+   recv, deliver;
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Counter.ship b/ships/Counter.ship
new file mode 100644 (file)
index 0000000..803105d
--- /dev/null
@@ -0,0 +1,243 @@
+ship: Counter
+
+== Ports ===========================================================
+data  in:   in1
+data  in:   in2
+data  in:   inOp
+  constant REPEAT_C1_V1: 0
+  constant REPEAT_C1_V2: 1
+  constant REPEAT_C2_V1: 2
+  constant REPEAT_C2_V2: 3
+  constant PASS_C1_V1:   4
+  constant PASS_C1_V2:   5
+  constant PASS_C2_V1:   6
+  constant PASS_C2_V2:   7
+  constant DROP_C1_V1:   8
+  constant DROP_C1_V2:   9
+  constant DROP_C2_V1:   10
+  constant DROP_C2_V2:   11
+  constant COUNT:        12
+data  out:  out
+
+== Fleeterpreter ====================================================
+
+boolean full = false;
+boolean op_count = false;
+boolean op_repeat = false;
+boolean op_pass = false;
+boolean op_drop = false;
+boolean op_c1 = false;
+boolean op_c2 = false;
+boolean op_v1 = false;
+boolean op_v2 = false;
+long temp = 0;
+
+public void reset() {
+  super.reset();
+  full = false;
+  temp = 0;
+}
+public void service() {
+
+  if (full) {
+    if (temp < 0) {
+      temp = 0;
+      full = false;
+      box_inOp.removeDataForShip();
+      if (op_count) box_in2.removeDataForShip();
+      else if (op_repeat && op_v1) box_in1.removeDataForShip();
+      else if (op_repeat && op_v2) box_in2.removeDataForShip();
+
+    } else if (box_out.readyForDataFromShip()) {
+      if (op_count) {
+        box_out.addDataFromShip(temp, (temp - box_in2.peekDataForShip()) < 0);
+        temp = temp - box_in2.peekDataForShip();
+      } else if (op_v1 && box_in1.dataReadyForShip()) {
+        if (op_drop) { box_in1.removeDataForShip(); temp--; }
+        else         { box_out.addDataFromShip(op_pass ? box_in1.removeDataForShip() : box_in1.peekDataForShip(), temp<=0); temp--; }
+      } else if (op_v2 && box_in2.dataReadyForShip()) {
+        if (op_drop) { box_in2.removeDataForShip(); temp--; }
+        else         { box_out.addDataFromShip(op_pass ? box_in2.removeDataForShip() : box_in2.peekDataForShip(), temp<=0); temp--; }
+      }
+      
+    }
+
+  } else if (box_inOp.dataReadyForShip()) {
+    long op   = box_inOp.peekDataForShip();
+    op_count  = (op & 15)==12;
+    op_repeat = ((op>>2) & 3)==0;
+    op_pass   = ((op>>2) & 3)==1;
+    op_drop   = ((op>>2) & 3)==2;
+    op_c1     = (op_repeat || op_pass || op_drop) && !(((op>>1)&1)!=0);
+    op_c2     = (op_repeat || op_pass || op_drop) &&  (((op>>1)&1)!=0);
+    op_v1     = (op_repeat || op_pass || op_drop) && !(((op>>0)&1)!=0);
+    op_v2     = (op_repeat || op_pass || op_drop) &&  (((op>>0)&1)!=0);
+
+    if (op_count && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
+    if (op_c1    &&  !box_in1.dataReadyForShip()) return;
+    if (op_c2    &&  !box_in2.dataReadyForShip()) return;
+    
+    full = true;
+
+    if (op_count) temp = box_in1.removeDataForShip() - box_in2.peekDataForShip();
+    if (op_c1)    temp = box_in1.removeDataForShip()-1;
+    if (op_c2)    temp = box_in2.removeDataForShip()-1;
+  }
+}
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  wire [3:0]              inOp_d_trunc;
+  assign                  inOp_d_trunc = inOp_d[3:0];
+
+  reg [`WORDWIDTH-1:0] temp;
+  initial temp   = {`WORDWIDTH{1'b1}};
+  reg     out_draining;
+  reg     full;
+  initial full = 0;
+  reg c_flag;
+  wire    op_count;  assign op_count  = inOp_d_trunc==12;
+  wire    op_repeat; assign op_repeat = inOp_d[3:2]==0;
+  wire    op_pass;   assign op_pass   = inOp_d[3:2]==1;
+  wire    op_drop;   assign op_drop   = inOp_d[3:2]==2;
+  wire    op_c1;     assign op_c1     = (op_repeat || op_pass || op_drop) && !inOp_d[1];
+  wire    op_c2;     assign op_c2     = (op_repeat || op_pass || op_drop) &&  inOp_d[1];
+  wire    op_v1;     assign op_v1     = (op_repeat || op_pass || op_drop) && !inOp_d[0];
+  wire    op_v2;     assign op_v2     = (op_repeat || op_pass || op_drop) &&  inOp_d[0];
+
+  wire [`WORDWIDTH-1:0] pre_out;
+  assign  pre_out = op_v1 ? in1_d : op_v2 ? in2_d : temp;
+  assign  out_d_  = { c_flag, pre_out };
+
+  // FIXME: REPEAT with a count of zero will not work properly
+
+  wire [`WORDWIDTH-1:0] temp_minus_in2;
+  assign temp_minus_in2 = (temp - in2_d);
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      full <= 0;
+      out_draining <= 0;
+      c_flag <= 0;
+    end else begin
+      `cleanup
+      if (`inOp_empty)         full   <= 0;
+      if (out_draining && `out_empty) begin
+        if (op_count) temp   <= temp_minus_in2;
+        else          temp   <= temp - 1;
+        if (op_pass && op_v1) `drain_in1
+        if (op_pass && op_v2) `drain_in2
+        out_draining <= 0;
+      end else if (`inOp_full) begin
+        if (!full) begin
+          if (op_count && `in1_full && `in2_full) begin
+            temp  <= in1_d[`WORDWIDTH-1:0] - in2_d[`WORDWIDTH-1:0];
+            `drain_in1
+            full  <= 1;
+          end else if (op_c1 && `in1_full) begin
+            temp  <= in1_d[`WORDWIDTH-1:0]-1;
+            `drain_in1
+            full  <= 1;
+          end else if (op_c2 && `in2_full) begin
+            temp  <= in2_d[`WORDWIDTH-1:0]-1;
+            `drain_in2
+            full  <= 1;
+          end
+        end else if (temp[`WORDWIDTH-1]) begin
+          full <= 0;
+          `drain_inOp
+          if (op_count) begin
+            `drain_in2
+          end else if (op_repeat && op_v1) begin
+            `drain_in1
+          end else if (op_repeat && op_v2) begin
+            `drain_in2
+          end
+        end else if (`out_empty) begin
+          if (op_count) begin
+            `fill_out
+            out_draining <= 1;
+            c_flag <= temp_minus_in2[`WORDWIDTH-1];
+          end else if (op_v1 && `in1_full) begin
+            if (op_drop)    begin `drain_in1 temp <= temp-1; end
+            else            begin `fill_out out_draining <= 1; end
+            c_flag <= (temp==0);
+          end else if (op_v2 && `in2_full) begin
+            if (op_drop)    begin `drain_in2 temp <= temp-1; end
+            else            begin `fill_out out_draining <= 1; end
+            c_flag <= (temp==0);
+          end
+        end
+      end
+    end
+  end
+
+== Test =================================================================
+
+#ship counter : Counter
+#ship debug   : Debug
+
+#expect 6
+#expect 3
+#expect 0
+#expect -1
+#expect 2
+#expect 1
+#expect 0
+#expect -1
+#expect 2
+#expect 2
+#expect 2
+#expect 2
+#expect -1
+#expect 9
+#expect 9
+#expect 9
+#expect -1
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+counter.in1:
+  set word=9;
+  deliver;
+  set word=3;
+  deliver;
+  set word=4;
+  deliver;
+  set word=3;
+  deliver;
+
+counter.in2:
+  set word=3;
+  deliver;
+  set word=1;
+  deliver;
+  set word=2;
+  deliver;
+  set word=9;
+  deliver;
+
+counter.inOp:
+  set word=12;
+  deliver;
+  deliver;
+  set word=1;
+  deliver;
+  deliver;
+
+counter.out:
+  head;
+  collect, send to debug.in;
+  set flags a=c, b=b;
+  set word=-1;
+  [a] send to debug.in;
+  tail;
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/DDR2.ship b/ships/DDR2.ship
new file mode 100644 (file)
index 0000000..4689e4e
--- /dev/null
@@ -0,0 +1,634 @@
+ship: DDR2
+
+== Ports ===========================================================
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+percolate down:  clk200_p      1
+
+percolate inout: ddr2_dq       64
+percolate inout: ddr2_dqs      8
+percolate inout: ddr2_dqs_n    8
+percolate up:    ddr2_a        13
+percolate up:    ddr2_ba       2
+percolate up:    ddr2_ras_n    1
+percolate up:    ddr2_cas_n    1
+percolate up:    ddr2_we_n     1
+percolate up:    ddr2_cs_n     1
+percolate up:    ddr2_odt      1
+percolate up:    ddr2_cke      1
+percolate up:    ddr2_dm       8
+percolate up:    ddr2_ck       2
+percolate up:    ddr2_ck_n     2
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+    public void service() { }
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+// clocking //////////////////////////////////////////////////////////////////////////////
+
+wire clk0;
+wire clkdiv0;
+wire clk0_unbuffered;
+wire clkdiv0_unbuffered;
+wire dcm_lock;
+
+BUFG clk200_p_buf (.I(clk200_p),            .O(clk200_p_buffered));
+BUFG clk0_fb_buf  (.I(clk0_unbuffered),     .O(clk0_fb));
+BUFG clk0_fb_buf2 (.I(clk0_unbuffered),     .O(clk0));
+BUFG clkdiv0_bufg (.I(clkdiv0_unbuffered),  .O(clkdiv0));
+
+DCM
+ #(
+   .CLKIN_PERIOD          (10.0),
+   .DLL_FREQUENCY_MODE    ("LOW"),
+   .DUTY_CYCLE_CORRECTION ("TRUE"),
+   .CLKDV_DIVIDE          (2),
+   .FACTORY_JF            (16'hF0F0)
+  ) ddr2_dcm (
+    .CLKIN     (clk),
+    .CLKFB     (clk0_fb),
+    .CLKDV     (clkdiv0_unbuffered),
+    .CLK0      (clk0_unbuffered),
+    .CLK90     (clk90),
+    .LOCKED    (dcm_lock),
+    .RST       (rst)
+  );
+
+// controller instance ////////////////////////////////////////////////////////////////////////
+
+wire        phy_init_done;
+wire        app_wdf_afull;
+wire        app_af_afull;
+reg         app_wdf_wren;
+reg  [63:0] app_wdf_data;
+reg         app_af_wren;
+reg  [2:0]  app_af_cmd;
+reg  [30:0] app_af_addr;
+wire        rd_data_valid;
+wire [63:0] rd_data_fifo_out;
+
+reg         read_waiting;
+reg  [7:0]  mask;
+reg  [6:0]  burst_count;
+
+ddr2_sdram # (
+    .BANK_WIDTH(2),                    // # of memory bank addr bits.
+    .CKE_WIDTH(1),                     // # of memory clock enable outputs.
+    .CLK_WIDTH(2),                     // # of clock outputs.
+    .COL_WIDTH(10),                    // # of memory column bits.
+    .CS_NUM(1),                        // # of separate memory chip selects.
+    .CS_WIDTH(1),                      // # of total memory chip selects.
+    .CS_BITS(0),                       // set to log2(CS_NUM) (rounded up).
+    .DM_WIDTH(8),                      // # of data mask bits.
+    .DQ_WIDTH(64),                     // # of data width.
+    .DQ_PER_DQS(8),                    // # of DQ data bits per strobe.
+    .DQS_WIDTH(8),                     // # of DQS strobes.
+    .DQ_BITS(6),                       // set to log2(DQS_WIDTH*DQ_PER_DQS).
+    .DQS_BITS(3),                      // set to log2(DQS_WIDTH).
+    .ODT_WIDTH(1),                     // # of memory on-die term enables.
+    .ROW_WIDTH(13),                    // # of memory row and # of addr bits.
+    .ADDITIVE_LAT(0),                  // additive write latency.
+    .BURST_LEN(4),                     // burst length (in double words).
+    .BURST_TYPE(0),                    // burst type (=0 seq; =1 interleaved).
+    .CAS_LAT(3),                       // CAS latency.
+    .ECC_ENABLE(0),                    // enable ECC (=1 enable).
+    .APPDATA_WIDTH(128),               // # of usr read/write data bus bits.
+    .MULTI_BANK_EN(1),                 // Keeps multiple banks open. (= 1 enable).
+    .TWO_T_TIME_EN(1),                 // 2t timing for unbuffered dimms.
+    .ODT_TYPE(1),                      // ODT (=0(none),=1(75),=2(150),=3(50)).
+    .REDUCE_DRV(0),                    // reduced strength mem I/O (=1 yes).
+    .REG_ENABLE(0),                    // registered addr/ctrl (=1 yes).
+    .TREFI_NS(7800),                   // auto refresh interval (ns).
+    .TRAS(40000),                      // active->precharge delay.
+    .TRCD(15000),                      // active->read/write delay.
+    .TRFC(105000),                     // refresh->refresh, refresh->active delay.
+    .TRP(15000),                       // precharge->command delay.
+    .TRTP(7500),                       // read->precharge delay.
+    .TWR(15000),                       // used to determine write->precharge.
+    .TWTR(7500),                       // write->read delay.
+    .HIGH_PERFORMANCE_MODE("TRUE"),    // # = TRUE, the IODELAY performance mode is set to high.
+                                       // # = FALSE, the IODELAY performance mode is set to low.
+    .SIM_ONLY(0),                      // = 1 to skip SDRAM power up delay.
+    .DEBUG_EN(0),                      // Enable debug signals/controls.
+                                       // When this parameter is changed from 0 to 1,
+                                       // make sure to uncomment the coregen commands
+                                       // in ise_flow.bat or create_ise.bat files in
+                                       // par folder.
+    .CLK_PERIOD(10000),                // Core/Memory clock period (in ps).
+    .DQS_IO_COL(16'b0000000000000000), // I/O column location of DQS groups
+                                       // (=0, left; =1 center, =2 right).
+    .DQ_IO_MS(64'b01110101_00111101_00001111_00011110_00101110_11000011_11000001_10111100),   
+                                       // Master/Slave location of DQ I/O (=0 slave).
+    .RST_ACT_LOW(1)                    // =1 for active low reset, =0 for active high.
+) ddr2_sdram (
+    .sys_rst_n                 (!rst),
+
+    .ddr2_dq                   (ddr2_dq),
+    .ddr2_a                    (ddr2_a),
+    .ddr2_ba                   (ddr2_ba),
+    .ddr2_ras_n                (ddr2_ras_n),
+    .ddr2_cas_n                (ddr2_cas_n),
+    .ddr2_we_n                 (ddr2_we_n),
+    .ddr2_cs_n                 (ddr2_cs_n),
+    .ddr2_odt                  (ddr2_odt),
+    .ddr2_cke                  (ddr2_cke),
+    .ddr2_dm                   (ddr2_dm),
+    .ddr2_dqs                  (ddr2_dqs),
+    .ddr2_dqs_n                (ddr2_dqs_n),
+    .ddr2_ck                   (ddr2_ck),
+    .ddr2_ck_n                 (ddr2_ck_n),
+
+    .phy_init_done             (phy_init_done),
+
+    .app_wdf_afull             (app_wdf_afull),
+    .app_af_afull              (app_af_afull),
+    .rd_data_valid             (rd_data_valid),
+    .rd_data_fifo_out          (rd_data_fifo_out),
+
+    .app_wdf_wren              ((~phy_init_done) ? 0 : app_wdf_wren),
+    .app_wdf_data              ((~phy_init_done) ? 0 : app_wdf_data),
+    .app_wdf_mask_data         ((~phy_init_done) ? 0 : mask),
+
+    .app_af_wren               ((~phy_init_done) ? 0 : app_af_wren),
+    .app_af_cmd                (app_af_cmd),
+    .app_af_addr               (app_af_addr),
+
+    .dcm_lock                  (dcm_lock),
+    .clk0                      (clk0),
+    .clk90                     (clk90),
+    .clkdiv0                   (clkdiv0),
+
+    .clk200                    (clk200_p_buffered)
+  );
+
+// custom code //////////////////////////////////////////////////////////////////////////////
+
+reg  [37:0] out_d;
+assign out_d_ = out_d;
+
+// grossly inefficient -- always uses only the first word of a burst!
+always @(posedge clk) begin
+  if (rst) begin
+    `reset
+    app_wdf_wren <= 0;
+    app_af_wren  <= 0;
+    read_waiting <= 0;
+    burst_count  <= 0;
+
+  end else begin
+    `cleanup
+
+    mask <= 8'b11111111;
+    if (burst_count == 0 || burst_count == 1) begin
+      app_wdf_wren <= 0;
+      app_af_wren  <= 0;
+    end else if ((burst_count > 1) && (app_af_cmd == 3'b000)) begin
+      app_af_wren  <= ~burst_count[0];
+    end
+
+    if (burst_count > 0) begin
+      burst_count <= burst_count - 1;
+    end else if ((~read_waiting) && rd_data_valid) begin
+      /* wait */
+    end else if (read_waiting) begin
+      if (rd_data_valid) begin
+        read_waiting <= 0;
+        out_d <= { 1'b0, rd_data_fifo_out[36:0] };
+        `fill_out
+      end
+    end else if (app_wdf_afull || app_af_afull) begin
+      /* wait */
+    end else if (`inAddrWrite_full && `inDataWrite_full && `out_empty) begin
+      `drain_inDataWrite
+      `drain_inAddrWrite
+      app_wdf_data   <= inDataWrite_d;
+      app_af_addr    <= { inAddrWrite_d, 2'b00 };
+      app_af_cmd     <= 3'b000;
+      app_af_wren    <= 1;
+      app_wdf_wren   <= 1;
+      burst_count    <= 7;
+      out_d          <= { 1'b1, 37'b0 };
+      mask           <= 8'b00000000;
+      `fill_out
+    end else if (`inAddrRead_full && `out_empty) begin
+      `drain_inAddrRead
+      app_af_addr    <= { inAddrRead_d, 2'b00 };
+      app_af_cmd     <= 3'b001;
+      app_af_wren    <= 1;
+      burst_count    <= 3;
+      read_waiting   <= 1;
+    end
+  end
+end
+
+== UCF ==============================================================
+
+Net clk200_p PERIOD =  5 ns HIGH 50%;  # 200Mhz
+
+#NET "*/u_ddr2_infrastructure/sys_clk_ibufg" TNM_NET =  "SYS_CLK";
+Net "ddr2_0/clk0" TNM_NET = "SYS_CLK";
+TIMESPEC "TS_SYS_CLK" = PERIOD "SYS_CLK" 10 ns HIGH 50 %;
+
+#NET "*/u_ddr2_infrastructure/clk200_ibufg" TNM_NET = "SYS_CLK_200";
+Net clk200_p TNM_NET = "SYS_CLK_200";
+TIMESPEC "TS_SYS_CLK_200" = PERIOD "SYS_CLK_200" 5 ns HIGH 50 %;
+
+# suggested by
+# http://www.xilinx.com/support/answers/31606.htm
+# NET "clk_0" TNM_NET = "SYS_clk_0";
+# TIMESPEC "TS_SYS_clk_0" = PERIOD "SYS_clk_0" 5 ns HIGH 50 %;
+# NET "clk_90" TNM_NET = "SYS_clk_90";
+# TIMESPEC "TS_SYS_clk_90" = PERIOD "SYS_clk_90" "TS_SYS_clk_0" PHASE 1.25 ns HIGH 50 %;
+
+################################################################################
+# I/O STANDARDS
+################################################################################
+
+NET  "ddr2_dq[*]"                               IOSTANDARD = SSTL18_II_DCI;
+NET  "ddr2_a[*]"                                IOSTANDARD = SSTL18_II;
+NET  "ddr2_ba[*]"                               IOSTANDARD = SSTL18_II;
+NET  "ddr2_ras_n"                               IOSTANDARD = SSTL18_II;
+NET  "ddr2_cas_n"                               IOSTANDARD = SSTL18_II;
+NET  "ddr2_we_n"                                IOSTANDARD = SSTL18_II;
+NET  "ddr2_cs_n"                             IOSTANDARD = SSTL18_II;
+NET  "ddr2_odt"                              IOSTANDARD = SSTL18_II;
+NET  "ddr2_cke"                              IOSTANDARD = SSTL18_II;
+NET  "ddr2_dm[*]"                               IOSTANDARD = SSTL18_II;
+#NET  "sys_clk_p"                                IOSTANDARD = LVDS_25 | DIFF_TERM = TRUE;
+#NET  "sys_clk_n"                                IOSTANDARD = LVDS_25 | DIFF_TERM = TRUE;
+#NET  "clk200_p"                                 IOSTANDARD = LVDS_25 | DIFF_TERM = TRUE;
+#NET  "clk200_n"                                 IOSTANDARD = LVDS_25 | DIFF_TERM = TRUE;
+#NET  "sys_rst_n"                                IOSTANDARD = LVCMOS18;
+#NET  "phy_init_done"                           IOSTANDARD = LVCMOS18;
+#NET  "error"                                   IOSTANDARD = LVCMOS18;
+NET  "ddr2_dqs[*]"                              IOSTANDARD = DIFF_SSTL18_II_DCI;
+NET  "ddr2_dqs_n[*]"                            IOSTANDARD = DIFF_SSTL18_II_DCI;
+NET  "ddr2_ck[*]"                               IOSTANDARD = DIFF_SSTL18_II;
+NET  "ddr2_ck_n[*]"                             IOSTANDARD = DIFF_SSTL18_II;
+
+################################################################################
+# Location Constraints
+################################################################################
+
+NET  "ddr2_dq[0]"                                LOC = "AF30" ;              #Bank 17
+NET  "ddr2_dq[1]"                                LOC = "AK31" ;              #Bank 17
+NET  "ddr2_dq[2]"                                LOC = "AF31" ;              #Bank 17
+NET  "ddr2_dq[3]"                                LOC = "AD30" ;              #Bank 17
+NET  "ddr2_dq[4]"                                LOC = "AJ30" ;              #Bank 17
+NET  "ddr2_dq[5]"                                LOC = "AF29" ;              #Bank 17
+NET  "ddr2_dq[6]"                                LOC = "AD29" ;              #Bank 17
+NET  "ddr2_dq[7]"                                LOC = "AE29" ;              #Bank 17
+NET  "ddr2_dq[8]"                                LOC = "AH27" ;              #Bank 21
+NET  "ddr2_dq[9]"                                LOC = "AF28" ;              #Bank 21
+NET  "ddr2_dq[10]"                               LOC = "AH28" ;              #Bank 21
+NET  "ddr2_dq[11]"                               LOC = "AA28" ;              #Bank 21
+NET  "ddr2_dq[12]"                               LOC = "AG25" ;              #Bank 21
+NET  "ddr2_dq[13]"                               LOC = "AJ26" ;              #Bank 21
+NET  "ddr2_dq[14]"                               LOC = "AG28" ;              #Bank 21
+NET  "ddr2_dq[15]"                               LOC = "AB28" ;              #Bank 21
+NET  "ddr2_dq[16]"                               LOC = "AC28" ;              #Bank 21
+NET  "ddr2_dq[17]"                               LOC = "AB25" ;              #Bank 21
+NET  "ddr2_dq[18]"                               LOC = "AC27" ;              #Bank 21
+NET  "ddr2_dq[19]"                               LOC = "AA26" ;              #Bank 21
+NET  "ddr2_dq[20]"                               LOC = "AB26" ;              #Bank 21
+NET  "ddr2_dq[21]"                               LOC = "AA24" ;              #Bank 21
+NET  "ddr2_dq[22]"                               LOC = "AB27" ;              #Bank 21
+NET  "ddr2_dq[23]"                               LOC = "AA25" ;              #Bank 21
+NET  "ddr2_dq[24]"                               LOC = "AC29" ;              #Bank 17
+NET  "ddr2_dq[25]"                               LOC = "AB30" ;              #Bank 17
+NET  "ddr2_dq[26]"                               LOC = "W31" ;       #Bank 17
+NET  "ddr2_dq[27]"                               LOC = "V30" ;       #Bank 17
+NET  "ddr2_dq[28]"                               LOC = "AC30" ;              #Bank 17
+NET  "ddr2_dq[29]"                               LOC = "W29" ;       #Bank 17
+NET  "ddr2_dq[30]"                               LOC = "V27" ;       #Bank 17
+NET  "ddr2_dq[31]"                               LOC = "W27" ;       #Bank 17
+NET  "ddr2_dq[32]"                               LOC = "V29" ;       #Bank 17
+NET  "ddr2_dq[33]"                               LOC = "Y27" ;       #Bank 17
+NET  "ddr2_dq[34]"                               LOC = "Y26" ;       #Bank 17
+NET  "ddr2_dq[35]"                               LOC = "W24" ;       #Bank 17
+NET  "ddr2_dq[36]"                               LOC = "V28" ;       #Bank 17
+NET  "ddr2_dq[37]"                               LOC = "W25" ;       #Bank 17
+NET  "ddr2_dq[38]"                               LOC = "W26" ;       #Bank 17
+NET  "ddr2_dq[39]"                               LOC = "V24" ;       #Bank 17
+NET  "ddr2_dq[40]"                               LOC = "R24" ;       #Bank 19
+NET  "ddr2_dq[41]"                               LOC = "P25" ;       #Bank 19
+NET  "ddr2_dq[42]"                               LOC = "N24" ;       #Bank 19
+NET  "ddr2_dq[43]"                               LOC = "P26" ;       #Bank 19
+NET  "ddr2_dq[44]"                               LOC = "T24" ;       #Bank 19
+NET  "ddr2_dq[45]"                               LOC = "N25" ;       #Bank 19
+NET  "ddr2_dq[46]"                               LOC = "P27" ;       #Bank 19
+NET  "ddr2_dq[47]"                               LOC = "N28" ;       #Bank 19
+NET  "ddr2_dq[48]"                               LOC = "M28" ;       #Bank 19
+NET  "ddr2_dq[49]"                               LOC = "L28" ;       #Bank 19
+NET  "ddr2_dq[50]"                               LOC = "F25" ;       #Bank 19
+NET  "ddr2_dq[51]"                               LOC = "H25" ;       #Bank 19
+NET  "ddr2_dq[52]"                               LOC = "K27" ;       #Bank 19
+NET  "ddr2_dq[53]"                               LOC = "K28" ;       #Bank 19
+NET  "ddr2_dq[54]"                               LOC = "H24" ;       #Bank 19
+NET  "ddr2_dq[55]"                               LOC = "G26" ;       #Bank 19
+NET  "ddr2_dq[56]"                               LOC = "G25" ;       #Bank 19
+NET  "ddr2_dq[57]"                               LOC = "M26" ;       #Bank 19
+NET  "ddr2_dq[58]"                               LOC = "J24" ;       #Bank 19
+NET  "ddr2_dq[59]"                               LOC = "L26" ;       #Bank 19
+NET  "ddr2_dq[60]"                               LOC = "J27" ;       #Bank 19
+NET  "ddr2_dq[61]"                               LOC = "M25" ;       #Bank 19
+NET  "ddr2_dq[62]"                               LOC = "L25" ;       #Bank 19
+NET  "ddr2_dq[63]"                               LOC = "L24" ;       #Bank 19
+NET  "ddr2_a[12]"                                LOC = "T31" ;       #Bank 15      
+NET  "ddr2_a[11]"                                LOC = "R29" ;       #Bank 15      
+NET  "ddr2_a[10]"                                LOC = "J31" ;       #Bank 15      
+NET  "ddr2_a[9]"                                 LOC = "R28" ;       #Bank 15
+NET  "ddr2_a[8]"                                 LOC = "M31" ;       #Bank 15
+NET  "ddr2_a[7]"                                 LOC = "P30" ;       #Bank 15
+NET  "ddr2_a[6]"                                 LOC = "P31" ;       #Bank 15
+NET  "ddr2_a[5]"                                 LOC = "L31" ;       #Bank 15
+NET  "ddr2_a[4]"                                 LOC = "K31" ;       #Bank 15
+NET  "ddr2_a[3]"                                 LOC = "P29" ;       #Bank 15      
+NET  "ddr2_a[2]"                                 LOC = "N29" ;       #Bank 15      
+NET  "ddr2_a[1]"                                 LOC = "M30" ;       #Bank 15      
+NET  "ddr2_a[0]"                                 LOC = "L30" ;       #Bank 15      
+NET  "ddr2_ba[1]"                                LOC = "J30" ;       #Bank 15
+NET  "ddr2_ba[0]"                                LOC = "G31" ;       #Bank 15
+NET  "ddr2_ras_n"                                LOC = "H30" ;       #Bank 15
+NET  "ddr2_cas_n"                                LOC = "E31" ;       #Bank 15
+NET  "ddr2_we_n"                                 LOC = "K29" ;       #Bank 15
+NET  "ddr2_cs_n"                                 LOC = "L29" ;       #Bank 15
+NET  "ddr2_odt"                                  LOC = "F31" ;       #Bank 15
+NET  "ddr2_cke"                                  LOC = "T28" ;       #Bank 15
+NET  "ddr2_cke[1]"                               LOC = "U30" ;
+NET  "ddr2_dm[0]"                                LOC = "AJ31" ;              #Bank 17
+NET  "ddr2_dm[1]"                                LOC = "AE28" ;              #Bank 21
+NET  "ddr2_dm[2]"                                LOC = "Y24" ;       #Bank 21
+NET  "ddr2_dm[3]"                                LOC = "Y31" ;       #Bank 17
+NET  "ddr2_dm[4]"                                LOC = "V25" ;       #Bank 17
+NET  "ddr2_dm[5]"                                LOC = "P24" ;       #Bank 19
+NET  "ddr2_dm[6]"                                LOC = "F26" ;       #Bank 19
+NET  "ddr2_dm[7]"                                LOC = "J25" ;       #Bank 19
+NET  "sys_clk_p"                                 LOC = "H14" ;       #Bank 3
+NET  "sys_clk_n"                                 LOC = "H15" ;       #Bank 3
+NET  "clk200_p"                                  LOC = "L19" ;       #Bank 3
+NET  "clk200_n"                                  LOC = "K19" ;       #Bank 3
+NET  "sys_rst_n"                                 LOC = "E9";           #Bank 20
+#NET  "phy_init_done"                             LOC = "H18" ;              #Bank 3
+NET  "error"                                     LOC = "F6";           #Bank 12
+NET  "ddr2_dqs[0]"                               LOC = "AA29" ;              #Bank 17
+NET  "ddr2_dqs_n[0]"                             LOC = "AA30" ;              #Bank 17
+NET  "ddr2_dqs[1]"                               LOC = "AK28" ;              #Bank 21
+NET  "ddr2_dqs_n[1]"                             LOC = "AK27" ;              #Bank 21
+NET  "ddr2_dqs[2]"                               LOC = "AK26" ;              #Bank 21
+NET  "ddr2_dqs_n[2]"                             LOC = "AJ27" ;              #Bank 21
+NET  "ddr2_dqs[3]"                               LOC = "AB31" ;              #Bank 17
+NET  "ddr2_dqs_n[3]"                             LOC = "AA31" ;              #Bank 17
+NET  "ddr2_dqs[4]"                               LOC = "Y28" ;       #Bank 17
+NET  "ddr2_dqs_n[4]"                             LOC = "Y29" ;       #Bank 17
+NET  "ddr2_dqs[5]"                               LOC = "E26" ;       #Bank 19
+NET  "ddr2_dqs_n[5]"                             LOC = "E27" ;       #Bank 19
+NET  "ddr2_dqs[6]"                               LOC = "H28" ;       #Bank 19
+NET  "ddr2_dqs_n[6]"                             LOC = "G28" ;       #Bank 19
+NET  "ddr2_dqs[7]"                               LOC = "G27" ;       #Bank 19
+NET  "ddr2_dqs_n[7]"                             LOC = "H27" ;       #Bank 19
+NET  "ddr2_ck[0]"                                LOC = "AK29" ;              #Bank 21
+NET  "ddr2_ck_n[0]"                              LOC = "AJ29" ;              #Bank 21
+NET  "ddr2_ck[1]"                                LOC = "E28" ;       #Bank 19
+NET  "ddr2_ck_n[1]"                              LOC = "F28" ;       #Bank 19
+
+################################################################################
+#IDELAYCTRL Location Constraints
+################################################################################
+
+INST "*/IDELAYCTRL_INST[0].u_idelayctrl" LOC=IDELAYCTRL_X0Y1;
+INST "*/IDELAYCTRL_INST[1].u_idelayctrl" LOC=IDELAYCTRL_X0Y2;
+INST "*/IDELAYCTRL_INST[2].u_idelayctrl" LOC=IDELAYCTRL_X0Y6;
+
+###############################################################################
+# Define multicycle paths - these paths may take longer because additional
+# time allowed for logic to settle in calibration/initialization FSM
+###############################################################################
+
+# MIG 2.1: Eliminate Timegroup definitions for CLK0, and CLK90. Instead trace
+#          multicycle paths from originating flip-flop to ANY destination
+#          flip-flop (or in some cases, it can also be a BRAM)
+# MUX Select for either rising/falling CLK0 for 2nd stage read capture
+INST "*/u_phy_calib/gen_rd_data_sel*.u_ff_rd_data_sel" TNM = "TNM_RD_DATA_SEL";
+TIMESPEC "TS_MC_RD_DATA_SEL" = FROM "TNM_RD_DATA_SEL" TO FFS
+"TS_SYS_CLK" * 4;
+# MUX select for read data - optional delay on data to account for byte skews
+#INST "*/u_usr_rd/gen_rden_sel_mux*.u_ff_rden_sel_mux" TNM = "TNM_RDEN_SEL_MUX";
+#TIMESPEC "TS_MC_RDEN_SEL_MUX" = FROM "TNM_RDEN_SEL_MUX" TO FFS
+#"TS_SYS_CLK" * 4;
+# Calibration/Initialization complete status flag (for PHY logic only) - can
+# be used to drive both flip-flops and BRAMs
+INST "*/u_phy_init/u_ff_phy_init_data_sel" TNM = "TNM_PHY_INIT_DATA_SEL";
+TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_0" = FROM "TNM_PHY_INIT_DATA_SEL" TO FFS
+"TS_SYS_CLK" * 4;
+TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_90" = FROM "TNM_PHY_INIT_DATA_SEL" TO RAMS
+"TS_SYS_CLK" * 4;
+# Select (address) bits for SRL32 shift registers used in stage3/stage4
+# calibration
+INST "*/u_phy_calib/gen_gate_dly*.u_ff_gate_dly" TNM = "TNM_GATE_DLY";
+TIMESPEC "TS_MC_GATE_DLY" = FROM "TNM_GATE_DLY" TO FFS "TS_SYS_CLK" * 4;
+#INST "*/u_phy_calib/gen_rden_dly*.u_ff_rden_dly" TNM = "TNM_RDEN_DLY";
+#TIMESPEC "TS_MC_RDEN_DLY" = FROM "TNM_RDEN_DLY" TO FFS "TS_SYS_CLK" * 4;
+INST "*/u_phy_calib/gen_cal_rden_dly*.u_ff_cal_rden_dly"
+  TNM = "TNM_CAL_RDEN_DLY";
+TIMESPEC "TS_MC_CAL_RDEN_DLY" = FROM "TNM_CAL_RDEN_DLY" TO FFS
+  "TS_SYS_CLK" * 4;
+
+###############################################################################
+# DQS Read Post amble Glitch Squelch circuit related constraints
+###############################################################################
+
+###############################################################################
+# LOC placement of DQS-squelch related IDDR and IDELAY elements
+# Each circuit can be located at any of the following locations:
+#  1. Unused "N"-side of DQS differential pair I/O
+#  2. DM data mask (output only, input side is free for use)
+#  3. Any output-only site
+###############################################################################
+
+INST "*/gen_dqs[0].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y96";
+INST "*/gen_dqs[0].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y96";
+INST "*/gen_dqs[1].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y58";
+INST "*/gen_dqs[1].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y58";
+INST "*/gen_dqs[2].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y62";
+INST "*/gen_dqs[2].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y62";
+INST "*/gen_dqs[3].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y100";
+INST "*/gen_dqs[3].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y100";
+INST "*/gen_dqs[4].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y102";
+INST "*/gen_dqs[4].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y102";
+INST "*/gen_dqs[5].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y256";
+INST "*/gen_dqs[5].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y256";
+INST "*/gen_dqs[6].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y260";
+INST "*/gen_dqs[6].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y260";
+INST "*/gen_dqs[7].u_iob_dqs/u_iddr_dq_ce"  LOC = "ILOGIC_X0Y262";
+INST "*/gen_dqs[7].u_iob_dqs/u_iodelay_dq_ce"  LOC = "IODELAY_X0Y262";
+
+###############################################################################
+# LOC and timing constraints for flop driving DQS CE enable signal
+# from fabric logic. Even though the absolute delay on this path is
+# calibrated out (when synchronizing this output to DQS), the delay
+# should still be kept as low as possible to reduce post-calibration
+# voltage/temp variations - these are roughly proportional to the
+# absolute delay of the path
+###############################################################################
+
+INST "*/u_phy_calib/gen_gate[0].u_en_dqs_ff"  LOC = SLICE_X0Y48;
+INST "*/u_phy_calib/gen_gate[1].u_en_dqs_ff"  LOC = SLICE_X0Y29;
+INST "*/u_phy_calib/gen_gate[2].u_en_dqs_ff"  LOC = SLICE_X0Y31;
+INST "*/u_phy_calib/gen_gate[3].u_en_dqs_ff"  LOC = SLICE_X0Y50;
+INST "*/u_phy_calib/gen_gate[4].u_en_dqs_ff"  LOC = SLICE_X0Y51;
+INST "*/u_phy_calib/gen_gate[5].u_en_dqs_ff"  LOC = SLICE_X0Y128;
+INST "*/u_phy_calib/gen_gate[6].u_en_dqs_ff"  LOC = SLICE_X0Y130;
+INST "*/u_phy_calib/gen_gate[7].u_en_dqs_ff"  LOC = SLICE_X0Y131;
+
+# Control for DQS gate - from fabric flop. Prevent "runaway" delay -
+# two parts to this path: (1) from fabric flop to IDELAY, (2) from
+# IDELAY to asynchronous reset of IDDR that drives the DQ CE's
+# This can be relaxed by the user for lower frequencies:
+# 300MHz = 850ps, 267MHz = 900ps. At 200MHz = 950ps.
+# In general PAR should be able to route this
+# within 900ps over all speed grades.
+NET "*/u_phy_io/en_dqs*" MAXDELAY = 600 ps;
+NET "*/u_phy_io/gen_dqs*.u_iob_dqs/en_dqs_sync" MAXDELAY = 850 ps;
+
+###############################################################################
+# "Half-cycle" path constraint from IDDR to CE pin for all DQ IDDR's
+# for DQS Read Post amble Glitch Squelch circuit
+###############################################################################
+
+# Max delay from output of IDDR to CE input of DQ IDDRs = tRPST + some slack
+#  where slack account for rise-time of DQS on board. For now assume slack = 
+#  0.400ns (based on initial SPICE simulations, assumes use of ODT), so 
+#  time = 0.4*Tcyc + 0.40ns = 1.6ns @333MHz
+INST "*/gen_dqs[*].u_iob_dqs/u_iddr_dq_ce" TNM = "TNM_DQ_CE_IDDR";
+INST "*/gen_dq[*].u_iob_dq/gen_stg2_*.u_iddr_dq" TNM = "TNM_DQS_FLOPS";
+TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 1.9 ns;
+
+###############################################################################
+# MIG 2.2: Prevent unrelated logic from being packed into any slices used
+#          by read data capture RPM's - if unrelated logic gets packed into
+#          these slices, it could cause the DIRT strings that define the
+#          IDDR -> fabric flop routing to become unroutable during PAR stage
+#          (unrelated logic may require routing resources required by the
+#          DIRT strings - MAP does not currently take into account DIRT
+#          strings when placing logic
+###############################################################################
+
+AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
+
+###############################################################################
+# Location constraints for DQ read-data capture flops in fabric (for 2nd
+# stage capture)
+###############################################################################
+
+INST "*/gen_dq[0].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y42;            #  AF30      X0Y22    *
+INST "*/gen_dq[1].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y43;            #  AK31      X0Y23    
+INST "*/gen_dq[2].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y45;            #  AF31      X0Y25    
+INST "*/gen_dq[3].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y46;            #  AD30      X0Y26    
+INST "*/gen_dq[4].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y41;            #  AJ30      X0Y21    
+INST "*/gen_dq[5].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y42;            #  AF29      X0Y22    ***
+INST "*/gen_dq[6].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y44;            #  AD29      X0Y24    
+INST "*/gen_dq[7].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y44;            #  AE29      X0Y24    
+INST "*/gen_dq[8].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y28;            #  AH27      X0Y8     ***
+INST "*/gen_dq[9].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y32;            #  AF28      X0Y12    
+INST "*/gen_dq[10].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y33;           #  AH28      X0Y13    
+INST "*/gen_dq[11].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y34;           #  AA28      X0Y14    
+INST "*/gen_dq[12].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y26;           #  AG25      X0Y6     
+INST "*/gen_dq[13].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y28;           #  AJ26      X0Y8     *
+INST "*/gen_dq[14].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y33;           #  AG28      X0Y13    
+INST "*/gen_dq[15].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y34;           #  AB28      X0Y14    
+INST "*/gen_dq[16].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y35;           #  AC28      X0Y15    
+INST "*/gen_dq[17].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y36;           #  AB25      X0Y16    ***
+INST "*/gen_dq[18].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y38;           #  AC27      X0Y18    
+INST "*/gen_dq[19].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y39;           #  AA26      X0Y19    
+INST "*/gen_dq[20].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y36;           #  AB26      X0Y16    *
+INST "*/gen_dq[21].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y37;           #  AA24      X0Y17    
+INST "*/gen_dq[22].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y38;           #  AB27      X0Y18    
+INST "*/gen_dq[23].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y39;           #  AA25      X0Y19    
+INST "*/gen_dq[24].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y46;           #  AC29      X0Y26    
+INST "*/gen_dq[25].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y49;           #  AB30      X0Y29    ***
+INST "*/gen_dq[26].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y53;           #  W31       X0Y33    
+INST "*/gen_dq[27].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y55;           #  V30       X0Y35    
+INST "*/gen_dq[28].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y49;           #  AC30      X0Y29    *
+INST "*/gen_dq[29].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y52;           #  W29       X0Y32    
+INST "*/gen_dq[30].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y54;           #  V27       X0Y34    ***
+INST "*/gen_dq[31].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y56;           #  W27       X0Y36    
+INST "*/gen_dq[32].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y52;           #  V29       X0Y32    
+INST "*/gen_dq[33].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y56;           #  Y27       X0Y36    
+INST "*/gen_dq[34].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y58;           #  Y26       X0Y38    
+INST "*/gen_dq[35].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y59;           #  W24       X0Y39    
+INST "*/gen_dq[36].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y54;           #  V28       X0Y34   * 
+INST "*/gen_dq[37].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y57;           #  W25       X0Y37    
+INST "*/gen_dq[38].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y58;           #  W26       X0Y38    
+INST "*/gen_dq[39].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y59;           #  V24       X0Y39    
+INST "*/gen_dq[40].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y120;          #  R24       X0Y100   
+INST "*/gen_dq[41].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y121;          #  P25       X0Y101   
+INST "*/gen_dq[42].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y122;          #  N24       X0Y102   
+INST "*/gen_dq[43].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y123;          #  P26       X0Y103   
+INST "*/gen_dq[44].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y120;          #  T24       X0Y100   
+INST "*/gen_dq[45].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y121;          #  N25       X0Y101   
+INST "*/gen_dq[46].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y123;          #  P27       X0Y103   
+INST "*/gen_dq[47].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y124;          #  N28       X0Y104   
+INST "*/gen_dq[48].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y124;          #  M28       X0Y104   
+INST "*/gen_dq[49].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y126;          #  L28       X0Y106   
+INST "*/gen_dq[50].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y132;          #  F25       X0Y112   
+INST "*/gen_dq[51].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y133;          #  H25       X0Y113   
+INST "*/gen_dq[52].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y125;          #  K27       X0Y105   
+INST "*/gen_dq[53].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y126;          #  K28       X0Y106   
+INST "*/gen_dq[54].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y133;          #  H24       X0Y113   
+INST "*/gen_dq[55].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y134;          #  G26       X0Y114   
+INST "*/gen_dq[56].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y134;          #  G25       X0Y114   
+INST "*/gen_dq[57].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y136;          #  M26       X0Y116   
+INST "*/gen_dq[58].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y137;          #  J24       X0Y117   
+INST "*/gen_dq[59].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y138;          #  L26       X0Y118   
+INST "*/gen_dq[60].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y135;          #  J27       X0Y115   
+INST "*/gen_dq[61].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y136;          #  M25       X0Y116   
+INST "*/gen_dq[62].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y138;          #  L25       X0Y118   
+INST "*/gen_dq[63].u_iob_dq/gen_stg2_*.u_ff_stg2a_rise"  RLOC_ORIGIN = X0Y139;          #  L24       X0Y119   
+
+
+== Test ==============================================================
+#expect 20
+#expect 16
+#expect 12
+
+#ship debug : Debug
+#ship ddr   : DDR2
+
+debug.in:
+  set ilc=*; recv, deliver;
+
+ddr.out:
+  set ilc=3; collect;
+  send token to ddr.inAddrRead;
+  set ilc=3; collect, send to debug.in;
+
+ddr.inAddrWrite:
+  set word=  0x1; deliver;
+  set word= 0x10; deliver;
+  set word=0x100; deliver;
+
+ddr.inDataWrite:
+  set word=20; deliver;
+  set word=16; deliver;
+  set word=12; deliver;
+
+ddr.inAddrRead:
+  recv token;
+  set word=  0x1; deliver;
+  set word= 0x10; deliver;
+  set word=0x100; deliver;
+
+
+== Constants ========================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/DDR2.ship- b/ships/DDR2.ship-
new file mode 100644 (file)
index 0000000..1092f73
--- /dev/null
@@ -0,0 +1,303 @@
+ship: DDR2
+
+== Ports ===========================================================
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+percolate up:    DDR2_CAS_B   1
+percolate up:    DDR2_CKE     2
+percolate up:    DDR2_RAS_B   1
+percolate up:    DDR2_WE_B    1
+percolate up:    DDR2_ODT     2
+percolate up:    DDR2_CS0_B   2
+percolate up:    DDR2_CLK_N   2
+percolate up:    DDR2_CLK_P   2
+percolate up:    DDR2_A       14
+percolate up:    DDR2_BA      3
+percolate inout: DDR2_DQ      64
+percolate up:    DDR2_DM      8
+percolate inout: DDR2_DQS_N   8
+percolate inout: DDR2_DQS_P   8
+
+percolate inout: I2C_DDR2_SCL 1
+percolate inout: I2C_DDR2_SDA 1
+
+percolate down:  CLKBUF_Q1_N  1
+percolate down:  CLKBUF_Q1_P  1
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+    public void service() { }
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+// Nearly all of this was copied from Greg Gibeling's work; copyright shown below:
+
+// Everything here was copied from
+// GateLib/Firmware/DRAM/Hardware/DDR2SDRAM/Test/FPGA_TOP_ML505_DDR2SDRAMTest.v
+
+//==============================================================================
+//      Section:        License
+//==============================================================================
+//      Copyright (c) 2005-2008, Regents of the University of California
+//      All rights reserved.
+//
+//      Redistribution and use in source and binary forms, with or without modification,
+//      are permitted provided that the following conditions are met:
+//
+//              - Redistributions of source code must retain the above copyright notice,
+//                      this list of conditions and the following disclaimer.
+//              - Redistributions in binary form must reproduce the above copyright
+//                      notice, this list of conditions and the following disclaimer
+//                      in the documentation and/or other materials provided with the
+//                      distribution.
+//              - Neither the name of the University of California, Berkeley nor the
+//                      names of its contributors may be used to endorse or promote
+//                      products derived from this software without specific prior
+//                      written permission.
+//
+//      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//      DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+//==============================================================================
+
+parameter
+    ClockFreq  = 200000000,
+    BAWidth    = 2,
+    RAWidth    = 13,
+    CAWidth    = 10,                                                     
+    DWidth     = 128,       // 128b SDR internal transfers
+    UWidth     = 8,         // This will almost ALWAYS be 8
+    BurstLen   = 2,         // 256b total burst, 2 words DWidth words at SDR, or 4 external words at DDR
+    EnableMask = 1,
+    EnableECC  = 0,
+    Board      = 0;
+
+localparam
+    UCount   =  DWidth / UWidth,
+    // 128b/8 = 16b per mask means per-byte masking
+    MWidth   =  (EnableECC || (EnableMask == 0)) ? 0 : UCount,
+    // Unused lower address bits, the -1 is to get a proper log2
+    UAWidth  =  `log2(UCount-1),
+    TAWidth  =  CAWidth + RAWidth + BAWidth,
+    // Note that the components are in order according to where in the
+    // address they appear, the -1 is to account for DDR
+    AWidth   =  TAWidth + UAWidth - 1,
+    ECheck   =  EnableECC ? 2 : 0,
+    ECorrect =  EnableECC ? 1 : 0,
+    CWidth   =  3,
+    EHWidth  =  `max(`log2(ECheck), 1),
+    ERWidth  =  `max(`log2(ECheck), 1);
+
+wire   Reset;
+assign Reset = !rst;
+
+reg     [AWidth-1:0]    CommandAddress;
+reg     [CWidth-1:0]    Command; 
+wire                    CommandReady;
+reg                     CommandValid;
+
+wire    [DWidth-1:0]    DataIn;
+wire    [MWidth-1:0]    DataInMask;
+reg                     DataInValid;
+wire                    DataInReady;
+        
+wire    [DWidth-1:0]    DataOut;
+wire    [EHWidth-1:0]   DataOutErrorChecked;
+wire    [ERWidth-1:0]   DataOutErrorCorrected;
+wire                    DataOutValid;
+reg                     DataOutReady;
+
+wire                    Clock_IBUFG;
+wire                    Clock, ClockD2, ClockP90;
+wire                    Clock_DCM, ClockD2_DCM, ClockP90_DCM;
+wire                    Locked;
+
+reg  [`WORDWIDTH:0] out_d;
+assign out_d_ = out_d;
+
+assign  DDR2_BA[2]    = 1'b0;
+assign  DDR2_CS0_B[1] = 1'b1;
+assign  DDR2_ODT[1]   = 1'b0;
+assign  DDR2_CKE[1]   = 1'b0;
+
+IBUFGDS ClockIBufG(.I(CLKBUF_Q1_P), .IB(CLKBUF_Q1_N), .O(Clock_IBUFG));
+DCM_BASE
+  #( 
+     .CLKIN_PERIOD(5.0),
+     .CLKDV_DIVIDE(2.0),
+     .DLL_FREQUENCY_MODE("HIGH"),
+     .DUTY_CYCLE_CORRECTION("TRUE"),
+     .FACTORY_JF(16'hF0F0)
+   )
+  DCMBase(
+     .CLK0(Clock_DCM),
+     .CLK180( ),
+     .CLK270( ),
+     .CLK2X( ),
+     .CLK2X180( ),
+     .CLK90(ClockP90_DCM),
+     .CLKDV(ClockD2_DCM),
+     .CLKFX( ),
+     .CLKFX180( ),
+     .LOCKED(Locked),
+     .CLKFB(Clock),
+     .CLKIN(Clock_IBUFG),
+     .RST(Reset));
+  // synthesis attribute CLKIN_PERIOD          of DCMBase is "5.0"
+  // synthesis attribute CLKDV_DIVIDE          of DCMBase is "2.0"
+  // synthesis attribute DLL_FREQUENCY_MODE    of DCMBase is "HIGH"
+  // synthesis attribute DUTY_CYCLE_CORRECTION of DCMBase is "TRUE"
+  // synthesis attribute FACTORY_JF            of DCMBase is "16'hF0F0"
+  BUFG    ClockBufG(.I(Clock_DCM), .O(Clock));
+  BUFG    ClockP90BufG(.I(ClockP90_DCM), .O(ClockP90));
+  BUFG    ClockD2BufG(.I(ClockD2_DCM), .O(ClockD2));
+
+DDR2SDRAM DDR2SDRAM(
+      .Clock(Clock),
+      .ClockD2(ClockD2),
+      .ClockP90(ClockP90),
+      .Reset(Reset),
+      .Locked(Locked),
+      .ClockF200(Clock),
+      .Initialized( ),
+      .PoweredUp( ),
+
+      .CommandClock(clk),
+      .DataInClock(clk),
+      .DataOutClock(clk),
+      .CommandReset(Reset),
+      .DataInReset(Reset),
+      .DataOutReset(Reset),
+
+      .CommandAddress(CommandAddress),
+      .Command(Command),
+      .CommandValid(CommandValid),
+      .CommandReady(CommandReady),
+      .DataIn(DataIn),
+      .DataInMask(DataInMask),
+      .DataInValid(DataInValid),
+      .DataInReady(DataInReady),
+      .DataOut(DataOut),
+      .DataOutErrorChecked(DataOutErrorChecked),
+      .DataOutErrorCorrected(DataOutErrorCorrected),
+      .DataOutValid(DataOutValid),
+      .DataOutReady(DataOutReady),
+      .DDR2_DQ(DDR2_DQ),
+      .DDR2_A(DDR2_A),
+      .DDR2_BA(DDR2_BA[1:0]),
+      .DDR2_RAS_B(DDR2_RAS_B),
+      .DDR2_CAS_B(DDR2_CAS_B),
+      .DDR2_WE_B(DDR2_WE_B),
+      .DDR2_CS0_B(DDR2_CS0_B[0]),
+      .DDR2_ODT(DDR2_ODT[0]),
+      .DDR2_CKE(DDR2_CKE[0]),
+      .DDR2_DM(DDR2_DM),
+      .DDR2_DQS_P(DDR2_DQS_P),
+      .DDR2_DQS_N(DDR2_DQS_N),
+      .DDR2_CLK_P(DDR2_CLK_P),
+      .DDR2_CLK_N(DDR2_CLK_N));
+      defparam DDR2SDRAM.UWidth     = UWidth;
+      defparam DDR2SDRAM.BAWidth    = BAWidth;
+      defparam DDR2SDRAM.RAWidth    = RAWidth;
+      defparam DDR2SDRAM.CAWidth    = CAWidth;
+      defparam DDR2SDRAM.DWidth     = DWidth;
+      defparam DDR2SDRAM.BurstLen   = BurstLen;
+      defparam DDR2SDRAM.EnableMask = EnableMask;
+      defparam DDR2SDRAM.EnableECC  = EnableECC;
+      defparam DDR2SDRAM.Board      = Board;
+      defparam DDR2SDRAM.MultiClock = 1;
+
+  assign DataIn     = inDataWrite_d;
+  assign DataInMask = 16'b1111111111111111;
+
+  always @(posedge clk) begin
+
+    if (rst) begin
+      `reset
+      CommandValid <= 0;
+      DataOutReady <= 0;
+    end else begin
+      `cleanup
+
+      CommandValid <= 0;
+      DataInValid  <= 0;
+
+      if (`out_empty) begin
+          DataOutReady <= 1;      
+      end
+
+      if (DataOutReady && DataOutValid && `out_empty) begin
+          out_d <= { 1'b0, DataOut[`WORDWIDTH-1:0] };
+          `fill_out
+          DataOutReady <= 0;
+
+      end else if (DataOutReady && CommandReady && DataInReady && `out_empty) begin
+          if (`inAddrWrite_full && `inDataWrite_full) begin
+            `drain_inDataWrite
+            `drain_inAddrWrite
+            CommandAddress <= inAddrWrite_d;
+            Command        <= 3'b000;
+            CommandValid   <= 1;
+            DataInValid    <= 1;
+            out_d <= { 1'b1, 37'b0 };
+            `fill_out
+            DataOutReady <= 0;
+          end else if (`inAddrRead_full) begin
+            `drain_inAddrRead
+            CommandAddress <= inAddrRead_d;
+            CommandValid   <= 1;
+            Command        <= 3'b001;
+            DataInValid    <= 0;
+            DataOutReady   <= 1;
+          end
+      end
+    end
+  end
+
+== Test ==============================================================
+
+#skip
+#expect 0
+
+#ship debug : Debug
+#ship ddr   : DDR2
+
+debug.in:
+  recv, deliver;
+
+ddr.out:
+  collect;
+  set flags a=!c,b=b;
+  send to debug.in;
+  collect;
+  set flags a=!c,b=b;
+  send to debug.in;
+ddr.inAddrWrite:
+  set word=0;
+  deliver;
+  deliver;
+ddr.inDataWrite:
+  set word=1;
+  deliver;
+  deliver;
+
+
+
+
+== Constants ========================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/DRAM.ship b/ships/DRAM.ship
new file mode 100644 (file)
index 0000000..161928e
--- /dev/null
@@ -0,0 +1,155 @@
+ship: DRAM
+
+== Ports ===========================================================
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+percolate up:            ddr1_Clk_pin       1
+percolate up:            ddr1_Clk_n_pin     1
+percolate up:            ddr1_Addr_pin      13
+percolate up:            ddr1_BankAddr_pin  2
+percolate up:            ddr1_CAS_n_pin     1
+percolate up:            ddr1_CE_pin        1
+percolate up:            ddr1_CS_n_pin      1
+percolate up:            ddr1_RAS_n_pin     1
+percolate up:            ddr1_WE_n_pin      1
+percolate up:            ddr1_DM_pin        4
+percolate inout:         ddr1_DQS           4
+percolate inout:         ddr1_DQ            32
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+    public void service() { }
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  wire  [31:0]  dram_addr;
+  wire  [31:0]  dram_addr__;
+
+  wire          dram_addr_a;
+  wire  [63:0]  dram_write_data;
+  wire  [63:0]  dram_read_data;
+
+  reg           dram_addr_r;
+  reg           dram_isread;
+
+  assign dram_addr__ = dram_isread ? inAddrRead_d[31:0] : inAddrWrite_d[31:0];
+  assign dram_addr   = { dram_addr__[30:6], 1'b0, dram_addr__[5:0] };
+
+  reg  [`WORDWIDTH:0]  out_d;
+  assign out_d_ = out_d;
+
+   ddr_ctrl 
+   #(
+       .clk_freq( 50000000 ),
+       .clk_multiply( 12 ),
+       .clk_divide( 5 ),
+       .phase_shift( 0 ),
+       .wait200_init( 26 )
+   ) ddr_ctrl (
+          .ddr_a( ddr1_Addr_pin ),
+          .ddr_clk( ddr1_Clk_pin ),
+          .ddr_clk_n( ddr1_Clk_n_pin ),
+          .ddr_ba( ddr1_BankAddr_pin ),
+          .ddr_dq( ddr1_DQ ),
+          .ddr_dm( ddr1_DM_pin ),
+          .ddr_dqs( ddr1_DQS ),
+          .ddr_cs_n( ddr1_CS_n_pin ),
+          .ddr_ras_n( ddr1_RAS_n_pin ),
+          .ddr_cas_n( ddr1_CAS_n_pin ),
+          .ddr_we_n( ddr1_WE_n_pin ),
+          .ddr_cke( ddr1_CE_pin ),
+   
+          .clk(clk),
+          .reset(rst),
+          .rot(3'b100),
+   
+          .fml_wr(!dram_isread && dram_addr_r),
+          .fml_done(dram_addr_a),
+          .fml_rd( dram_isread && dram_addr_r),
+          .fml_adr(dram_addr),
+          .fml_din(dram_write_data),
+          .fml_dout(dram_read_data),
+          .fml_msk(16'h0)
+   );
+
+  always @(posedge clk) begin
+
+    if (rst) begin
+      `reset
+      dram_isread <= 0;
+      dram_addr_r <= 0;
+
+    end else begin
+      `cleanup
+
+      if (dram_addr_r && !dram_addr_a) begin
+         // busy
+      end else if (dram_addr_r &&  dram_addr_a && !dram_isread) begin
+          dram_addr_r <= 0;
+          `drain_inDataWrite
+          `drain_inAddrWrite
+          `fill_out
+          out_d <= { 1'b1, 37'b0 };
+      end else if (dram_addr_r &&  dram_addr_a && dram_isread) begin
+          dram_addr_r <= 0;
+          `drain_inAddrRead
+          `fill_out
+          out_d <= { 1'b0, dram_read_data[36:0] };
+      end else if (`out_empty && `inAddrWrite_full && `inDataWrite_full && !dram_addr_r && !dram_addr_a) begin
+          dram_addr_r <= 1;
+          dram_isread <= 0;
+      end else if (`out_empty && `inAddrRead_full && !dram_addr_r && !dram_addr_a) begin
+          dram_addr_r <= 1;
+          dram_isread <= 1;
+      end
+    end
+  end
+
+
+== Test ========================================================
+#skip
+// expected output
+#expect 10
+
+// ships required in order to run this code
+#ship debug          : Debug
+#ship memory         : DRAM
+
+memory.inAddrWrite:
+  set word=0;
+  deliver;
+  deliver;
+
+memory.inDataWrite:
+  set word=-1;
+  deliver;
+  set word=-1;
+  deliver;
+
+memory.inAddrRead:
+  recv token;
+  set word=0;
+  deliver;
+
+memory.out:
+  collect;
+  collect;
+  send token to memory.inAddrRead;
+  collect;
+  send to debug.in;
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+
+== Constants ========================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Debug.ship b/ships/Debug.ship
new file mode 100644 (file)
index 0000000..e912f92
--- /dev/null
@@ -0,0 +1,225 @@
+ship: Debug
+
+== Ports ===========================================================
+data  in:     in
+dockless out: out
+
+percolate down: uart_in     1
+percolate up:   uart_out    1
+percolate up:   rst_out     1
+percolate down: rst_in      1
+
+== Constants ========================================================
+
+== TeX ==============================================================
+
+percolate up:   uart_rts    1
+percolate down: uart_cts    1
+
+This ship is used for debugging.  It has only one port, {\tt in}.
+Programmers should send debug report values to this port.  How such
+values are reported back to the programmer doing the debugging is left
+unspecified.
+
+\subsection*{To Do}
+
+Provide an {\tt inOp} port and use opcode ports \cite{am25} to
+effectively allow multiple independent ``debug streams''
+
+Provide a way to programmatically read back the output of the debug
+ship.
+
+== Fleeterpreter ====================================================
+public void service() {
+  if (box_in.dataReadyForShip())
+    ((Interpreter)getFleet()).debug(box_in.removeDataForShip());
+}
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  wire break_i;
+  reg send_k;
+  initial send_k = 0;
+
+  reg [`WORDWIDTH-1:0] data_to_host_full_word;
+  reg [7:0] count_in;
+  reg [7:0] count_out;
+  reg [49:0] out_d;
+  assign out_d_ = out_d;
+
+  wire       data_to_host_full;
+  reg  [7:0] data_to_host;
+  wire       data_to_fleet_empty;
+  wire [7:0] data_to_fleet;
+  reg        data_to_host_write_enable;
+  reg        data_to_fleet_read_enable;
+  reg  [7:0] force_reset;
+
+  wire sio_ce;
+  wire sio_ce_x4;
+
+  wire break;
+  wire uart_cts;
+  assign uart_cts = 0;
+  assign rst_out = rst_in || (force_reset!=0) /* || break */;
+
+  // fst=3 means clock divider is 3+2=5 for a 50Mhz clock => 10Mhz
+  // using a 33Mhz clock,
+  //   33.333Mhz / 38400hz * 4 = 217.013 => 215+2,1 => 215,1
+  // using a 100Mhz clock,
+  //   100Mhz / 38400hz * 4 = 651.039 => 215+2,3 => 215,3
+  // using a 100Mhz clock, 115200baud
+  //   100Mhz / 115200hz * 4 = 217.013 => 215+2,1 => 215,1
+//  sasc_brg sasc_brg(clk, !rst_in, 215, 3, sio_ce, sio_ce_x4);
+  sasc_brg sasc_brg(clk, !rst_in, 215, 1, sio_ce, sio_ce_x4);
+  sasc_top sasc_top(clk, !rst_in,
+                    uart_in,
+                    uart_out,
+                    uart_cts,
+                    uart_rts, 
+                    sio_ce,
+                    sio_ce_x4,
+                    data_to_host,
+                    data_to_fleet,
+                    data_to_fleet_read_enable,
+                    data_to_host_write_enable,
+                    data_to_host_full,
+                    data_to_fleet_empty,
+                    break,
+                    break_i);
+
+   reg [16:0] credits;
+
+   // fpga -> host
+   always @(posedge clk) begin
+     if (rst_in /* || break */) begin
+       count_in    <= 0;
+       count_out   <= 0;
+       force_reset <= 0;
+       credits      = 0;
+       `reset
+     end else begin
+
+       `cleanup
+
+       // fpga -> host
+       data_to_host_write_enable <= 0;
+       if (force_reset == 1) begin
+         force_reset <= 0;
+         data_to_host_write_enable <= 1;
+         credits = 0;
+         count_in  <= 0;
+         count_out <= 0;
+         `reset
+       end else if (force_reset != 0) begin
+         force_reset <= force_reset-1;
+       end else if (count_out==0 && `in_full) begin
+         `drain_in
+         data_to_host_full_word <= in_d;
+         count_out <= 8;
+       end else if (count_out!=0 && !data_to_host_full && !data_to_host_write_enable && credits!=0) begin
+         data_to_host <= { 2'b0, data_to_host_full_word[5:0] };
+         data_to_host_full_word <= (data_to_host_full_word >> 6);
+         data_to_host_write_enable <= 1;
+         count_out <= count_out-1;
+         credits = credits - 1;
+       end
+
+       // host -> fpga
+       data_to_fleet_read_enable <= 0;
+       if (!data_to_fleet_empty && !data_to_fleet_read_enable) begin
+
+         // Note: if the switch fabric refuses to accept a new item,
+         // we can get deadlocked in a state where sending a reset
+         // code (2'b11) won't have any effect.  Probably need to go
+         // back to using the break signal.
+
+           // command 0: data
+         if (data_to_fleet[7:6] == 2'b00 && `out_empty) begin
+           data_to_fleet_read_enable <= 1;
+           out_d <= { out_d[43:0], data_to_fleet[5:0] };
+           if (count_in==9) begin
+             count_in <= 0;
+             `fill_out
+           end else begin
+             count_in <= count_in+1;
+           end
+
+           // command 1: flow control credit
+         end else if (data_to_fleet[7:6] == 2'b01) begin
+           data_to_fleet_read_enable <= 1;
+           credits = credits + data_to_fleet[5:0];
+
+/*
+         // uncommenting this requires changing data_to_host_write_enable
+         // to a blocking assignment, and seems to cause data loss whenever
+         // more than four items are in flight.
+           // command 2: echo
+         end else if (data_to_fleet[7:6] == 2'b10 && !data_to_host_full && !data_to_host_write_enable) begin
+           data_to_fleet_read_enable <= 1;
+           data_to_host <= data_to_fleet;
+           data_to_host_write_enable = 1;
+*/
+
+           // command 3: reset (and echo back reset code)
+         end else if (data_to_fleet[7:6] == 2'b11) begin
+           data_to_fleet_read_enable <= 1;
+           data_to_host <= data_to_fleet;
+           force_reset <= 255;
+
+         end 
+
+       end
+
+    end
+  end
+
+== UCF =================================================================
+
+Net clk_pin LOC=AH15;
+Net clk_pin  PERIOD = 10 ns HIGH 50%;  # 100Mhz
+
+# 33mhz clock
+#Net clk_pin LOC=AH17;
+#Net clk_pin TNM_NET = clk_pin;
+#TIMESPEC TS_clk_pin = PERIOD clk_pin 30 ns HIGH 50%;  # 33Mhz
+
+Net rst_pin LOC=E9;
+Net rst_pin PULLUP;
+Net rst_pin TIG;
+
+#Net uart_cts LOC=G6;
+#Net uart_cts IOSTANDARD = LVCMOS33;
+#Net uart_cts TIG;
+
+#Net uart_rts LOC=F6;
+#Net uart_rts IOSTANDARD = LVCMOS33;
+#Net uart_rts TIG;
+
+Net uart_in LOC=AG15;
+#Net uart_in IOSTANDARD = LVCMOS33;
+Net uart_in TIG;
+Net uart_in PULLUP;
+
+Net uart_out LOC=AG20;
+#Net uart_out IOSTANDARD = LVCMOS33;
+Net uart_out TIG;
+Net uart_out PULLUP;
+
+
+
+
+
+== Test ================================================================
+#expect 25
+
+#ship debug : Debug
+
+debug.in:
+  set word= 25;
+  deliver;
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Dvi.ship b/ships/Dvi.ship
new file mode 100644 (file)
index 0000000..2c925a2
--- /dev/null
@@ -0,0 +1,590 @@
+ship: Dvi
+
+== Ports ===========================================================
+data  in:    inPixelX
+data  in:    inPixelY
+data  in:    inPixelValue
+
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+percolate up:    dvi_d0      1
+percolate up:    dvi_d1      1
+percolate up:    dvi_d2      1
+percolate up:    dvi_d3      1
+percolate up:    dvi_d4      1
+percolate up:    dvi_d5      1
+percolate up:    dvi_d6      1
+percolate up:    dvi_d7      1
+percolate up:    dvi_d8      1
+percolate up:    dvi_d9      1
+percolate up:    dvi_d10     1
+percolate up:    dvi_d11     1
+
+percolate up:    dvi_h       1
+percolate up:    dvi_v       1
+percolate up:    dvi_xclk_n  1
+percolate up:    dvi_xclk_p  1
+percolate up:    dvi_de      1
+percolate up:    dvi_reset_b 1
+
+percolate up:    gpio_led_c   1
+percolate up:    gpio_led_e   1
+percolate up:    gpio_led_n   1
+percolate up:    gpio_led_s   1
+percolate up:    gpio_led_w   1
+
+percolate up:    gpio_led_4   1
+percolate up:    gpio_led_5   1
+percolate up:    gpio_led_6   1
+percolate up:    gpio_led_7   1
+
+percolate up:    dvi_iic_scl 1
+percolate inout: dvi_iic_sda 1
+
+percolate up:    gpio_led_0   1
+percolate up:    gpio_led_1   1
+percolate up:    gpio_led_2   1
+percolate up:    gpio_led_3   1
+
+percolate up:      sram_adv_ld_b 1
+percolate up:      sram_bw0 1
+percolate up:      sram_bw1 1
+percolate up:      sram_bw2 1
+percolate up:      sram_bw3 1
+percolate up:      sram_clk 1
+percolate up:      sram_cs_b 1
+percolate up:      sram_flash_a0 1
+percolate up:      sram_flash_a1 1
+percolate up:      sram_flash_a2 1
+percolate up:      sram_flash_a3 1
+percolate up:      sram_flash_a4 1
+percolate up:      sram_flash_a5 1
+percolate up:      sram_flash_a6 1
+percolate up:      sram_flash_a7 1
+percolate up:      sram_flash_a8 1
+percolate up:      sram_flash_a9 1
+percolate up:      sram_flash_a10 1
+percolate up:      sram_flash_a11 1
+percolate up:      sram_flash_a12 1
+percolate up:      sram_flash_a13 1
+percolate up:      sram_flash_a14 1
+percolate up:      sram_flash_a15 1
+percolate up:      sram_flash_a16 1
+percolate up:      sram_flash_a17 1
+percolate up:      sram_flash_a18 1
+percolate up:      sram_flash_a19 1
+percolate up:      sram_flash_a20 1
+percolate up:      sram_flash_a21 1
+percolate up:      sram_flash_we_b 1
+percolate up:      sram_mode 1
+percolate up:      sram_oe_b 1
+
+percolate inout:    sram_dqp0 1
+percolate inout:    sram_dqp1 1
+percolate inout:    sram_dqp2 1
+percolate inout:    sram_dqp3 1
+
+percolate inout:    sram_flash_d0 1
+percolate inout:    sram_flash_d1 1
+percolate inout:    sram_flash_d2 1
+percolate inout:    sram_flash_d3 1
+percolate inout:    sram_flash_d4 1
+percolate inout:    sram_flash_d5 1
+percolate inout:    sram_flash_d6 1
+percolate inout:    sram_flash_d7 1
+percolate inout:    sram_flash_d8 1
+percolate inout:    sram_flash_d9 1
+percolate inout:    sram_flash_d10 1
+percolate inout:    sram_flash_d11 1
+percolate inout:    sram_flash_d12 1
+percolate inout:    sram_flash_d13 1
+percolate inout:    sram_flash_d14 1
+percolate inout:    sram_flash_d15 1
+percolate inout:    sram_d16 1
+percolate inout:    sram_d17 1
+percolate inout:    sram_d18 1
+percolate inout:    sram_d19 1
+percolate inout:    sram_d20 1
+percolate inout:    sram_d21 1
+percolate inout:    sram_d22 1
+percolate inout:    sram_d23 1
+percolate inout:    sram_d24 1
+percolate inout:    sram_d25 1
+percolate inout:    sram_d26 1
+percolate inout:    sram_d27 1
+percolate inout:    sram_d28 1
+percolate inout:    sram_d29 1
+percolate inout:    sram_d30 1
+percolate inout:    sram_d31 1
+
+== FPGA ==============================================================
+
+wire [9:0] x_coord;
+wire [9:0] y_coord;
+wire data_valid_ext;
+wire clk_fb;
+wire pix_clk;
+wire[7:0] dvi_green;
+wire[7:0] dvi_red;
+wire[7:0] dvi_blue;
+
+assign dvi_reset_b = 1;
+assign dvi_de = data_valid_ext;
+
+vga_timing_generator 
+ #(
+     .WIDTH(640),
+     .H_FP(16),
+     .H_SYNC(96),
+     .H_BP(48),
+     .HEIGHT(480),
+     .V_FP(12),
+     .V_SYNC(2),
+     .V_BP(31),
+     .HEIGHT_BITS(10),
+     .WIDTH_BITS(10),
+     .DATA_DELAY(0)
+  ) my_vga_timing_generator (
+     .rst(rst),
+     .clk(pix_clk),
+     .hsync(dvi_h),
+     .vsync(dvi_v),
+     .X_COORD(x_coord),
+     .Y_COORD(y_coord),
+     .DATA_VALID(),
+     .DATA_VALID_EXT(data_valid_ext),
+     .PIXEL_COUNT()
+  );
+
+  ODDR #(
+      .DDR_CLK_EDGE("OPPOSITE_EDGE"),    // "OPPOSITE_EDGE" or "SAME_EDGE" 
+      .INIT(1'b0),                          // Initial value for Q port ('1' or '0')
+      .SRTYPE("SYNC")                    // Reset Type ("ASYNC" or "SYNC")
+  ) ODDR_xclk_p (
+      .Q(dvi_xclk_p),       // 1-bit DDR output
+      .C(pix_clk),          // 1-bit clock input
+      .CE(1),              // 1-bit clock enable input
+      .D1(1),              // 1-bit data input (positive edge)
+      .D2(0),              // 1-bit data input (negative edge)
+      .R(0),              // 1-bit reset input
+      .S(0)               // 1-bit set input
+      );
+  ODDR #(
+      .DDR_CLK_EDGE("OPPOSITE_EDGE"),    // "OPPOSITE_EDGE" or "SAME_EDGE" 
+      .INIT(1'b0),                          // Initial value for Q port ('1' or '0')
+      .SRTYPE("SYNC")                    // Reset Type ("ASYNC" or "SYNC")
+  ) ODDR_xclk_n (
+      .Q(dvi_xclk_n),       // 1-bit DDR output
+      .C(pix_clk),          // 1-bit clock input
+      .CE(1),              // 1-bit clock enable input
+      .D1(0),              // 1-bit data input (positive edge)
+      .D2(1),              // 1-bit data input (negative edge)
+      .R(0),              // 1-bit reset input
+      .S(0)               // 1-bit set input
+      );
+
+  i2c_video_programmer my_i2c_video_programmer_i (
+      .CLK200Mhz(clk),
+      .RST(rst),
+      .I2C_SDA(dvi_iic_sda),
+      .I2C_SCL(dvi_iic_scl));
+
+  DCM_BASE #(
+      .CLKDV_DIVIDE(4.0),     // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
+      .CLKFX_DIVIDE(16),      // Can be any interger from 1 to 32
+      .CLKFX_MULTIPLY(2),       // Can be any integer from 2 to 32
+      .CLKIN_DIVIDE_BY_2("FALSE"),   // TRUE/FALSE to enable CLKIN divide by two feature
+      .CLKIN_PERIOD(10.0),     // Specify period of input clock in ns from 1.25 to 1000.00
+      .CLKOUT_PHASE_SHIFT("NONE"),  // Specify phase shift mode of NONE or FIXED
+      .CLK_FEEDBACK("1X"),    // Specify clock feedback of NONE or 1X
+      .DCM_AUTOCALIBRATION("TRUE"),    // DCM calibrartion circuitry TRUE/FALSE
+      .DCM_PERFORMANCE_MODE("MAX_SPEED"),  // Can be MAX_SPEED or MAX_RANGE
+      .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"),  // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+      .DFS_FREQUENCY_MODE("HIGH"),  // LOW or HIGH frequency mode for frequency synthesis
+      .DLL_FREQUENCY_MODE("LOW"),  // LOW, HIGH, or HIGH_SER frequency mode for DLL
+      .DUTY_CYCLE_CORRECTION("TRUE"),    // Duty cycle correction, TRUE or FALSE
+      .FACTORY_JF(16'hF0F0),  // FACTORY JF Values Suggested to be set to X"F0F0" 
+      .PHASE_SHIFT(0),       // Amount of fixed phase shift from -255 to 1023
+      .STARTUP_WAIT("FALSE")   // Delay configuration DONE until DCM LOCK, TRUE/FALSE
+  ) DCM_BASE_dvi (
+      .CLK0(clk_fb),
+      .CLKDV(pix_clk),
+      .CLKFB(clk_fb),
+      .CLKIN(clk),
+      .RST(rst)
+      );
+
+  ODDR ODDR_dvi_d0  (dvi_d0,  pix_clk, 1, dvi_green[4], dvi_blue[0],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d1  (dvi_d1,  pix_clk, 1, dvi_green[5], dvi_blue[1],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d2  (dvi_d2,  pix_clk, 1, dvi_green[6], dvi_blue[2],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d3  (dvi_d3,  pix_clk, 1, dvi_green[7], dvi_blue[3],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d4  (dvi_d4,  pix_clk, 1, dvi_red[0],   dvi_blue[4],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d5  (dvi_d5,  pix_clk, 1, dvi_red[1],   dvi_blue[5],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d6  (dvi_d6,  pix_clk, 1, dvi_red[2],   dvi_blue[6],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d7  (dvi_d7,  pix_clk, 1, dvi_red[3],   dvi_blue[7],  ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d8  (dvi_d8,  pix_clk, 1, dvi_red[4],   dvi_green[0], ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d9  (dvi_d9,  pix_clk, 1, dvi_red[5],   dvi_green[1], ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d10 (dvi_d10, pix_clk, 1, dvi_red[6],   dvi_green[2], ~data_valid_ext, 0);
+  ODDR ODDR_dvi_d11 (dvi_d11, pix_clk, 1, dvi_red[7],   dvi_green[3], ~data_valid_ext, 0);
+
+  reg we;
+  reg  [31:0] mem_out;
+  wire [20:0] inAddr;
+  wire [20:0] vga_pixel_addr_;
+  reg  [20:0] vga_pixel_addr;
+  reg  [20:0] last_vga_pixel_addr;
+
+  reg write_enable;
+  reg oe;
+  reg [3:0] wait_until_read;
+  reg [3:0] wait_until_write;
+  reg [3:0] wait_until_video;
+  reg [37:0] addr;
+  wire [35:0] data_out;
+  reg [37:0] out_d;
+  reg [37:0] writeData;
+  
+  reg use_addr;
+
+  assign out_d_ = out_d;
+  
+  assign sram_flash_a0 = use_addr ? addr[0] : 0;
+  assign sram_flash_a1 = use_addr ? addr[1] : vga_pixel_addr[0];
+  assign sram_flash_a2 = use_addr ? addr[2] : vga_pixel_addr[1];
+  assign sram_flash_a3 = use_addr ? addr[3] : vga_pixel_addr[2];
+  assign sram_flash_a4 = use_addr ? addr[4] : vga_pixel_addr[3];
+  assign sram_flash_a5 = use_addr ? addr[5] : vga_pixel_addr[4];
+  assign sram_flash_a6 = use_addr ? addr[6] : vga_pixel_addr[5];
+  assign sram_flash_a7 = use_addr ? addr[7] : vga_pixel_addr[6];
+  assign sram_flash_a8 = use_addr ? addr[8] : vga_pixel_addr[7];
+  assign sram_flash_a9 = use_addr ? addr[9] : vga_pixel_addr[8];
+  assign sram_flash_a10 = use_addr ? addr[10] : vga_pixel_addr[9];
+  assign sram_flash_a11 = use_addr ? addr[11] : vga_pixel_addr[10];
+  assign sram_flash_a12 = use_addr ? addr[12] : vga_pixel_addr[11];
+  assign sram_flash_a13 = use_addr ? addr[13] : vga_pixel_addr[12];
+  assign sram_flash_a14 = use_addr ? addr[14] : vga_pixel_addr[13];
+  assign sram_flash_a15 = use_addr ? addr[15] : vga_pixel_addr[14];
+  assign sram_flash_a16 = use_addr ? addr[16] : vga_pixel_addr[15];
+  assign sram_flash_a17 = use_addr ? addr[17] : vga_pixel_addr[16];
+  assign sram_flash_a18 = use_addr ? addr[18] : vga_pixel_addr[17];
+  assign sram_flash_a19 = use_addr ? addr[19] : vga_pixel_addr[18];
+  assign sram_flash_a20 = use_addr ? addr[20] : vga_pixel_addr[19];
+  assign sram_flash_a21 = use_addr ? addr[21] : vga_pixel_addr[20];
+  
+  assign data_out[0]  = sram_flash_d0;   assign sram_flash_d0  = oe ? 1'bz : writeData[0];
+  assign data_out[1]  = sram_flash_d1;   assign sram_flash_d1  = oe ? 1'bz : writeData[1];
+  assign data_out[2]  = sram_flash_d2;   assign sram_flash_d2  = oe ? 1'bz : writeData[2];
+  assign data_out[3]  = sram_flash_d3;   assign sram_flash_d3  = oe ? 1'bz : writeData[3];
+  assign data_out[4]  = sram_flash_d4;   assign sram_flash_d4  = oe ? 1'bz : writeData[4];
+  assign data_out[5]  = sram_flash_d5;   assign sram_flash_d5  = oe ? 1'bz : writeData[5];
+  assign data_out[6]  = sram_flash_d6;   assign sram_flash_d6  = oe ? 1'bz : writeData[6];
+  assign data_out[7]  = sram_flash_d7;   assign sram_flash_d7  = oe ? 1'bz : writeData[7];
+  assign data_out[8]  = sram_flash_d8;   assign sram_flash_d8  = oe ? 1'bz : writeData[8];
+  assign data_out[9]  = sram_flash_d9;   assign sram_flash_d9  = oe ? 1'bz : writeData[9];
+  assign data_out[10] = sram_flash_d10;  assign sram_flash_d10 = oe ? 1'bz : writeData[10];
+  assign data_out[11] = sram_flash_d11;  assign sram_flash_d11 = oe ? 1'bz : writeData[11];
+  assign data_out[12] = sram_flash_d12;  assign sram_flash_d12 = oe ? 1'bz : writeData[12];
+  assign data_out[13] = sram_flash_d13;  assign sram_flash_d13 = oe ? 1'bz : writeData[13];
+  assign data_out[14] = sram_flash_d14;  assign sram_flash_d14 = oe ? 1'bz : writeData[14];
+  assign data_out[15] = sram_flash_d15;  assign sram_flash_d15 = oe ? 1'bz : writeData[15];
+  assign data_out[16] = sram_d16;        assign sram_d16       = oe ? 1'bz : writeData[16];
+  assign data_out[17] = sram_d17;        assign sram_d17       = oe ? 1'bz : writeData[17];
+  assign data_out[18] = sram_d18;        assign sram_d18       = oe ? 1'bz : writeData[18];
+  assign data_out[19] = sram_d19;        assign sram_d19       = oe ? 1'bz : writeData[19];
+  assign data_out[20] = sram_d20;        assign sram_d20       = oe ? 1'bz : writeData[20];
+  assign data_out[21] = sram_d21;        assign sram_d21       = oe ? 1'bz : writeData[21];
+  assign data_out[22] = sram_d22;        assign sram_d22       = oe ? 1'bz : writeData[22];
+  assign data_out[23] = sram_d23;        assign sram_d23       = oe ? 1'bz : writeData[23];
+  assign data_out[24] = sram_d24;        assign sram_d24       = oe ? 1'bz : writeData[24];
+  assign data_out[25] = sram_d25;        assign sram_d25       = oe ? 1'bz : writeData[25];
+  assign data_out[26] = sram_d26;        assign sram_d26       = oe ? 1'bz : writeData[26];
+  assign data_out[27] = sram_d27;        assign sram_d27       = oe ? 1'bz : writeData[27];
+  assign data_out[28] = sram_d28;        assign sram_d28       = oe ? 1'bz : writeData[28];
+  assign data_out[29] = sram_d29;        assign sram_d29       = oe ? 1'bz : writeData[29];
+  assign data_out[30] = sram_d30;        assign sram_d30       = oe ? 1'bz : writeData[30];
+  assign data_out[31] = sram_d31;        assign sram_d31       = oe ? 1'bz : writeData[31];
+  assign data_out[32] = sram_dqp0;       assign sram_dqp0      = oe ? 1'bz : writeData[32];
+  assign data_out[33] = sram_dqp1;       assign sram_dqp1      = oe ? 1'bz : writeData[33];
+  assign data_out[34] = sram_dqp2;       assign sram_dqp2      = oe ? 1'bz : writeData[34];
+  assign data_out[35] = sram_dqp3;       assign sram_dqp3      = oe ? 1'bz : writeData[35];
+  
+  assign sram_mode       = 0;
+  assign sram_clk        = clk;
+  assign sram_bw0        = ~write_enable;
+  assign sram_bw1        = ~write_enable;
+  assign sram_bw2        = ~write_enable;
+  assign sram_bw3        = ~write_enable;
+  assign sram_flash_we_b = ~write_enable;
+  assign sram_adv_ld_b   = 0;
+  assign sram_cs_b       = 0;
+  assign sram_oe_b       = ~oe;
+
+  // Framebuffer is 544x478 -- yeah, I know that's completely weird.
+
+  wire on_screen_;
+  reg on_screen;
+  assign on_screen_ = (x_coord >= 48) && (x_coord < 592);
+  wire [9:0] adjusted_x_coord;
+  assign adjusted_x_coord = x_coord - 48;
+
+  assign inAddr          = inPixelX_d[20:0]
+                         + { 7'b0000000, inPixelY_d[8:0], 5'b00000    }
+                         + {     3'b000, inPixelY_d[8:0], 9'b0000000000 };
+  assign vga_pixel_addr_ = { 11'b00000000000, adjusted_x_coord }
+                         + { 7'b0000000, y_coord[8:0], 5'b00000 }
+                         + {     3'b000, y_coord[8:0], 9'b0000000000 };
+
+  assign dvi_red         = on_screen ? { mem_out[17:12], 2'b0 } : 0;
+  assign dvi_green       = on_screen ? { mem_out[11:6],  2'b0 } : 0;
+  assign dvi_blue        = on_screen ? { mem_out[5:0],   2'b0 } : 0;
+
+  always @(posedge pix_clk) begin
+      vga_pixel_addr <= vga_pixel_addr_;
+      on_screen      <= on_screen_;
+  end
+
+  wire idle;
+  assign idle = (wait_until_write==0 && wait_until_read==0 && wait_until_video==0);
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      wait_until_read <= 0;
+      wait_until_video <= 0;
+      wait_until_write <= 0;
+      use_addr <= 0;
+  
+    end else begin
+      `cleanup
+  
+      write_enable <= 0;
+      oe <= 1;
+
+      if (wait_until_write == 1) begin
+        wait_until_write <= 0;
+        oe <= 0;
+        use_addr <= 0;
+      end else if (wait_until_write != 0) begin
+        wait_until_write <= wait_until_write-1;
+      end
+
+      if (wait_until_read == 1) begin
+        wait_until_read <= 0;
+        out_d <= { 1'b0, data_out };
+        `fill_out
+        `drain_inAddrRead
+        use_addr <= 0;
+      end else if (wait_until_read != 0) begin
+        wait_until_read <= wait_until_read-1;
+      end
+
+      if (wait_until_video == 1) begin
+        wait_until_video <= 0;
+        mem_out <= data_out;
+      end else if (wait_until_video != 0) begin
+        wait_until_video <= wait_until_video-1;
+      end
+
+      if (`inAddrWrite_full && `inDataWrite_full && idle && `out_empty) begin
+        write_enable     <= 1;
+        wait_until_write <= 1;
+        addr             <= { inAddrWrite_d, 1'b0 };
+        writeData        <= inDataWrite_d;
+        out_d            <= { 1'b1, 37'b0 };
+        use_addr         <= 1;
+        `fill_out
+        `drain_inDataWrite
+        `drain_inAddrWrite
+  
+      end else if (`inPixelX_full && `inPixelY_full && `inPixelValue_full && idle) begin
+        `drain_inPixelX
+        `drain_inPixelY
+        `drain_inPixelValue
+        write_enable     <= 1;
+        wait_until_write <= 1;
+        addr             <= { inAddr, 1'b0 };
+        writeData        <= inPixelValue_d;
+        use_addr        <= 1;
+
+      end else if (`inAddrRead_full && idle && `out_empty) begin
+        // next cycle (wait_until_read==3) will assert the address for the request
+        // cycle after that (wait_until_read==2) is the gap
+        // cycle after that (wait_until_read==1) will have the valid data being asserted back
+        // unfortunately, I seem to get errors unless I wait for an EXTRA cycle on top of this.
+//        wait_until_read <= 3;
+        wait_until_read <= 4;
+        addr            <= { inAddrRead_d, 1'b0 };
+        use_addr        <= 1;
+
+      end else if (last_vga_pixel_addr != vga_pixel_addr && idle && on_screen) begin
+        // wait_until_video can't be more than 3, because (3+1) is the ratio of the pixel clock to the host clock
+        wait_until_video    <= 3;
+        addr                <= { vga_pixel_addr, 1'b0 };
+        last_vga_pixel_addr <= vga_pixel_addr;
+
+      end
+  
+    end
+  end
+
+
+== UCF ===============================================================
+
+#Net "dvi_0/dvi_xclk_p_unbuffered" PERIOD =  5 ns HIGH 50%;
+
+NET  dvi_d0               LOC="AB8"   | IOSTANDARD="LVDCI_33";   # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d1               LOC="AC8"   | IOSTANDARD="LVDCI_33";   # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d2               LOC="AN12"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d3               LOC="AP12"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d4               LOC="AA9"   | IOSTANDARD="LVDCI_33";   # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d5               LOC="AA8"   | IOSTANDARD="LVDCI_33";   # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d6               LOC="AM13"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d7               LOC="AN13"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d8               LOC="AA10"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d9               LOC="AB10"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d10              LOC="AP14"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_d11              LOC="AN14"  | IOSTANDARD="LVDCI_33";  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_de               LOC="AE8"   | IOSTANDARD="LVDCI_33" | SLEW=FAST;   # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_reset_b          LOC="AK6"   | IOSTANDARD="LVCMOS33";   # Bank 18, Vcco=3.3V, No DCI
+NET  dvi_h                LOC="AM12"  | IOSTANDARD="LVDCI_33" | SLEW=FAST;  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_v                LOC="AM11"  | IOSTANDARD="LVDCI_33" | SLEW=FAST;  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_xclk_n           LOC="AL10"  | IOSTANDARD="LVCMOS33" | DRIVE=24 | SLEW=FAST;  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  dvi_xclk_p           LOC="AL11"  | IOSTANDARD="LVCMOS33" | DRIVE=24 | SLEW=FAST;  # Bank 22, Vcco=3.3V, DCI using 49.9 ohm resistors
+
+NET  dvi_gpio1            LOC="N30" | IOSTANDARD="LVCMOS18";   # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors
+NET  dvi_iic_scl          LOC="U27" | PULLUP | IOSTANDARD="LVCMOS18";   # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors
+NET  dvi_iic_sda          LOC="T29" | PULLUP | IOSTANDARD="LVCMOS18";   # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors
+
+NET  gpio_led_c           LOC="E8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  gpio_led_e           LOC="AG23";  # Bank 2, Vcco=3.3V
+NET  gpio_led_n           LOC="AF13";  # Bank 2, Vcco=3.3V
+NET  gpio_led_s           LOC="AG12";  # Bank 2, Vcco=3.3V
+NET  gpio_led_w           LOC="AF23";  # Bank 2, Vcco=3.3V
+
+NET  gpio_led_0           LOC="H18";   # Bank 3, Vcco=2.5V, No DCI
+NET  gpio_led_1           LOC="L18";   # Bank 3, Vcco=2.5V, No DCI
+NET  gpio_led_2           LOC="G15";   # Bank 3, Vcco=2.5V, No DCI
+NET  gpio_led_3           LOC="AD26" | IOSTANDARD="LVCMOS18";  # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors
+NET  gpio_led_4           LOC="G16";   # Bank 3, Vcco=2.5V, No DCI
+NET  gpio_led_5           LOC="AD25" | IOSTANDARD="LVCMOS18";  # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors
+NET  gpio_led_6           LOC="AD24" | IOSTANDARD="LVCMOS18";  # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors
+NET  gpio_led_7           LOC="AE24" | IOSTANDARD="LVCMOS18";  # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors
+
+######
+
+NET  sram_adv_ld_b        LOC="H8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_bw0             LOC="D10";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_bw1             LOC="D11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_bw2             LOC="J11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_bw3             LOC="K11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_clk             LOC="AG21";  # Bank 4, Vcco=3.3V, No DCI      
+NET  sram_clk             LOC="G8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_cs_b            LOC="J10";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d16             LOC="N10";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d17             LOC="E13";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d18             LOC="E12";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d19             LOC="L9";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d20             LOC="M10";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors      
+NET  sram_d21             LOC="E11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d22             LOC="F11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d23             LOC="L8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d24             LOC="M8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d25             LOC="G12";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d26             LOC="G11";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d27             LOC="C13";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d28             LOC="B13";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d29             LOC="K9";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d30             LOC="K8";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_d31             LOC="J9";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_dqp0            LOC="D12";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_dqp1            LOC="C12";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_dqp2            LOC="H10";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_dqp3            LOC="H9";    # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_flash_a0        LOC="K12";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a1        LOC="K13";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a2        LOC="H23";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a3        LOC="G23";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a4        LOC="H12";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a5        LOC="J12";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a6        LOC="K22";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a7        LOC="K23";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a8        LOC="K14";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a9        LOC="L14";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a10       LOC="H22";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a11       LOC="G22";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a12       LOC="J15";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a13       LOC="K16";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a14       LOC="K21";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a15       LOC="J22";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a16       LOC="L16";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a17       LOC="L15";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a18       LOC="L20";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a19       LOC="L21";   # Bank 1, Vcco=3.3V
+NET  sram_flash_a20       LOC="AE23";  # Bank 2, Vcco=3.3V
+NET  sram_flash_a21       LOC="AE22";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d0        LOC="AD19";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d1        LOC="AE19";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d2        LOC="AE17";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d3        LOC="AF16";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d4        LOC="AD20";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d5        LOC="AE21";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d6        LOC="AE16";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d7        LOC="AF15";  # Bank 2, Vcco=3.3V
+NET  sram_flash_d8        LOC="AH13";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d9        LOC="AH14";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d10       LOC="AH19";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d11       LOC="AH20";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d12       LOC="AG13";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d13       LOC="AH12";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d14       LOC="AH22";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_d15       LOC="AG22";  # Bank 4, Vcco=3.3V, No DCI
+NET  sram_flash_we_b      LOC="AF20";  # Bank 2, Vcco=3.3V
+NET  sram_mode            LOC="A13";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+NET  sram_oe_b            LOC="B12";   # Bank 20, Vcco=3.3V, DCI using 49.9 ohm resistors
+
+
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+
+  public void service() { }
+
+== FleetSim ==============================================================
+
+== Constants =========================================================
+
+== Test ==============================================================
+
+#expect 0
+#expect 0
+#expect 0
+
+#ship debug : Debug
+#ship video : Dvi
+
+video.inPixelX:
+  set word=0;
+  deliver;
+  send token to debug.in;
+video.inPixelY:
+  set word=0;
+  deliver;
+  send token to debug.in;
+video.inPixelValue:
+  set word=0;
+  deliver;
+  send token to debug.in;
+
+debug.in:
+  set word=0;
+  set ilc=*;
+  recv token, deliver;
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Fifo.ship b/ships/Fifo.ship
new file mode 100644 (file)
index 0000000..616c97b
--- /dev/null
@@ -0,0 +1,63 @@
+ship: Fifo
+
+== Ports ===========================================================
+data  in:   in
+
+data  out:  out
+
+== Constants ========================================================
+
+== TeX ==============================================================
+
+The {\tt Fifo} ship is a simple fifo.  Word-sized delivered to the {\tt
+in} port are enqueued into the fifo, and values which arrive at the
+end of the fifo are provided to the {\tt out} port.
+
+The internal capacity of the fifo is unspecified, but guaranteed to be
+at least 16 words.
+
+== Fleeterpreter ====================================================
+    private Queue<Long> fifo = new LinkedList<Long>();
+    public void service() {
+        if (box_in.dataReadyForShip()) {
+            fifo.add(box_in.removeDataForShip());
+        }
+        if (box_out.readyForDataFromShip() && fifo.size() > 0) {
+            box_out.addDataFromShip(fifo.remove());
+        }
+    }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+// not used
+
+== Test =================================================================
+// expected output
+#expect 9
+
+// ships required in order to run this code
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:   set ilc=*;  recv, deliver;
+fifo.in:
+  set word= 9;
+  deliver;
+  set ilc=63;
+  recv, deliver;
+  set ilc=37;
+  recv, deliver;
+
+fifo.out:
+  set ilc=63;
+  collect, send to fifo.in;
+  set ilc=36;
+  collect, send to fifo.in;
+  collect, send to debug.in;
+
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Lut3.ship b/ships/Lut3.ship
new file mode 100644 (file)
index 0000000..a85b8f3
--- /dev/null
@@ -0,0 +1,404 @@
+ship: Lut3
+
+== Ports ===========================================================
+data  in:   in1
+data  in:   in2
+data  in:   in3
+data  in:   inLut
+
+data  out:  out
+
+== Constants ========================================================
+
+AND
+OR
+XOR
+NAND
+NOR
+
+== TeX ==============================================================
+
+This ship implements a bitwise 3-input {\bf L}ook {\bf U}p {\bf
+T}able.  The least significant eight bits of the {\tt inLut} value
+form a truth table with three inputs and one output.
+
+When values are available at all four inputs they are consumed and a
+value is produced at {\tt out}.  Each bit of {\tt out} is produced by
+looking up the corresponding bits of {\tt in1}, {\tt in2}, and {\tt
+in3} in the {\tt inLut} truth table.
+
+In particular, the bits {\tt in1}, {\tt in2}, {\tt in3} are
+concatenated to form a three-bit number, with {\tt in3} as the {\it
+most significant} bit and {\tt in1} as the {\it least significant
+bit}.  This three-bit number, ranging from 0 to 7 (decimal), is used
+as a bit index into {\tt inLut}'s value (whose least significant bit
+is considered ``bit zero'').
+
+
+== Fleeterpreter ====================================================
+  public void service() {
+      if (box_in1.dataReadyForShip() &&
+          box_in2.dataReadyForShip() &&
+          box_in3.dataReadyForShip() &&
+          box_inLut.dataReadyForShip() &&
+          box_out.readyForDataFromShip()) {
+          long a      = box_in1.removeDataForShip();
+          long b      = box_in2.removeDataForShip();
+          long c      = box_in3.removeDataForShip();
+          long lut    = box_inLut.removeDataForShip();
+          long ret = 0;
+          ret |= ((lut & (1<<0))==0) ? 0 : (~a) & (~b) & (~c);
+          ret |= ((lut & (1<<1))==0) ? 0 : ( a) & (~b) & (~c);
+          ret |= ((lut & (1<<2))==0) ? 0 : (~a) & ( b) & (~c);
+          ret |= ((lut & (1<<3))==0) ? 0 : ( a) & ( b) & (~c);
+          ret |= ((lut & (1<<4))==0) ? 0 : (~a) & (~b) & ( c);
+          ret |= ((lut & (1<<5))==0) ? 0 : ( a) & (~b) & ( c);
+          ret |= ((lut & (1<<6))==0) ? 0 : (~a) & ( b) & ( c);
+          ret |= ((lut & (1<<7))==0) ? 0 : ( a) & ( b) & ( c);
+          box_out.addDataFromShip(ret);
+      }
+  }
+
+== FleetSim ==============================================================
+== FPGA ==============================================================
+
+  reg          out_draining;
+  wire [7:0]              lut;
+
+  genvar i;
+  generate
+    for(i=0; i<`WORDWIDTH; i=i+1) begin : OUT
+      assign out_d_[i] = lut[{in3_d[i], in2_d[i], in1_d[i]}];
+    end
+  endgenerate
+
+  assign lut = inLut_d[7:0];
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      out_draining <= 0;
+    end else begin
+      `cleanup
+      if (out_draining && `out_empty) begin
+         `drain_in1
+         `drain_in2
+         `drain_in3
+         `drain_inLut
+         out_draining <= 0;
+      end
+      if (!out_draining && `in1_full && `in2_full && `in3_full && `inLut_full && `out_empty) begin
+         `fill_out
+         out_draining <= 1;
+      end
+    end
+  end
+
+
+== Test =================================================================
+#expect  0
+#expect  -128
+#expect  64
+#expect  -64
+#expect  32
+#expect  -96
+#expect  96
+#expect  -32
+#expect  16
+#expect  -112
+#expect  80
+#expect  -48
+#expect  48
+#expect  -80
+#expect  112
+#expect  -16
+#expect  8
+#expect  -120
+#expect  72
+#expect  -56
+#expect  40
+#expect  -88
+#expect  104
+#expect  -24
+#expect  24
+#expect  -104
+#expect  88
+#expect  -40
+#expect  56
+#expect  -72
+#expect  120
+#expect  -8
+#expect  4
+#expect  -124
+#expect  68
+#expect  -60
+#expect  36
+#expect  -92
+#expect  100
+#expect  -28
+#expect  20
+#expect  -108
+#expect  84
+#expect  -44
+#expect  52
+#expect  -76
+#expect  116
+#expect  -12
+#expect  12
+#expect  -116
+#expect  76
+#expect  -52
+#expect  44
+#expect  -84
+#expect  108
+#expect  -20
+#expect  28
+#expect  -100
+#expect  92
+#expect  -36
+#expect  60
+#expect  -68
+#expect  124
+#expect  -4
+#expect  2
+#expect  -126
+#expect  66
+#expect  -62
+#expect  34
+#expect  -94
+#expect  98
+#expect  -30
+#expect  18
+#expect  -110
+#expect  82
+#expect  -46
+#expect  50
+#expect  -78
+#expect  114
+#expect  -14
+#expect  10
+#expect  -118
+#expect  74
+#expect  -54
+#expect  42
+#expect  -86
+#expect  106
+#expect  -22
+#expect  26
+#expect  -102
+#expect  90
+#expect  -38
+#expect  58
+#expect  -70
+#expect  122
+#expect  -6
+#expect  6
+#expect  -122
+#expect  70
+#expect  -58
+#expect  38
+#expect  -90
+#expect  102
+#expect  -26
+#expect  22
+#expect  -106
+#expect  86
+#expect  -42
+#expect  54
+#expect  -74
+#expect  118
+#expect  -10
+#expect  14
+#expect  -114
+#expect  78
+#expect  -50
+#expect  46
+#expect  -82
+#expect  110
+#expect  -18
+#expect  30
+#expect  -98
+#expect  94
+#expect  -34
+#expect  62
+#expect  -66
+#expect  126
+#expect  -2
+#expect  1
+#expect  -127
+#expect  65
+#expect  -63
+#expect  33
+#expect  -95
+#expect  97
+#expect  -31
+#expect  17
+#expect  -111
+#expect  81
+#expect  -47
+#expect  49
+#expect  -79
+#expect  113
+#expect  -15
+#expect  9
+#expect  -119
+#expect  73
+#expect  -55
+#expect  41
+#expect  -87
+#expect  105
+#expect  -23
+#expect  25
+#expect  -103
+#expect  89
+#expect  -39
+#expect  57
+#expect  -71
+#expect  121
+#expect  -7
+#expect  5
+#expect  -123
+#expect  69
+#expect  -59
+#expect  37
+#expect  -91
+#expect  101
+#expect  -27
+#expect  21
+#expect  -107
+#expect  85
+#expect  -43
+#expect  53
+#expect  -75
+#expect  117
+#expect  -11
+#expect  13
+#expect  -115
+#expect  77
+#expect  -51
+#expect  45
+#expect  -83
+#expect  109
+#expect  -19
+#expect  29
+#expect  -99
+#expect  93
+#expect  -35
+#expect  61
+#expect  -67
+#expect  125
+#expect  -3
+#expect  3
+#expect  -125
+#expect  67
+#expect  -61
+#expect  35
+#expect  -93
+#expect  99
+#expect  -29
+#expect  19
+#expect  -109
+#expect  83
+#expect  -45
+#expect  51
+#expect  -77
+#expect  115
+#expect  -13
+#expect  11
+#expect  -117
+#expect  75
+#expect  -53
+#expect  43
+#expect  -85
+#expect  107
+#expect  -21
+#expect  27
+#expect  -101
+#expect  91
+#expect  -37
+#expect  59
+#expect  -69
+#expect  123
+#expect  -5
+#expect  7
+#expect  -121
+#expect  71
+#expect  -57
+#expect  39
+#expect  -89
+#expect  103
+#expect  -25
+#expect  23
+#expect  -105
+#expect  87
+#expect  -41
+#expect  55
+#expect  -73
+#expect  119
+#expect  -9
+#expect  15
+#expect  -113
+#expect  79
+#expect  -49
+#expect  47
+#expect  -81
+#expect  111
+#expect  -17
+#expect  31
+#expect  -97
+#expect  95
+#expect  -33
+#expect  63
+#expect  -65
+#expect  127
+#expect  -1
+
+#ship debug        : Debug
+#ship lut          : Lut3
+#ship alu          : Alu
+
+lut.in1:   set word= 85; set ilc=*;  deliver;
+lut.in2:   set word= 51; set ilc=*;  deliver;
+lut.in3:   set word= 15; set ilc=*;  deliver;
+lut.out:   set ilc=*;  collect, send to debug.in;
+
+// cycle through truth tables using alu as INC
+alu.in2:
+   set word= 1;
+   set ilc=*;  deliver;
+alu.inOp:
+   set word= Alu.inOp[ADD];
+   set ilc=*;  deliver;
+alu.in1:
+   set word= 0;
+   deliver;
+   set ilc=*;  recv, deliver;
+alu.out:
+  set olc=2;
+  head;
+  recv token, collect, send to lut.inLut;
+  send to alu.in1;
+  tail;
+
+lut.inLut:
+  set word= 0;
+  deliver;
+  set ilc=*;  recv, deliver;
+
+// acks from debug ship trigger new truth tables
+debug.in:
+  set ilc=63;
+  recv, deliver, send token to alu.out;
+  set ilc=63;
+  recv, deliver, send token to alu.out;
+  set ilc=63;
+  recv, deliver, send token to alu.out;
+  set ilc=63;
+  recv, deliver, send token to alu.out;
+  set ilc=4;
+  recv, deliver, send token to alu.out;
+
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Memory.ship b/ships/Memory.ship
new file mode 100644 (file)
index 0000000..2d1d6f1
--- /dev/null
@@ -0,0 +1,248 @@
+ship: Memory
+
+== Ports ===========================================================
+data  in:    inCBD
+data  in:    inAddrRead
+data  in:    inAddrWrite
+data  in:    inDataWrite
+
+data  out:   out
+
+== TeX ==============================================================
+
+The {\tt Memory} ship represents an interface to a storage space,
+which can be used to read from it or write to it.  This storage space
+might be a fast on-chip cache, off chip DRAM, or perhaps even a disk
+drive.
+
+Generally, distinct {\tt Memory} ships do not access the same backing
+storage, although this is not strictly prohibited.
+
+Each {\tt Memory} ship may have multiple {\it interfaces}, numbered
+starting with {\tt 0}.  Each interface may have any subset of the
+following docks: {\tt inCBD}, {\tt inAddrRead}, {\tt inAddrWrite},
+{\tt inDataWrite}, and {\tt out}.  If {\tt inCBD} or {\tt inAddrRead}
+is present on an interface, then {\tt out} must be present as well.
+If {\tt inAddrWrite} is present then {\tt inDataWrite} must be present
+as well.
+
+Each interface serializes the operations presented to it; this means
+that an interface with both read and write capabilities will not be
+able to read and write concurrently.  Instead, a {\tt Memory} ship
+with the ability to read and write concurrently should have two
+interfaces, one which is read-only and one which is write-only.
+
+There may be multiple {\tt Memory} ships which interface to the same
+physical storage space.  An implementation of Fleet must provide
+additional documentation to the programmer indicating which {\tt
+Memory} ships correspond to which storage spaces.  A single {\tt
+Memory} ship may also access a ``virtual storage space'' formed by
+concatenating multiple physical storage spaces.
+
+\subsection*{Code Bag Fetch}
+
+When a word appears at the {\tt inCBD} port, it is treated as a {\it
+code bag descriptor}, as shown below:
+
+\begin{center}
+\setlength{\bitwidth}{3mm}
+{\tt
+\begin{bytefield}{37}
+  \bitheader[b]{36,6,5,0}\\
+  \bitbox{31}{Address} 
+  \bitbox{6}{size} 
+\end{bytefield}
+}
+\end{center}
+
+When a word arrives at the {\tt inCBD} port, it is treated as a memory
+read with {\tt inAddrRead=Address}, {\tt inStride=1}, and {\tt
+inCount=size}.
+
+\subsection*{Reading}
+
+When a word is delivered to {\tt inAddrRead}, the word residing in
+memory at that address is provided at {\tt out}.  The {\tt c-flag} at
+the {\tt out} port is set to zero.
+
+\subsection*{Writing}
+
+When a word is delivered to {\tt inAddrWrite} and {\tt inDataWrite},
+the word at {\tt inDataWrite} is written to the address specified by
+{\tt inAddrWrite}.  Once the word is successfully committed to memory,
+the value {\tt inAddr+inStride} is provided at {\tt out} (that is, the
+address of the next word to be written).  The {\tt c-flag} at
+the {\tt out} port is set to one.
+
+\subsection*{To Do}
+
+Stride and count are not implemented.
+
+We need a way to do an ``unordered fetch'' -- a way to tell the memory
+unit to retrieve some block of words in any order it likes.  This can
+considerably accelerate fetches when the first word of the region is
+not cached, but other parts are cached.  This can also be used for
+dispatching codebags efficiently -- but how will we make sure that
+instructions destined for a given pump are dispatched in the correct
+order (source sequence guarantee)?
+
+A more advanced form would be ``unordered fetch of ordered records''
+-- the ability to specify a record size (in words), the offset of the
+first record, and the number of records to be fetched.  The memory
+unit would then fetch the records in any order it likes, but would be
+sure to return the words comprising a record in the order in which
+they appear in memory.  This feature could be used to solve the source
+sequence guarantee problem mentioned in the previous paragraph.
+
+== Fleeterpreter ====================================================
+    private long[] mem = new long[0];
+    public long readMem(int addr) { return addr >= mem.length ? 0 : mem[addr]; }
+    public void writeMem(int addr, long val) {
+        if (addr >= mem.length) {
+            long[] newmem = new long[addr * 2 + 1];
+            System.arraycopy(mem, 0, newmem, 0, mem.length);
+            mem = newmem;
+        }
+        mem[addr] = val;
+    }
+    private Queue<Long> toDispatch = new LinkedList<Long>();
+    public void reset() {
+      super.reset();
+      mem = new long[0];
+      toDispatch.clear();
+    }
+    public void service() {
+        if (toDispatch.size() > 0) {
+            if (!box_out.readyForDataFromShip()) return;
+            box_out.addDataFromShip(toDispatch.remove());
+        }
+        if (box_inCBD.dataReadyForShip()) {
+            long val = box_inCBD.removeDataForShip();
+            long addr = ((Interpreter)getFleet()).CBD_OFFSET.getval(val);
+            long size = ((Interpreter)getFleet()).CBD_SIZE.getval(val);
+            for(int i=0; i<size; i++)
+              toDispatch.add(readMem((int)(addr+i)));
+        } else if (box_inAddrWrite.dataReadyForShip() && box_inDataWrite.dataReadyForShip() && box_out.readyForDataFromShip()) {
+            writeMem((int)box_inAddrWrite.removeDataForShip(), box_inDataWrite.removeDataForShip());
+            box_out.addDataFromShip(0,true);
+        } else if (box_inAddrRead.dataReadyForShip() && box_out.readyForDataFromShip()) {
+            box_out.addDataFromShip(readMem((int)box_inAddrRead.removeDataForShip()),false);
+        }
+    }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  `define BRAM_ADDR_WIDTH 14
+  `define BRAM_SIZE (1<<(`BRAM_ADDR_WIDTH))
+
+  reg    [(`WORDWIDTH-1):0]       ram [((`BRAM_SIZE)-1):0];
+  reg    [(`BRAM_ADDR_WIDTH-1):0] addr1;
+  reg    [(`BRAM_ADDR_WIDTH-1):0] addr2;
+  reg    [(`WORDWIDTH-1):0]       out1;
+  reg    [(`WORDWIDTH-1):0]       out2;
+
+  reg                             out_w;
+  reg                             write_flag;
+  reg [(`BRAM_ADDR_WIDTH-1):0]    cursor;
+  reg [(`CODEBAG_SIZE_BITS-1):0]  counter;
+
+  assign out_d_ = { out_w, out1 };
+
+  // I use "blocking assignment" here in order to facilitate BRAM inference
+  always @(posedge clk) begin
+    write_flag = 0;
+
+    if (rst) begin
+      `reset
+      cursor      = 0;
+      counter     = 0;
+    end else begin
+      `cleanup
+
+      if (counter!=0) begin
+        if (`out_empty) begin
+          `fill_out
+          out_w    = 0;
+          addr1    = cursor;
+          cursor   = cursor  + 1;
+          counter  = counter - 1;
+        end
+
+      end else if (`inCBD_full) begin
+        cursor    = inCBD_d[(`WORDWIDTH-1):(`CODEBAG_SIZE_BITS)];
+        counter   = inCBD_d[(`CODEBAG_SIZE_BITS-1):0];
+        addr1     = cursor;
+        `drain_inCBD
+
+      end else if (`out_empty && `inAddrRead_full) begin
+        addr1     = inAddrRead_d[(`WORDWIDTH-1):0];
+        `drain_inAddrRead
+        `fill_out
+        out_w     = 0;
+
+      end else if (`out_empty && `inAddrWrite_full && `inDataWrite_full) begin
+        write_flag = 1;
+        `drain_inAddrWrite
+        `drain_inDataWrite
+        `fill_out
+        addr2     = inAddrWrite_d[(`WORDWIDTH-1):0];
+        out_w     = 1;
+
+      end
+    end
+
+    // this must appear at the end of the block, outside of any if..then's
+    if (write_flag) 
+      ram[addr2] <= inDataWrite_d; 
+    out1 <= ram[addr1];
+    out2 <= ram[addr2]; 
+  end
+    
+
+
+
+== Test ==============================================================
+// Note: this only tests the read/write interfaces, not the inCBD interface
+// FIXME: test c-flag at out dock
+
+// expected output
+#expect 10
+
+// ships required in order to run this code
+#ship debug          : Debug
+#ship memory         : Memory
+
+memory.inAddrWrite:
+  set word=3;
+  deliver;
+  deliver;
+
+memory.inDataWrite:
+  set word=4;
+  deliver;
+  set word=10;
+  deliver;
+
+memory.inAddrRead:
+  recv token;
+  set word=3;
+  deliver;
+
+memory.out:
+  collect;
+  collect;
+  send token to memory.inAddrRead;
+  collect;
+  send to debug.in;
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+
+== Constants ========================================================
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Null.ship b/ships/Null.ship
new file mode 100644 (file)
index 0000000..38897c1
--- /dev/null
@@ -0,0 +1,22 @@
+ship: Null
+
+== Ports ===========================================================
+data  out:  out
+
+== Constants ========================================================
+
+== TeX ==============================================================
+== Fleeterpreter ====================================================
+    public void service() {
+    }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+
+== Test =================================================================
+#skip
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Random.ship b/ships/Random.ship
new file mode 100644 (file)
index 0000000..dd11dd3
--- /dev/null
@@ -0,0 +1,37 @@
+ship: Null
+
+== Ports ===========================================================
+data  out:  out
+
+== Constants ========================================================
+
+== TeX ==============================================================
+== Fleeterpreter ====================================================
+    public void service() {
+    }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  reg [`WORDWIDTH-1:0] out_d;
+  assign out_d_ = out_d;
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      out_d <= 0;
+    end else begin
+      `cleanup
+      if (`out_empty) begin
+        out_d <=  {out_d, out_d[17] ~^ out_d[10]}; 
+        `fill_out
+      end
+    end
+  end
+
+== Test =================================================================
+#skip
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Rotator.ship b/ships/Rotator.ship
new file mode 100644 (file)
index 0000000..74cb3f1
--- /dev/null
@@ -0,0 +1,119 @@
+ship: Rotator
+
+== Ports ===========================================================
+in:   in
+in:   inAmount
+
+out:  out
+
+  
+== TeX ==============================================================
+
+The Rotator performs bitwise rotations of words.  When a value is
+present at both {\tt in} and {\tt inAmount}, both values are consumed,
+the value {\tt in} is rotated {\it towards the least significant bit}
+by {\tt inAmount} bits and emitted at {\tt out}.
+
+The output is undefined if {\tt inAmount} is greater than or equal to
+the number of bits in a word.
+
+
+== Fleeterpreter ====================================================
+
+public void service() {
+  if (box_inAmount.dataReadyForShip() && box_in.dataReadyForShip() && box_out.readyForDataFromShip()) {
+    long amount = box_inAmount.removeDataForShip();
+    long data   = box_in.removeDataForShip();
+    long mask = ~((-1L) << getInterpreter().getWordWidth());
+    data = data & mask;
+    long res = ((data >> amount) | (data << (getInterpreter().getWordWidth()-amount))) & mask;
+    box_out.addDataFromShip(res, (res & (1L << (getInterpreter().getWordWidth()-1)))!=0);
+  }
+}
+
+
+== FPGA ==============================================================
+
+  reg [(`WORDWIDTH):0] out_d;
+  assign out_d_ = out_d;
+
+  reg full;
+  initial full = 0;
+
+  reg [5:0] shamt;
+  initial shamt = 0;
+
+  wire shamt_eq;
+  assign shamt_eq = (shamt[5:0] == (inAmount_d[5:0]));
+
+  always @(posedge clk) begin
+    if (rst) begin
+      `reset
+      full <= 0;
+    end else begin
+      `cleanup
+      if (`in_full && `inAmount_full && `out_empty) begin
+        if (!full) begin
+          out_d <= { 1'b0, in_d };
+          shamt <= 0;
+          full  <= 1;
+        end else if (!shamt_eq) begin
+          out_d <= { out_d[0], out_d[0], out_d[`WORDWIDTH-1:1] };
+          shamt <= shamt+1;
+        end else begin
+          `drain_in
+          `drain_inAmount
+          `fill_out
+          full <= 0;
+        end
+      end
+    end
+  end
+
+== Test ==============================================================
+
+
+// expected output
+#expect 2
+#expect 0
+#expect -0x1000000000
+#expect 1
+#expect 44627559471
+#expect 0
+
+
+// ships required in order to run this code
+#ship debug        : Debug
+#ship rotator      : Rotator
+
+debug.in: set ilc=*;  recv, deliver;
+
+rotator.in:
+   set word=1;
+   deliver;
+   set word=1;
+   deliver;
+   set word=21615257152;
+   deliver;
+rotator.inAmount:
+   set word=36;
+   deliver;
+   set word=1;
+   deliver;
+   set word=17;
+   deliver;
+rotator.out:
+   set olc=3;
+   head;
+   collect, send to debug.in;
+   set flags a=c, b=b;
+   [!a] set word=0;
+   [a]  set word=1;
+   send to debug.in;
+   tail;
+
+
+
+== Contributors =========================================================
+Amir Kamil <kamil@cs.berkeley.edu>
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Timer.ship b/ships/Timer.ship
new file mode 100644 (file)
index 0000000..5eff426
--- /dev/null
@@ -0,0 +1,42 @@
+ship: Timer
+
+== Ports ===========================================================
+data  out:   out
+
+== FPGA ==============================================================
+
+  reg [37:0] out_d;
+  assign out_d_ = out_d;
+
+  always @(posedge clk) begin
+
+    if (rst) begin
+      `reset
+      out_d <= 0;
+    end else begin
+      `cleanup
+
+      out_d <= out_d+1;
+
+      if (`out_empty) begin
+         `fill_out
+      end
+
+    end
+  end
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+
+  public void service() { }
+
+== FleetSim ==============================================================
+
+== Constants =========================================================
+
+== Test ==============================================================
+#skip
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/ships/Video.ship b/ships/Video.ship
new file mode 100644 (file)
index 0000000..b614242
--- /dev/null
@@ -0,0 +1,225 @@
+ship: Video
+
+== Ports ===========================================================
+data  in:    inX
+data  in:    inY
+data  in:    inData
+
+percolate up:         vga_psave   1
+percolate up:         vga_hsync   1
+percolate up:         vga_vsync   1
+percolate up:         vga_sync    1
+percolate up:         vga_blank   1
+percolate up:         vga_r       8
+percolate up:         vga_g       8
+percolate up:         vga_b       8
+percolate up:         vga_clkout  1
+
+== TeX ==============================================================
+
+== Fleeterpreter ====================================================
+
+  private java.awt.Frame frame = null;
+  public void service() {
+  if (box_inX.dataReadyForShip() &&
+      box_inY.dataReadyForShip() &&
+      box_inData.dataReadyForShip()
+      ) {
+      long x      = box_inX.removeDataForShip();
+      long y      = box_inY.removeDataForShip();
+      long d      = box_inData.removeDataForShip();
+
+      if (frame==null) {
+           frame = new java.awt.Frame();
+           java.awt.Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
+           frame.setSize((int)dim.getWidth(),(int)dim.getHeight());
+           frame.show();
+           frame.setBackground(new java.awt.Color(0,0,0));
+      }
+      java.awt.Color c = new java.awt.Color(
+         ((d & (1L<<2))!=0) ? 0xff : 0x00,
+         ((d & (1L<<1))!=0) ? 0xff : 0x00,
+         ((d & (1L<<0))!=0) ? 0xff : 0x00
+      );
+      java.awt.Graphics2D g = (java.awt.Graphics2D)frame.getGraphics();
+      g.transform(java.awt.geom.AffineTransform.getScaleInstance(((double)frame.getWidth())/640, ((double)frame.getHeight())/480));
+      g.setColor(c);
+      g.fillRect((int)x,(int)y,1,1);
+
+    }
+  }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+  wire vga_clk_unbuffered;  // synthesis attribute period of vga_clk_unbuffered is "40 ns";
+
+  wire vga_clk;
+  wire vga_clk_fb;
+
+  BUFG GBUF_FOR_VGA_CLOCK (.I(vga_clk_unbuffered), .O(vga_clk));
+  DCM  // 25Mhz VGA clock
+   #(
+      .CLKFX_MULTIPLY(4),
+      .CLKFX_DIVIDE(16),
+      .CLKIN_PERIOD("20 ns")
+    ) vgadcm (
+      .CLKIN (clk),
+      .CLKFB(vga_clk_fb),
+      .CLKFX (vga_clk_unbuffered),
+      .CLK0  (vga_clk_fb)
+    );
+
+
+  wire [31:0] vga_pixel_addr_;
+  wire        vga_pixel_r;
+  wire        vga_pixel_a_;
+  reg         vga_pixel_a;
+  assign vga_pixel_a_ = vga_pixel_a;
+  wire [18:0] inAddr;
+
+  reg we;
+  wire [2:0] mem_out;
+  wire  [31:0] vga_pixel_data;
+  assign vga_pixel_data = {
+             8'b0,
+             mem_out[2], 7'b0,
+             mem_out[1], 7'b0,
+             mem_out[0], 7'b0
+  };
+
+  assign inAddr = inX_d + (inY_d * 640);
+
+  vram vram(clk, !rst, we, inAddr[18:0], vga_pixel_addr_[20:2], inData_d, , mem_out);
+
+  wb_vga wb_vga(
+       .wb_clk_i(clk),
+       .wb_rst_i(rst),
+       
+       .fbwb_adr_o(vga_pixel_addr_),
+       .fbwb_stb_o(vga_pixel_r),
+       .fbwb_ack_i(vga_pixel_a_),
+       .fbwb_dat_i(vga_pixel_data),
+
+       /* VGA signals */
+        .vga_clk(vga_clk),
+        .vga_psave(vga_psave),
+        .vga_hsync(vga_hsync),
+        .vga_vsync(vga_vsync),
+        .vga_sync(vga_sync),
+        .vga_blank(vga_blank),
+        .vga_r(vga_r),
+        .vga_g(vga_g),
+        .vga_b(vga_b),
+        .vga_clkout(vga_clkout)
+  );
+
+  always @(posedge clk) begin
+
+    if (rst) begin
+      `reset
+    end else begin
+      `cleanup
+      vga_pixel_a <= vga_pixel_r;
+
+      if (`inX_full && `inY_full && `inData_full) begin
+         we <= 1;
+         `drain_inX
+         `drain_inY
+         `drain_inData
+      end else begin
+         we <= 0;
+      end
+
+    end
+  end
+
+== UCF ===============================================================
+
+## VGA ##############################################################################
+
+#net "vga_hsync" loc   = f9;
+#net "vga_hsync" slew  = slow;
+#net "vga_hsync" drive = 2;
+#
+#net "vga_vsync" loc   = h10;
+#net "vga_vsync" slew  = slow;
+#net "vga_vsync" drive = 2;
+#
+#net "vga_clkout"  loc ="c12";
+#net "vga_clkout"  slew = fast;
+#net "vga_clkout"  drive = 8;
+#
+#net "vga_r<7>" loc ="h8";
+#net "vga_r<6>" loc ="c5";
+#net "vga_r<5>" loc ="h9";
+#net "vga_r<4>" loc ="g12";
+#net "vga_r<3>" loc ="g11";
+#net "vga_r<2>" loc ="g10";
+#net "vga_r<1>" loc ="f11";
+#net "vga_r<0>" loc ="f10";
+#net "vga_r<*>" slew = slow;
+#net "vga_r<*>" drive = 2;
+#
+#net "vga_g<7>" loc ="d5";
+#net "vga_g<6>" loc ="d4";
+#net "vga_g<5>" loc ="f8";
+#net "vga_g<4>" loc ="e13";
+#net "vga_g<3>" loc ="e12";
+#net "vga_g<2>" loc ="e11";
+#net "vga_g<1>" loc ="e9";
+#net "vga_g<0>" loc ="e8";
+#net "vga_g<*>" slew = slow;
+#net "vga_g<*>" drive = 2;
+#
+#net "vga_b<7>" loc ="c4";
+#net "vga_b<6>" loc ="c3";
+#net "vga_b<5>" loc ="d12";
+#net "vga_b<4>" loc ="d11";
+#net "vga_b<3>" loc ="d10";
+#net "vga_b<2>" loc ="d9";
+#net "vga_b<1>" loc ="c13";
+#net "vga_b<0>" loc ="g8";
+#net "vga_b<*>" slew = slow;
+#net "vga_b<*>" drive = 2;
+#
+#net "vga_*" iostandard = lvcmos33;
+#
+
+
+== Constants ========================================================
+
+== Test ==============================================================
+
+#skip
+// can't test much here; just make sure it accepts values
+
+#expect 0
+#expect 0
+#expect 0
+
+#ship debug : Debug
+#ship video : Video
+
+video.inX:
+  set word=0;
+  deliver;
+  send token to debug.in;
+video.inY:
+  set word=0;
+  deliver;
+  send token to debug.in;
+video.inData:
+  set word=0;
+  deliver;
+  send token to debug.in;
+
+debug.in:
+  set word=0;
+  set ilc=*;
+  recv token, deliver;
+
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>
diff --git a/src/edu/berkeley/fleet/Main.java b/src/edu/berkeley/fleet/Main.java
new file mode 100644 (file)
index 0000000..f8e5956
--- /dev/null
@@ -0,0 +1,219 @@
+package edu.berkeley.fleet;
+import edu.berkeley.sbp.util.ANSI;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.interpreter.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.util.*;
+import java.io.*;
+import java.util.*;
+
+public class Main {
+
+    static String command;
+    static HashMap<String,String> options = new HashMap<String,String>();
+    static ArrayList<String> args = new ArrayList<String>();
+
+    public static void main(String[] s) throws Exception {
+        if (s.length == 0) {
+            usage();
+            System.exit(-1);
+        }
+        boolean optionsDone = false;
+        for(int i=0; i<s.length; i++) {
+            if (!optionsDone && s[i].indexOf('=') != -1) {
+                options.put(s[i].substring(0, s[i].indexOf('=')),
+                            s[i].substring(s[i].indexOf('=')+1));
+               
+            } else if (!optionsDone) {
+                optionsDone = true;
+                command = s[i];
+            } else {
+                args.add(s[i]);
+            }
+        }
+
+        String target = options.get("target");
+        Fleet fleet;
+        if ("fpga".equals(target)) {
+            String bitfile = options.get("bitfile");
+            fleet = new Fpga();
+        } else if ("sim".equals(target) || "fleetsim".equals(target)) {
+            fleet = (Fleet)Class.forName("com.sunlabs.fleetsim.fleet.FleetDescription").newInstance();
+        } else if (command.equals("expand")) {
+            fleet = new Interpreter(new String[0], false);
+        } else {
+            fleet = new Interpreter();
+        }
+
+        if (!"yes".equals(options.get("verbose")))
+            Log.log = null;
+
+        if (command.equals("run")) {
+            InputStream is;
+            String filename = args.get(0);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            Reader r = new InputStreamReader(new FileInputStream(args.get(0)));
+            run(fleet, edu.berkeley.fleet.assembler.Main.assemble(fleet, r));
+
+        } else if (command.equals("expand")) {
+            String name = new File(args.get(0)).getName();
+            if (name.endsWith(".ship"))
+                name = name.substring(0, name.length() - ".ship".length());
+            if (fleet instanceof edu.berkeley.fleet.fpga.Fpga) {
+                ((edu.berkeley.fleet.fpga.Fpga)fleet).expand(new ShipDescription(fleet, name, new BufferedReader(new InputStreamReader(new FileInputStream(args.get(0))))));
+            } else {
+                ((Interpreter)fleet).expand(new ShipDescription(fleet, name, new BufferedReader(new InputStreamReader(new FileInputStream(args.get(0))))));
+            }
+
+        } else if (command.equals("doc")) {
+            if (!new File(".tmp").exists())
+                new File(".tmp").mkdirs();
+            PrintWriter pw = new PrintWriter(new FileOutputStream(".tmp/FleetTwo.Manual.tex"));
+            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("doc/archman.tex")));
+            for(String ss = br.readLine(); ss!=null; ss = br.readLine())
+                pw.println(ss);
+            for(String f : new File("ships").list()) {
+                new ShipDescription(fleet, f, new BufferedReader(new InputStreamReader(new FileInputStream(new File("ships/"+f))))).printTeX(pw);
+            }
+            pw.println("\\end{document}");
+            pw.close();
+
+        } else if (command.equals("test")) {
+            for(int i=0; i<args.size(); i++)
+                test(fleet, new File(args.get(i)));
+        } else {
+            usage();
+            System.exit(-1);
+        }
+    }
+
+    static void runTest(Fleet fleet, Reader reader, String title) throws Exception {
+        Instruction[] instructions = null;
+        System.out.print("\r[    ] "  + ANSI.yellow(title)+": ");
+        try {
+            instructions = edu.berkeley.fleet.assembler.Main.assemble(fleet, reader);
+        } finally {
+            if (instructions==null)
+                System.out.println();
+        }
+        if (edu.berkeley.fleet.assembler.Parser.skip) {
+            System.out.println("\r[" + ANSI.yellow("SKIP") +
+                               "] "  + ANSI.yellow(title));
+            edu.berkeley.fleet.assembler.Parser.skip = false;
+            return;
+        }
+        FleetProcess fp = fleet.run(instructions);
+        //long now = System.currentTimeMillis();
+        try {
+            ArrayList<Long> expect = edu.berkeley.fleet.assembler.Parser.expect;
+            String output = "";
+            // FIXME: check for extraneous stuff at the end
+            String verdict = "[    ]";
+            boolean failed = false;
+            while(true) {
+                if (output.length() > 60 && !failed)
+                    output = "..."+output.substring(output.length()-57, output.length());
+                if (!failed && expect.size() == 0) verdict = "["+ANSI.green("PASS")+"]";
+                System.out.print("\r" + verdict + " " + ANSI.yellow(title) + ": " + output);
+                if (failed) break;
+                if (expect.size() == 0) break;
+                //if (now!=0) { System.err.println(); System.err.println(System.currentTimeMillis()-now); now=0;}
+                long l = unBitSet(fp.recvWord());
+                long l2 = expect.remove(0);
+
+                // FIXME, this is ugly and not size-independent
+                if ((l & (1L << 36)) != 0) {
+                    l = l | (0xffffffffffffffffL << 37);
+                }
+                // FIXME, this is ugly and not size-independent
+                if ((l2 & (1L << 36)) != 0) {
+                    l2 = l2 | (0xffffffffffffffffL << 37);
+                }
+
+                if (l!=l2) {
+                    verdict = "["+ANSI.red("FAIL")+"]";
+                    output += ANSI.red("0x"+Long.toString(l, 16)) +
+                        ANSI.yellow(" (expected ")+ANSI.green("0x"+Long.toString(l2, 16))+ANSI.yellow(")");
+                    failed = true;
+                    continue;
+                } else {
+                    output += ("0x"+Long.toString(l2, 16) + " ");
+                }
+            }
+            System.out.println();
+        } finally {
+            fp.terminate();
+        }
+    }
+
+    static void test(Fleet fleet, File f) throws Exception {
+        if (f.isDirectory()) {
+            for(String s : f.list())
+                test(fleet, new File(f.getPath() + File.separatorChar + s));
+            return;
+        } else if (f.getPath().endsWith(".fleet") || f.getPath().endsWith(".test")) {
+            runTest(fleet, new InputStreamReader(new FileInputStream(f)), f.getPath());
+        } else if (f.getPath().endsWith(".ship")) {
+            ShipDescription sd = new ShipDescription(fleet, f.getName(), new BufferedReader(new InputStreamReader(new FileInputStream(f))));
+            String testsection = sd.getSection("test");
+            if (testsection == null)
+                System.out.println("no test for " + sd.getName() + "!");
+            else if (fleet.getShip(sd.getName(),0)==null && !(fleet instanceof edu.berkeley.fleet.assembler.Parser.FleetWithDynamicShips))
+                System.out.println("specified Fleet does not have any ships of type " + sd.getName());
+            else
+                runTest(fleet, new StringReader(testsection), sd.getName());
+        }
+    }
+
+    public static void run(Fleet fleet, Instruction[] instructions) throws IOException {
+        FleetProcess client = fleet.run(instructions);
+        while(true) {
+            long result = unBitSet(client.recvWord());
+            System.err.print(result);
+            System.err.print(" 0x");
+            System.err.print(Long.toString(result, 16));
+            System.err.println();
+        }
+    }
+
+    public static long unBitSet(BitVector bs) {
+        long val = 0;
+        for(int i=0; i<37; i++) {
+            if (bs.get(i))
+                val |= (1L << i);
+        }
+        if ((val & (1L << 36)) != 0)
+            val = val | (0xffffffffffffffffL << 36);
+        return val;
+    }
+
+    static void usage() {
+        System.err.println(".........................................................................");
+        System.err.println("Fleet Framework                              UC Berkeley, Sun Labs / 2007");
+        System.err.println("");
+        System.err.println("usage:  java -jar fleet.jar [options] [command] [filename] [args]");
+        System.err.println("");
+        System.err.println("[options] is in the form key=val; supported keys are:");
+        System.err.println("   target={sim,fpga,interp}");
+        System.err.println("   bitfile=(hardware image for fpga)");
+        System.err.println("   verbose={yes,no}");
+        System.err.println("");
+        System.err.println("[command] is one of:");
+        System.err.println("   asm");
+        System.err.println("   disasm");
+        System.err.println("   typeset");
+        System.err.println("   extract [section]");
+        System.err.println("   run");
+        System.err.println("");
+        System.err.println("[filename] is one of:");
+        System.err.println("   *.fa          Fleet assembler");
+        System.err.println("   *.f0          F0 code (not yet supported)");
+        System.err.println("   *.fo          Fleet binary object");
+        System.err.println("   *.ship        Ship description");
+        System.err.println("");
+        System.err.println("All [args] not consumed by [command] are passed to target");
+        System.err.println("");
+    }
+
+}
\ No newline at end of file
diff --git a/src/edu/berkeley/fleet/api/BitVector.java b/src/edu/berkeley/fleet/api/BitVector.java
new file mode 100644 (file)
index 0000000..92cb6a0
--- /dev/null
@@ -0,0 +1,179 @@
+package edu.berkeley.fleet.api;
+
+/**
+ *  A sequence of bits with a fixed length.  This class performs
+ *  important error-checking not found in the Java BitSet and
+ *  BigInteger classes.  Bits are numbered starting with LSB as "bit
+ *  zero".
+ *
+ *  The toLong(), set(long), and setAndSignExtend(long) methods offer
+ *  the following guarantee: for all i, unless an exception is thrown
+ *  the following identities will hold:
+ *
+ *     bv.set(i).toLong() == i
+ *     bv.equals(new BitVector(bv.length()).set(bv.toLong()))
+ *
+ *  An exception is thrown if the BitVector in question is more than
+ *  64 bits long (in which case it cannot be converted to a long with
+ *  toLong()) or the long in question cannot be represented as a two's
+ *  complement number using the number of bits allocated in the
+ *  BitVector.
+ */
+public class BitVector implements DeferredBitVector {
+
+    private final boolean[] bits;
+
+    private boolean immutable = false;
+
+    public BitVector(int length) {
+        this.bits = new boolean[length];
+    }
+
+    /** copy constructor */
+    public BitVector(BitVector bv) {
+        this(bv.length());
+        for(int i=0; i<bv.length(); i++)
+            set(i, bv.get(i));
+    }
+
+    /** copy the low-order bits of the argument into this BitVector; returns <tt>this</tt> */
+    public BitVector set(long value) {
+        if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+        for(int i=0; i<length(); i++)
+            set(i, ((value >>> i) & 1L) != 0);
+        return this;
+    }
+
+    public BitVector set(BitVector bv) {
+        if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+        if (length()!=bv.length()) throw new RuntimeException("attempt to copy between BitVectors of unequal sizes");
+        for(int i=0; i<length(); i++)
+            set(i, bv.get(i));
+        return this;
+    }
+
+    /** copy the low-order bits of the argument into this BitVector and sign extend; returns <tt>this</tt> */
+    public BitVector setAndSignExtend(long value) {
+        if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+        for(int i=0; i<length(); i++)
+            set(i, i<64 ? (((value >>> i) & 1L) != 0) : value<0 ? true : false);
+        return this;
+    }
+
+    /** returns the length of this BitVector */
+    public int length() {
+        return bits.length;
+    }
+    
+    /** sets the specified bit to the given value */
+    public BitVector set(int bit, boolean value) {
+        if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+        bits[bit] = value;
+        return this;
+    }
+
+    /** returns the value of the specified bit */
+    public boolean get(int bit) {
+        return bits[bit];
+    }
+
+    /** get a sub-BitVector of a BitVector */
+    public BitVector get(int high, int low) {
+        if (low < 0 || high < 0 || high>low)
+            throw new RuntimeException("attempt to invoke BitVector("+high+","+low+")");
+        if (high > length()-1)
+            throw new RuntimeException("attempt to invoke BitVector("+high+","+low+") on an "+length()+"-bit BitVector");
+        BitVector ret = new BitVector(1+high-low);
+        for(int i=low; i<=high; i++)
+            ret.set(i-low, get(i));
+        return ret;
+    }
+
+    public String toString() {
+        StringBuffer ret = new StringBuffer();
+        ret.append(length()+"");
+        ret.append("'b");
+        for(int i=length()-1; i>=0; i--)
+            ret.append(get(i) ? '1' : '0');
+        return ret.toString();
+    }
+
+    /** makes this BitVector immutable; cannot be undone */
+    public void setImmutable() {
+        immutable = true;
+    }
+
+    /** indicates if this BitVector has been marked as immutable */
+    public boolean getImmutable() {
+        return immutable;
+    }
+
+    public int hashCode() {
+        int ret = 0;
+        for(int i=0; i<length(); i++)
+            if (get(i))
+                ret ^= (1L << (i % 32));
+        return ret;
+    }
+
+    public boolean equalsZeroExtended(BitVector bv) {
+        for(int i=0; i<Math.min(bv.bits.length, bits.length); i++)
+            if (bits[i] != bv.bits[i])
+                return false;
+        return true;
+    }
+
+    public boolean equals(Object o) {
+        if (o==null || !(o instanceof BitVector)) return false;
+        BitVector bv = (BitVector)o;
+        if (bv.bits.length != bits.length) return false;
+        return equalsZeroExtended(bv);
+    }
+
+    /**
+     *  Converts this BitVector to a long, sign-extending if
+     *  length()<64 and throwing an exception if length()>64
+     */
+    public long toLong() {
+        if (length() > 64)
+            throw new RuntimeException("a " + length() + "-bit BitVector cannot fit in a Java long");
+        long ret = 0;
+        for(int i=0; i<64; i++)
+            if (i<length() ? get(i) : get(length()-1))
+                ret |= (1L << i);
+        return ret;
+    }
+
+    public BitVector getBitVector() {
+        return this;
+    }
+
+    public BitVector and(BitVector bv) {
+        if (bv.length() != this.length())
+            throw new RuntimeException("attempt to invoke BitVector.and() on BitVectors "+
+                                       "of mismatched size: this="+this+", bv="+bv);
+        BitVector ret = new BitVector(length());
+        for(int i=0; i<length(); i++)
+            ret.set(i, get(i) && bv.get(i));
+        return ret;
+    }
+
+    public BitVector or(BitVector bv) {
+        if (bv.length() != this.length())
+            throw new RuntimeException("attempt to invoke BitVector.or() on BitVectors "+
+                                       "of mismatched size: this="+this+", bv="+bv);
+        BitVector ret = new BitVector(length());
+        for(int i=0; i<length(); i++)
+            ret.set(i, get(i) || bv.get(i));
+        return ret;
+    }
+
+    public BitVector not() {
+        BitVector ret = new BitVector(length());
+        for(int i=0; i<length(); i++)
+            ret.set(i, !get(i));
+        return ret;
+    }
+}
+
+
diff --git a/src/edu/berkeley/fleet/api/DeferredBitVector.java b/src/edu/berkeley/fleet/api/DeferredBitVector.java
new file mode 100644 (file)
index 0000000..454795e
--- /dev/null
@@ -0,0 +1,10 @@
+package edu.berkeley.fleet.api;
+
+/**
+ *  A "deferred" BitVector; basically a placeholder to facilitate
+ *  instantiating literal instructions (shift/set) before the value is
+ *  known.
+ */
+public interface DeferredBitVector {
+    public BitVector getBitVector();
+}
diff --git a/src/edu/berkeley/fleet/api/Destination.java b/src/edu/berkeley/fleet/api/Destination.java
new file mode 100644 (file)
index 0000000..238db4f
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet.api;
+
+/**
+ *  A physical destination on the switch fabric -- may have multiple
+ *  paths to it from any particular source.
+ */
+public abstract class Destination {
+
+    private final Dock dock;
+
+    public Destination(Dock dock) {
+        this.dock = dock;
+    }
+
+    /** Get the Dock to which this destination belongs, null if none. */
+    public Dock getDock() { return dock; }
+
+    /** subclasses must override this */
+    public abstract String toString();
+
+}            
diff --git a/src/edu/berkeley/fleet/api/Dock.java b/src/edu/berkeley/fleet/api/Dock.java
new file mode 100644 (file)
index 0000000..e0b79fe
--- /dev/null
@@ -0,0 +1,48 @@
+package edu.berkeley.fleet.api;
+import java.util.*;
+
+/** A dock on a ship */
+public abstract class Dock {
+
+    private final Ship ship;
+
+    public Dock(Ship ship) {
+        this.ship = ship;
+    }
+
+    /** return the Ship to which this Dock belongs */
+    public Ship getShip() { return ship; }
+
+    /** the descriptive name of this dock (relative to its ship) */
+    public abstract String getName();
+
+    /** returns true if this is an input dock */
+    public abstract boolean isInputDock();
+
+    /** returns true if this is an output dock */
+    public abstract boolean isOutputDock();
+
+    /** returns the <tt>Path</tt> from this dock to <tt>dest</tt>, carrying the signal specified or none if null */
+    public abstract Path        getPath(Destination dest, BitVector signal);
+
+    /** the data destination of this dock */
+    public abstract Destination getDataDestination();
+
+    /** the instruction destination of this dock */
+    public abstract Destination getInstructionDestination();
+
+    /** 
+     *  The maximum number of instructions we can put in the Dock
+     *  instruction fifo, or Integer.MAX_VALUE if unbounded; note that
+     *  this does not include the epilogue fifo -- that can be
+     *  determined with getInstructionDestination().getFifoLength()
+     */
+    public abstract int getInstructionFifoSize();
+
+    /** get a constant associated with a dock; returns null if none found */
+    public BitVector getConstant(String constantName) {
+        throw new RuntimeException("unknown constant \""+constantName+"\" on dock " + this);
+    }
+
+    public String toString() { return getShip()+"."+getName(); }
+}            
diff --git a/src/edu/berkeley/fleet/api/Fleet.java b/src/edu/berkeley/fleet/api/Fleet.java
new file mode 100644 (file)
index 0000000..ce0cfb2
--- /dev/null
@@ -0,0 +1,57 @@
+package edu.berkeley.fleet.api;
+import java.io.*;
+import java.util.*;
+
+/**
+ *  An instance of Fleet; each Fleet consists of a collection of
+ *  <tt>Ship</tt>s.
+ *
+ *  <p><b>Note about instruction representation:</b> it is very
+ *  important to understand that the binary representation of an
+ *  instruction includes a path from the dock which will
+ *  <i>dispatch</i> the instruction to the dock which will
+ *  <i>execute</i> the instruction.  Therefore, an instruction cannot
+ *  be converted <i>to</i> binary form without supplying a
+ *  <i>dispatching dock</i> so the necessary path can be computed.
+ *  <b>Moreover:</b> because a given string of bits uniquely describes
+ *  a path only if given along with a starting point, instructions
+ *  cannot be converted <i>from</i> binary format without knowing the
+ *  dispatch dock from which they are meant to be dispatched. <i>This
+ *  is why the {@link readInstruction} and {@link writeInstruction}
+ *  methods take a "<tt>dispatchFrom</tt>" argument.</i>
+ */
+public abstract class Fleet implements Iterable<Ship> {
+
+    public abstract Iterator<Ship> iterator();
+
+    /** A ship is uniquely identified by its type (a string) and its ordinal; for example, Fifo[7]. */
+    public abstract Ship getShip(String type, int ordinal);
+
+    /** the natural word width of this machine */
+    public abstract int getWordWidth();
+
+    /** the width of the immediate field in the "shift data latch" instruction */
+    public abstract int getShiftWidth();
+
+    /** the width of the immediate field in the "set data latch" instruction */
+    public abstract int getSetWidth();
+    
+    /**
+     *  Encodes an instruction as a BitVector
+     *   @instruction  The instruction to encode
+     *   @dispatchFrom The dock from which the instruction being written is to be dispatched (required for encoding)
+     */
+    public abstract BitVector   encodeInstruction(Instruction instruction, Dock dispatchFrom);
+
+    /**
+     *  Decodes an instruction from a BitVector
+     *   @instruction  The instruction to decode
+     *   @dispatchFrom The dock from which the instructions being read are to be dispatched (required for decoding)
+     */
+    public abstract Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom);
+
+    /** If supported, run the given code and create a FleetProcess to interact with it. */
+    public FleetProcess run(Instruction[] program) {
+        throw new RuntimeException("class " + this.getClass().getName() + " does not implement method run()");
+    }
+}
diff --git a/src/edu/berkeley/fleet/api/FleetProcess.java b/src/edu/berkeley/fleet/api/FleetProcess.java
new file mode 100644 (file)
index 0000000..1db837f
--- /dev/null
@@ -0,0 +1,55 @@
+package edu.berkeley.fleet.api;
+import java.io.*;
+import java.util.*;
+
+/**
+ *  Represents a <i>running</i> "slave" fleet with debugging
+ *  facilities controlled by the "master" JVM.
+ *
+ *  <p>Each Fleet which supports this API must include:
+ *  <ul><li> The ability to dispatch instructions, words, and tokens
+ *           from the master, "on the fly".
+ *      <li> A "debug.in" dock such that any words delivered there
+ *           are sent back to the master.
+ *  </ul>
+ */
+public abstract class FleetProcess {
+
+    private boolean terminated = false;
+
+    /** dispatch an instruction; may be buffered */
+    public abstract void sendInstruction(Instruction i);
+
+    /** dispatch a word to a given destination; may be buffered */
+    public abstract void sendWord(Destination d, BitVector word);
+
+    /** dispatch a token to a given destination; may be buffered */
+    public abstract void sendToken(Destination d);
+
+    /** flush all instructions, words, and tokens dispatched so far */
+    public abstract void flush();
+
+    /** the dock used to read back data from the slave */
+    public abstract Dock getDebugInputDock();
+
+    /** returns the next word delivered at the dock specified by <tt>getDebugInputDock()</tt> */
+    public abstract BitVector recvWord();
+
+    /** Terminate the process; subclasses may be assured that this will be called exactly once. */
+    protected abstract void _terminate();
+
+    /** Terminate the process. */
+    public final synchronized void terminate() {
+        if (terminated) return;
+        terminated = true;
+        _terminate();
+    }
+
+    /** Returns true if the process is terminated */
+    public final boolean isTerminated() { return terminated; }
+
+    public synchronized void finalize() { terminate(); }
+
+    /** return the Fleet that this FleetProcess controls */
+    public abstract Fleet getFleet();
+}
diff --git a/src/edu/berkeley/fleet/api/Instruction.java b/src/edu/berkeley/fleet/api/Instruction.java
new file mode 100644 (file)
index 0000000..53ebf3c
--- /dev/null
@@ -0,0 +1,360 @@
+package edu.berkeley.fleet.api;
+import java.util.*;
+
+/** a Fleet instruction; includes execution location but not full dispatch path */
+public abstract class Instruction {
+
+    /** the dock which is to execute this instruction */
+    public final Dock      dock;
+
+    /** the instruction's predicate */
+    public final Predicate predicate;
+
+    Instruction(Dock dock, Predicate predicate) {
+        if (dock==null)      throw new RuntimeException("dock may not be null");
+        if (predicate==null) throw new RuntimeException("predicate may not be null");
+        this.dock = dock;
+        this.predicate = predicate;
+    }
+
+    //public abstract Instruction withLooping(boolean newLooping);
+    //public abstract Instruction withPredicate(Predicate newPredicate);
+
+    public String toString() {
+        String s = predicate.toString();
+        if (s.length()>0) s = "["+s+"] ";
+        return dock+": "+s;
+    }
+
+    /**
+     *  A <tt>set</tt> instruction.
+     *
+     *  Note that immediates are supplied as Java <tt>long</tt> values
+     *  because they are actual integers with two's complement
+     *  sign-extension semantics.  This is in contrast to most other
+     *  immediate values in the API which are raw bit sequences of
+     *  fixed length -- these are represented by instances of
+     *  <tt>BitVector</tt>.
+     */
+    public static class Set extends Instruction {
+
+        /** the destination (latch to be set) */
+        public final SetDest        dest;
+
+        /** the source (what will be put in the <tt>dest</tt> latch) */
+        public final SetSource      source;
+
+        /** if <tt>source</tt> is <tt>Immediate</tt>, this is the immediate value; an integer */
+        public final long           immediate;
+
+        /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "a" */
+        public final FlagFunction   newFlagA;
+
+        /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "b" */
+        public final FlagFunction   newFlagB;
+
+        /** basic constructor */
+        public Set(Dock dock, SetDest dest, SetSource source) { this(dock, Predicate.Default, dest, source); }
+        public Set(Dock dock, Predicate predicate, SetDest dest, SetSource source) {
+            super(dock, predicate);
+            OUTER: switch(dest) {
+                case InnerLoopCounter:
+                    switch(source) {
+                        case Infinity: case DataLatch: case Immediate: break OUTER;
+                        default: break;
+                    }
+                case OuterLoopCounter:
+                    switch(source) {
+                        case Decrement: case DataLatch: case Immediate: break OUTER;
+                        default: break;
+                    }
+                case DataLatch:
+                    if (source==SetSource.Immediate) break;
+                default: throw new RuntimeException("cannot set " + dest + " to " + source);
+            }
+            this.source = source;
+            this.dest = dest;
+            this.immediate = 0;
+            this.newFlagA = null;
+            this.newFlagB = null;
+        }
+
+        /** constructor for set instructions with immediates */
+        public Set(Dock dock, SetDest dest, long immediate) { this(dock, Predicate.Default, dest, immediate); }
+        public Set(Dock dock, Predicate predicate, SetDest dest, long immediate) {
+            super(dock, predicate);
+            if (dest!=SetDest.InnerLoopCounter && dest!=SetDest.OuterLoopCounter && dest!=SetDest.DataLatch)
+                throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate");
+            this.source = SetSource.Immediate;
+            this.dest = dest;
+            this.immediate = immediate;
+            this.newFlagA = null;
+            this.newFlagB = null;
+        }
+
+        /** constructor for <tt>set flags</tt> instructions */
+        public Set(Dock dock, FlagFunction newFlagA, FlagFunction newFlagB) { this(dock, Predicate.Default, newFlagA, newFlagB); }
+        public Set(Dock dock, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) {
+            super(dock, predicate);
+            this.source = SetSource.Immediate;
+            this.dest = SetDest.Flags;
+            this.immediate = 0;
+            this.newFlagA = newFlagA;
+            this.newFlagB = newFlagB;
+        }
+
+        /** possible sources for the Set instruction */
+        public static enum SetSource {
+            Infinity, DataLatch, Immediate, Decrement;
+        }
+        /** possible destinations for the Set instruction */
+        public static enum SetDest {
+            InnerLoopCounter, OuterLoopCounter, Flags, DataLatch;
+        }
+
+        /**
+         *  (Immutable) a truth table describing how to update a flag
+         *  based on the value of other flags; it is the logical OR of
+         *  a set of flag predicates.  This class is immutable; all
+         *  methods that alter the function return a new object.
+         */
+        public static class FlagFunction implements Iterable<Predicate> {
+
+            /** the function that always assigns zero */
+            public static final FlagFunction ZERO = new FlagFunction();
+
+            /** the function that always assigns one */
+            public static final FlagFunction ONE  = ZERO.add(Predicate.FlagA).add(Predicate.NotFlagA);
+
+            private final java.util.Set<Predicate> predicates;
+
+            public Iterator<Predicate> iterator() { return predicates.iterator(); }
+
+            private FlagFunction() { this(Collections.EMPTY_SET); }
+            private FlagFunction(java.util.Set<Predicate> set) { this.predicates = Collections.unmodifiableSet(set); }
+
+            /** returns the function which is the logical OR of this function and <tt>ff</tt> */
+            public FlagFunction add(FlagFunction ff) {
+                FlagFunction ret = this;
+                for(Predicate p : ff) ret = ret.add(p);
+                return ret;
+            }
+
+            /** returns the function which is the logical OR of this function and <tt>p</tt> */
+            public FlagFunction add(Predicate p) {
+                HashSet h = new HashSet();
+                h.addAll(predicates);
+                switch(p) {
+                    case FlagA: case NotFlagA:
+                    case FlagB: case NotFlagB:
+                    case FlagC: case NotFlagC:
+                        break;
+                    default:
+                        throw new RuntimeException("invalid predicate in FlagFunction: " + p);
+                }
+                h.add(p);
+                return new FlagFunction(h);
+            }
+
+            /** remove <tt>p</tt> from the set of terms which this function is the logical OR of */
+            public FlagFunction remove(Predicate p) {
+                HashSet h = new HashSet();
+                h.addAll(predicates);
+                h.remove(p);
+                return new FlagFunction(h);
+            }
+
+            public String toString() {
+                if (predicates.isEmpty()) return "0";
+                if (predicates.contains(Predicate.FlagA) && predicates.contains(Predicate.NotFlagA)) return "1";
+                if (predicates.contains(Predicate.FlagB) && predicates.contains(Predicate.NotFlagB)) return "1";
+                if (predicates.contains(Predicate.FlagC) && predicates.contains(Predicate.NotFlagC)) return "1";
+                StringBuffer ret = new StringBuffer();
+                boolean empty = true;
+                for(Predicate p : new Predicate[] {
+                        Predicate.FlagA, Predicate.NotFlagA,
+                        Predicate.FlagB, Predicate.NotFlagB,
+                        Predicate.FlagC, Predicate.NotFlagC })
+                    if (predicates.contains(p)) {
+                        if (!empty) ret.append("|");
+                        ret.append(p);
+                        empty = false;
+                    }
+                return ret.toString();
+            }
+
+            public boolean evaluate(boolean flag_a, boolean flag_b, boolean flag_c, boolean olc_zero) {
+                boolean ret = false;
+                for(Predicate p : this)
+                    ret |= p.evaluate(flag_a, flag_b, flag_c, olc_zero);
+                return ret;
+            }
+        }
+
+        public String toString() {
+            switch(dest) {
+                case InnerLoopCounter:
+                    switch(source) {
+                        case Infinity: return super.toString()+"set ilc=*;";
+                        case DataLatch: return super.toString()+"set ilc=data;";
+                        case Immediate: return super.toString()+"set ilc="+immediate+";";
+                    }
+                case OuterLoopCounter:
+                    switch(source) {
+                        case Decrement: return super.toString()+"set olc--;";
+                        case DataLatch: return super.toString()+"set olc=data;";
+                        case Immediate: return super.toString()+"set olc="+immediate+";";
+                    }
+                case Flags: return super.toString()+"set flags a="+newFlagA+", b="+newFlagB+";";
+                case DataLatch: return super.toString()+"set word="+immediate+";";
+            }
+            throw new Error("impossible");
+        }
+    }
+
+    /** shifts an immediate into the low-order bits of the data latch */
+    public static class Shift extends Instruction {
+        public final DeferredBitVector immediate;
+        public Shift(Dock dock, DeferredBitVector immediate) { this(dock, Predicate.Default, immediate); }
+        public Shift(final Dock dock, Predicate predicate, final DeferredBitVector arg) {
+            super(dock, predicate);
+            this.immediate = new DeferredBitVector() {
+                    public BitVector getBitVector() {
+                        BitVector ret = arg.getBitVector();
+                        if (ret.length() != dock.getShip().getFleet().getShiftWidth())
+                            throw new RuntimeException("attempt to create a Shift instruction with a "+ret.length()+
+                                                       "-bit immediate on a Fleet that uses "+dock.getShip().getFleet().getShiftWidth()+
+                                                       "-bit shift instructions");
+                        return ret;
+                    }
+                };
+        }
+        public String toString() { return super.toString()+"shift "+immediate.getBitVector(); }
+    }
+
+    /** a flush instruction */
+    public static class Flush extends Instruction {
+        public Flush(Dock dock) { this(dock, Predicate.Default); }
+        public Flush(Dock dock, Predicate predicate) {
+            super(dock, predicate);
+            if (!dock.isInputDock()) throw new RuntimeException("Flush is only allowed at input docks");
+        }
+        public String toString() { return super.toString()+"flush;"; }
+    }
+
+    /** all communication is performed with this instruction */
+    public static class Move extends Instruction {
+
+        /** if true, this instruction is vulnerable to torpedoes */
+        public final boolean     interruptible;
+
+        /** if non-null, the path to load into the path latch */
+        public final Path        path;
+
+        /** if true, a token will be consumed before execution */
+        public final boolean     tokenIn;
+
+        /** if true, data will be consumed before execution */
+        public final boolean     dataIn;
+
+        /** if true, the data consumed will be copied into the data latch */
+        public final boolean     latchData;
+
+        /** if true, the data consumed will be copied into the path latch */
+        public final boolean     latchPath;
+
+        /** if true, the value in the data latch will be transmitted (to the location in the path latch if at an output dock) */
+        public final boolean     dataOut;
+
+        /** if true, the a token will be transmitted to the location in the path latch */
+        public final boolean     tokenOut;
+
+        public Move(Dock        dock,
+                    Path        path,
+                    boolean     tokenIn,
+                    boolean     dataIn,
+                    boolean     latchData,
+                    boolean     latchPath,
+                    boolean     dataOut,
+                    boolean     tokenOut
+                    ) {
+            this(dock, Predicate.Default, false, path, tokenIn, dataIn, latchData, latchPath, dataOut, tokenOut); }
+        public Move(Dock        dock,
+                    Predicate   predicate,
+                    boolean     interruptible,
+                    Path        path,
+                    boolean     tokenIn,
+                    boolean     dataIn,
+                    boolean     latchData,
+                    boolean     latchPath,
+                    boolean     dataOut,
+                    boolean     tokenOut
+                    ) {
+            super(dock, predicate);
+            this.path = path;
+            this.tokenIn = tokenIn;
+            this.dataIn = dataIn;
+            this.latchData = latchData;
+            this.latchPath = latchPath;
+            this.dataOut = dataOut;
+            this.tokenOut = tokenOut;
+            this.interruptible = interruptible;
+            if (dock != null && dock.isInputDock() && tokenIn && dataIn)
+                throw new RuntimeException("cannot have two \"recv\"s: " + this);
+            if (dock != null && dock.isOutputDock() && tokenOut && dataOut)
+                throw new RuntimeException("cannot have two \"send\"s: " + this);
+            if (latchData && !dataIn)
+                throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this);
+            if (latchPath && !dataIn)
+                throw new RuntimeException("cannot have latchPath bit set without dataIn bit: " + this);
+            if (latchPath && path!=null)
+                throw new RuntimeException("cannot have latchPath and a non-null path: " + this);
+        }
+
+        public String toString() {
+            StringBuffer ret = new StringBuffer();
+            if (tokenIn)                        ret.append(", recv token");
+            if (dataIn) {
+                if      (latchPath && latchData) ret.append(!dock.isInputDock() ? ", collect packet"  : ", recv packet");
+                if      (latchPath)              ret.append(!dock.isInputDock() ? ", collect path"    : ", recv path");
+                else if (latchData)              ret.append(!dock.isInputDock() ? ", collect"         : ", recv");
+                else                             ret.append(!dock.isInputDock() ? ", collect nothing" : ", recv nothing");
+            }
+            if (dataOut && dock.isInputDock())  ret.append(", deliver");
+            if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send"       : ", send to "  + pathToString(path));
+            if (tokenOut)                       ret.append(path==null ? ", send token" : ", send token to " + pathToString(path));
+            String s = ret.toString();
+            s = s.equals("") ? "nop" : s.substring(2);
+            if (interruptible) s = "[T] " + s;
+            return super.toString()+s+";";
+        }
+
+        private String pathToString(Path path) {
+            BitVector signal = path.getSignal();
+            if (signal!=null)
+                for(int i=0; i<signal.length(); i++)
+                    if (signal.get(i))
+                        return (path.getDestination()+":"+signal.toLong());
+            return (path.getDestination()+"");
+        }
+    }
+
+    /** a flush instruction */
+    public static class Abort extends Instruction {
+        public Abort(Dock dock, Predicate predicate) { super(dock, predicate); }
+        public String toString() { return super.toString()+"abort;"; }
+    }
+
+    /** marks the start of a loop; closes the hatch */
+    public static class Head extends Instruction {
+        public Head(Dock dock) { super(dock, Predicate.IgnoreFlagD); }
+        public String toString() { return dock+": head;"; }
+    }
+
+    /** marks the end of a loop; closes the hatch */
+    public static class Tail extends Instruction {
+        public Tail(Dock dock) { super(dock, Predicate.IgnoreFlagD); }
+        public String toString() { return dock+": tail;"; }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/api/Path.java b/src/edu/berkeley/fleet/api/Path.java
new file mode 100644 (file)
index 0000000..5de20fb
--- /dev/null
@@ -0,0 +1,29 @@
+package edu.berkeley.fleet.api;
+import java.util.*;
+
+/**
+ *  Represents a path through the switch fabric, from a Dock (source)
+ *  to a Destination, plus an optional "signal" value.
+ */
+public abstract class Path {
+
+    /** The start of the path. */
+    public abstract Dock        getSource();
+
+    /** The end of the path. */
+    public abstract Destination getDestination();
+
+    /** The number of units of buffering along this path. */
+    public abstract int         getBufferingAmount();
+
+    /** A metric, in unspecified units, of the latency along this path; less is better. */
+    public abstract int         getLatencyMetric();
+
+    /** An additional quantity of bits to be transmitted along with a packet, or null if none. */
+    public abstract BitVector   getSignal();
+
+    public String toString() {
+        return getSource() + "->" + getDestination() + ((getSignal()==null||getSignal().length()==0)?"":(":"+getSignal()));
+    }
+
+}            
diff --git a/src/edu/berkeley/fleet/api/Predicate.java b/src/edu/berkeley/fleet/api/Predicate.java
new file mode 100644 (file)
index 0000000..2556e47
--- /dev/null
@@ -0,0 +1,37 @@
+package edu.berkeley.fleet.api;
+
+/** possible predicate field values */
+public enum Predicate {
+    Default, FlagA, NotFlagA, FlagB, NotFlagB, FlagC, NotFlagC, IgnoreFlagD, FlagD;
+    public String toString() {
+        switch(this) {
+            case Default:    return "";
+            case FlagA:      return "a";
+            case FlagB:      return "b";
+            case FlagC:      return "c";
+            case NotFlagA:   return "!a";
+            case NotFlagB:   return "!b";
+            case NotFlagC:   return "!c";
+            case IgnoreFlagD:return "*";
+            case FlagD:      return "d";
+            default:         throw new Error("unknown predicate " + this);
+        }
+    }
+
+    /** evaluates this predicate for a given set of flags and olc */
+    public boolean evaluate(boolean flag_a, boolean flag_b, boolean flag_c, boolean flag_d) {
+        switch(this) {
+            case Default:    return !flag_d;
+            case FlagA:      return !flag_d && flag_a;
+            case FlagB:      return !flag_d && flag_b;
+            case FlagC:      return !flag_d && flag_c;
+            case NotFlagA:   return !flag_d && !flag_a;
+            case NotFlagB:   return !flag_d && !flag_b;
+            case NotFlagC:   return !flag_d && !flag_c;
+            case IgnoreFlagD:return true;
+            case FlagD:      return flag_d;
+            default:         throw new Error("unknown predicate " + this);
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/api/Ship.java b/src/edu/berkeley/fleet/api/Ship.java
new file mode 100644 (file)
index 0000000..0b7945d
--- /dev/null
@@ -0,0 +1,37 @@
+package edu.berkeley.fleet.api;
+import java.util.*;
+
+/** A ship in a Fleet; each ship consists of a collection of <tt>Dock</tt>s */
+public abstract class Ship implements Iterable<Dock> {
+
+    private final Fleet fleet;
+
+    public Ship(Fleet fleet) {
+        this.fleet = fleet;
+    }
+
+    /** return the Fleet that this Ship belongs to */
+    public Fleet  getFleet() { return fleet; }
+
+    /** returns the type of the ship ("Fetch", "Alu", etc) */
+    public abstract String getType();
+    
+    public abstract Iterator<Dock> iterator();
+
+    /** returns the dock on this ship having name "name" */
+    public abstract Dock getDock(String name);
+
+    /** the docks of a given type are numbered; this returns the ordinal number of this dock */
+    public abstract int getOrdinal();
+
+    /** get a constant associated with a ship; returns null if none found */
+    public BitVector getConstant(String constantName) {
+        throw new RuntimeException("unknown constant \""+constantName+"\" on ship " + this);
+    }
+
+    public String toString() {
+        String name = getType();
+        name = name.substring(0,1).toLowerCase()+name.substring(1);
+        return name + "" + getOrdinal() + "";
+    }
+}
diff --git a/src/edu/berkeley/fleet/api/package.html b/src/edu/berkeley/fleet/api/package.html
new file mode 100644 (file)
index 0000000..30815b1
--- /dev/null
@@ -0,0 +1,11 @@
+<body>
+<p>
+API for the FleetCode; see the class {@link edu.berkeley.fleet.api.Fleet} for a starting point and drill down from there.
+</p>
+
+<p>
+<b>Note:</b> all <tt>Instruction</tt> objects and their constituent parts
+(<tt>Path</tt>, <tt>Destination</tt>, etc) are immutable,
+like <tt>java.lang.String</tt>.
+</p>
+</body>
diff --git a/src/edu/berkeley/fleet/assembler/Main.java b/src/edu/berkeley/fleet/assembler/Main.java
new file mode 100644 (file)
index 0000000..24c45cd
--- /dev/null
@@ -0,0 +1,15 @@
+package edu.berkeley.fleet.assembler;
+
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** main entry point to the assembler */
+public class Main {
+
+    /** parse the assembly code on <tt>r</tt>, encode it for <tt>fleet</tt>, and write a binary on <tt>out</tt> */
+    public static Instruction[] assemble(Fleet fleet, Reader r) throws Exception {
+        return new Parser(fleet).parse(r);
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/assembler/Parser.java b/src/edu/berkeley/fleet/assembler/Parser.java
new file mode 100644 (file)
index 0000000..a589c7c
--- /dev/null
@@ -0,0 +1,576 @@
+package edu.berkeley.fleet.assembler;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import static edu.berkeley.fleet.api.Instruction.*;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.interpreter.*;
+import java.util.*;
+import java.io.*;
+
+
+/**
+ *  @author Adam Megacz <megacz@cs.berkeley.edu>
+ */
+public class Parser {
+
+    private static final BitVector SIGNAL_ZERO = new BitVector(1);
+    private static final BitVector SIGNAL_ONE  = new BitVector(1);
+    static {
+        SIGNAL_ONE.set(0,true);
+    }
+    
+    /** WARNING: this class may change in the future; it is not a stable interface */
+    public Parser(Fleet fleet) {
+        expect = new ArrayList<Long>();
+        this.fleet = fleet;
+    }
+
+    //////////////////////////////////////////////////////////////////////////////
+
+    private Fleet fleet;
+    private ArrayList<String> imports = new ArrayList<String>();
+
+    private HashMap<String,Ship> shipMap = new HashMap<String,Ship>();
+
+    // codebags in numerical order
+    private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+    private HashMap<String,CodeBag> codeBagsByName = new HashMap<String,CodeBag>();
+    
+    private CodeBag getCodeBag(String name) {
+        CodeBag cb = codeBagsByName.get(name);
+        if (cb!=null) return cb;
+        return new CodeBag(name);
+    }
+
+    private static Union grammar;
+    private static synchronized Union getGrammar() throws Exception {
+        if (grammar != null) return grammar;
+        InputStream grammarStream =
+            Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/assembler/fleet.g");
+        CharParser metaGrammarParser   = new CharParser(GrammarAST.getMetaGrammar());
+        Tree<String> parsedGrammar     = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
+        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new GrammarAST.ImportResolver() {
+                public InputStream getImportStream(String importname) { return null; }
+            });
+        return grammar;
+    }
+
+    // FIXME: this ought to be cached via serialization, I think
+    private static CharParser cp = null;
+    Tree<String> parseIt(Reader r) throws Exception {
+        if (cp==null)
+            cp = new CharParser(getGrammar());
+        CharInput ci = new CharInput(r);
+        Forest f = cp.parse(ci);
+        return f.expand1();
+    }
+
+    public Instruction[] parse(Reader r) throws Exception {
+        // this needs to be "code bag zero"
+        CodeBag baseCodeBag = new CodeBag();
+        CodeBag rootCodeBag = new CodeBag();
+        skip = false;
+        Tree<String> parsed = (Tree<String>)parseIt(r);
+        walk(parsed, rootCodeBag);
+
+        // map from arbitrary identifiers to actual addresses
+        int[] codeBagMap = new int[codeBags.size()];
+        int count = 0;
+        for(int i=0; i<codeBags.size(); i++) {
+            CodeBag c = codeBags.get(i);
+            codeBagMap[i] = count;
+            for(Instruction inst : c) {
+                count++;
+            }
+        }
+
+        // now write for real
+        count = 0;
+        ArrayList<Instruction> ret = new ArrayList<Instruction>();
+        for(int i=0; i<codeBags.size(); i++) {
+            CodeBag c = codeBags.get(i);
+            for(int j=0; j<c.size(); j++) {
+                Instruction inst = c.get(j);
+                if (c.isCBD.contains(j)) {
+                    Set old = (Set)inst;
+                    long lit = 0;
+                    lit = ((FleetTwoFleet)fleet).CBD_SIZE.setval(lit, codeBags.get((int)old.immediate).size());
+                    lit = ((FleetTwoFleet)fleet).CBD_OFFSET.setval(lit, codeBagMap[(int)old.immediate]);
+                    inst = new Set(old.dock, IgnoreFlagD, SetDest.DataLatch, lit);
+                }
+                ret.add(inst);
+                count++;
+            }
+        }
+        long startcbd = 0;
+        for(int i=0; i<codeBags.size(); i++) {
+            if (codeBags.get(i)==rootCodeBag) {
+                long lit = 0;
+                lit = ((FleetTwoFleet)fleet).CBD_SIZE.setval(lit, codeBags.get(i).size());
+                lit = ((FleetTwoFleet)fleet).CBD_OFFSET.setval(lit, codeBagMap[i]);
+                startcbd = lit;
+            }
+        }
+        if (codeBags.size()<=2)
+            return (Instruction[])ret.toArray(new Instruction[0]);
+        return fixup((Instruction[])ret.toArray(new Instruction[0]), startcbd);
+    }
+
+    private Instruction[] fixup(Instruction[] instructions, long startcbd) {
+        ArrayList<Instruction> ret = new ArrayList<Instruction>();
+        Fleet fpga = fleet;
+
+        Dock inAddrWrite = null;
+        Dock inDataWrite = null;
+        Dock inCBD       = null;
+        Dock out         = null;
+        Dock debugIn     = null;
+        Dock ihorn       = null;
+
+        for(Ship ship : fpga) {
+            if ("Memory".equals(ship.getType()) && ship.getOrdinal()==0) {
+                inAddrWrite = ship.getDock("inAddrWrite");
+                inDataWrite = ship.getDock("inDataWrite");
+                inCBD = ship.getDock("inCBD");
+                out = ship.getDock("out");
+                ihorn = out;
+                //ihorn = ship.getDock("outIhorn");
+            }
+            if ("Debug".equals(ship.getType()) && ship.getOrdinal()==0) {
+                debugIn = ship.getDock("in");
+            }
+        }
+
+        for(int i=0; i<instructions.length; i++) {
+            long lit = ((FleetTwoFleet)fpga).writeInstruction(instructions[i], out);
+            ret.add(discard(out));
+            ret.add(new Instruction.Shift(inDataWrite, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, lit))));
+            ret.add(new Instruction.Shift(inDataWrite, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, lit))));
+            ret.add(deliver(inDataWrite));
+            ret.add(new Instruction.Shift(inAddrWrite, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, i))));
+            ret.add(new Instruction.Shift(inAddrWrite, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, i))));
+            ret.add(deliver(inAddrWrite));
+        }
+        ret.add(new Instruction.Shift(inCBD, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, startcbd))));
+        ret.add(new Instruction.Shift(inCBD, IgnoreFlagD, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, startcbd))));
+        ret.add(wait(inCBD));
+        ret.add(deliver(inCBD));
+        ret.add(sendto(out, out.getPath(inCBD.getDataDestination(),null)));
+
+        int count = (int)((FleetTwoFleet)fleet).CBD_SIZE.getval(startcbd);
+        // FIXME FIXME FIXME!
+        int MAX_ILC = 31;
+        int num_instrs = 0;
+        while(count > 0) {
+            int num = Math.min(count, MAX_ILC);
+            num_instrs+=2;
+            count -= num;
+            ret.add(new Instruction.Set(ihorn, IgnoreFlagD, SetDest.InnerLoopCounter, num));
+            ret.add(new Instruction.Move(ihorn, IgnoreFlagD, false, null,false,true,true,true,true,false));
+        }
+        if (num_instrs > ihorn.getInstructionFifoSize()) throw new RuntimeException();
+
+        return (Instruction[])ret.toArray(new Instruction[0]);
+    }
+
+    /** in the first pass, codebags are assigned "addresses" in arbitrary order */
+    void walk(Tree<String> t, CodeBag cb) {
+
+        String head = t.head();
+        if (head==null) {
+        } else if (head.equals("Program")) {
+            for(Tree<String> tc : t.child(0))
+                walk(tc, cb);
+            if (t.size()>1)
+                for(Tree<String> statement : t.child(1))
+                    fillCodeBag(statement, cb);
+   
+        } else if (head.equals("#ship")) {
+            String name = name(t.child(0));
+            String type = string(t.child(1));
+            Ship ship = allocateShip(type);
+            shipMap.put(name, ship);
+
+        } else if (head.equals("#expect")) {
+            expect.add(number(t.child(0)));
+        } else if (head.equals("#skip")) {
+            skip = true;
+
+        }
+    }
+
+    private static String string(Tree<String> t) {
+        String ret = "";
+        if (t.head() != null) ret += t.head();
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
+    private static String stringBody(Tree<String> t) {
+        String ret = "";
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
+    private static String name(Tree<String> t) {
+        return string(t.child(0))+string(t.child(1));
+    }
+
+    Path path(Dock dock, Tree<String> t) {
+        if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
+        String shipName = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship ship = shipMap.get(shipName);
+        if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
+        Destination ret = null;
+        Dock bb = null;
+        for(Dock b : ship)
+            if (b.getName().equals(portName)) {
+                bb = b;
+            }
+        if (bb==null)
+            throw new RuntimeException("no such dock \""+portName+"\"");
+        if (t.size() >= 3) {
+            if (":i".equals(t.child(2).head())) return dock.getPath(bb.getInstructionDestination(),SIGNAL_ZERO);
+            if (":1".equals(t.child(2).head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ONE);
+            if (":0".equals(t.child(2).head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO);
+        }
+        return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO);
+    }
+
+    Dock dock(Tree<String> t) {
+        if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head()))
+            throw new RuntimeException(t+"");
+        String shipName = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship ship = shipMap.get(shipName);
+        if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
+        Dock bb = null;
+        for(Dock b : ship)
+            if (b.getName().equals(portName))
+                return b;
+        throw new RuntimeException("no such dock \""+portName+"\"");
+    }
+
+    private HashMap<String,Integer> numAllocated = new HashMap<String,Integer>();
+
+    Ship allocateShip(String shipType) {
+        int allocated = 0;
+        if (numAllocated.get(shipType) != null)
+            allocated = numAllocated.get(shipType);
+        numAllocated.put(shipType, allocated+1);
+        for(Iterator<Ship> it = fleet.iterator();
+            it.hasNext();
+            ) {
+            Ship s = it.next();
+            if (s.getType().equals(shipType)) {
+                if (allocated == 0) return s;
+                allocated--;
+            }
+        }
+        if (fleet instanceof FleetWithDynamicShips) {
+            FleetWithDynamicShips dyn = ((FleetWithDynamicShips)fleet);
+            Ship ship = dyn.createShip(shipType, shipType+allocated);
+            if (ship==null)
+                throw new RuntimeException("couldn't find a ship called \""+shipType+"\"");
+            return ship;
+        } else {
+            throw new RuntimeException("no more ships of type \""+shipType+"\"");
+        }
+    }
+
+    private BitVector parseSSL(Tree t) {
+        String shipType = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship chosenship = null;
+        for(Ship ship : fleet) {
+            if (ship.getType().equals(shipType)) {
+                chosenship = ship;
+                break;
+            }
+        }
+        if (chosenship==null) throw new RuntimeException("no ships of type " + shipType);
+        Dock chosenport = chosenship.getDock(portName);
+        Tree specs = t.child(2);
+        long literal = 0;
+        if (specs.size() != 1) throw new RuntimeException("multiple constants not supported");
+        Tree tt = specs.child(0);
+        return resolveLiteral(chosenport, stringBody(tt));
+    }
+
+    private static BitVector resolveLiteral(Dock dd, String s) {
+        long val = 0;
+        long ret = 0;
+        boolean hasval = false;
+        if (s.indexOf('=') != -1) {
+            val = Long.parseLong(s.substring(s.indexOf('=')+1));
+            s = s.substring(0, s.indexOf('='));
+            hasval = true;
+        }
+        return ((FleetTwoDock)dd).getDockConstant(s);
+    }
+
+    private static FlagFunction parseFlags(Tree<String> t) {
+        FlagFunction ret = FlagFunction.ZERO;
+        for(int i=0; i<t.size(); i++) {
+            String s = t.child(i).head();
+            if (s.equals("0"))  ret = ret.add(FlagFunction.ZERO);
+            if (s.equals("1"))  ret = ret.add(FlagFunction.ONE);
+            if (s.equals("a"))  ret = ret.add(FlagA);
+            if (s.equals("!a")) ret = ret.add(NotFlagA);
+            if (s.equals("b"))  ret = ret.add(FlagB);
+            if (s.equals("!b")) ret = ret.add(NotFlagB);
+            if (s.equals("c"))  ret = ret.add(FlagC);
+            if (s.equals("!c")) ret = ret.add(NotFlagC);
+        }
+        return ret;
+    }
+
+    private int anoncount = 1;
+    void fillCodeBag(Tree<String> t, CodeBag cb) {
+        if (t.head()==null) return;
+        else if (t.head().equals("CodeBagDef")) {
+            CodeBag cb2 = getCodeBag(name(t.child(0)));
+            for(Tree<String> statement : t.child(1))
+                fillCodeBag(statement, cb2);
+
+        } else if (t.head().equals("Fiber")) {
+            Dock dock = (Dock)dock(t.child(0));
+            
+            OUTER: for(Tree tt : t.child(1)) {
+
+                if ("tail".equals(tt.head()))    {
+                    cb.add(new Tail(dock));
+                    continue;
+                } else if ("head".equals(tt.head()))    {
+                    cb.add(new Head(dock));
+                    continue;
+                }
+
+                int count = 1;
+                Predicate predicate = Default;
+                boolean interruptible = false;
+                for(int i=0; i<tt.child(0).size(); i++) {
+                    Tree ttt = tt.child(0).child(i);
+                    if ("[a]".equals(ttt.head()))  predicate = FlagA;
+                    if ("[b]".equals(ttt.head()))  predicate = FlagB;
+                    if ("[c]".equals(ttt.head()))  predicate = FlagC;
+                    if ("[!a]".equals(ttt.head())) predicate = NotFlagA;
+                    if ("[!b]".equals(ttt.head())) predicate = NotFlagB;
+                    if ("[!c]".equals(ttt.head())) predicate = NotFlagC;
+                    if ("[*]".equals(ttt.head()))  predicate = IgnoreFlagD;
+                    if ("[d]".equals(ttt.head()))  predicate = FlagD;
+                }
+                tt = tt.child(1);
+                if ("flags".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, parseFlags(tt.child(0)), parseFlags(tt.child(1))));
+                    continue;
+                } else if ("olc=word".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch));
+                    continue;
+                } else if ("ilc=word".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch));
+                    continue;
+                } else if ("*".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.Infinity));
+                    continue;
+                } else if ("olc=int".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, SetDest.OuterLoopCounter, (number(tt.child(0)))));
+                    continue;
+                } else if ("ilc=int".equals(tt.head()))    {
+                    cb.add(new Set(dock, predicate, SetDest.InnerLoopCounter, (number(tt.child(0)))));
+                    continue;
+                } else if ("--".equals(tt.head())) {
+                    cb.add(new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.Decrement));
+                    continue;
+                } else if ("nop".equals(tt.head())) {
+                    if (tt.size() > 0 && "[T]".equals(tt.child(0).head())) interruptible = true;
+                    cb.add(new Move(dock, predicate, interruptible, null, false, false, false, false, false, false));
+                } else if ("shift".equals(tt.head())) {
+                    cb.add(new Shift(dock, predicate,
+                                     new BitVector(dock.getShip().getFleet().getShiftWidth()).set(number(tt.child(0)))));
+                    continue;
+                } else if ("flush".equals(tt.head())) {
+                    cb.add(new Flush(dock, predicate));
+                    continue;
+                } else if ("abort".equals(tt.head())) {
+                    cb.add(new Abort(dock, predicate));
+                    continue;
+                } else if ("word".equals(tt.head())) {
+                    BitVector literal = null;
+                    if (tt.child(0).head().equals("CodeBagBody")) {
+                        Tree<String> tq = tt;
+                        CodeBag cb2 = getCodeBag("anon"+(anoncount++));
+                        for(Tree<String> statement : tq.child(0))
+                            fillCodeBag(statement, cb2);
+                        cb.add(new Set(dock, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true);
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("Name")) {
+                        String refname = name(tt.child(0));
+                        CodeBag cb2 = getCodeBag(refname);
+                        cb.add(new Set(dock, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true);
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("[")) {
+                        literal = parseSSL(tt.child(0));
+                    } else {
+                        literal = new BitVector(dock.getShip().getFleet().getWordWidth()).set(number(tt.child(0)));
+                    }
+                    count = 1;
+
+                    if (((FleetTwoFleet)fleet).isSmallEnoughToFit(literal)) {
+                        cb.add(new Set(dock, predicate, SetDest.DataLatch, literal.toLong()));
+                    } else {
+                        int counter = 0;
+                        while(counter < dock.getShip().getFleet().getWordWidth()) counter += fleet.getShiftWidth();
+                        while(true) {
+                            counter -= fleet.getShiftWidth();
+                            if (counter < 0) break;
+                            BitVector bv = new BitVector(dock.getShip().getFleet().getShiftWidth());
+                            for(int i=0; i<fleet.getShiftWidth(); i++)
+                                if ((counter+i) < literal.length())
+                                    bv.set(i, literal.get(counter+i));
+                            cb.add(new Shift(dock, predicate, bv));
+                        }
+                    }
+                        
+                    continue;
+                }
+                Tree ttx = null;
+                boolean requeue = false;
+                if ("[T]".equals(tt.child(0).head()))  interruptible = true;
+                ttx = tt.child(tt.size()-1);
+                boolean tokenIn = false;
+                boolean dataIn = false;
+                boolean latch = false;
+                boolean dataOut = false;
+                boolean tokenOut = false;
+                boolean dispatch = false;
+                boolean localLiteral = false;
+                boolean ignoreUntilLast = false;
+                long literal = 0;
+                Path path = null;
+                for(int i=0; i<ttx.size(); i++) {
+                    Tree ttt = ttx.child(i);
+                    if      ("recv token".equals(ttt.head()))    { tokenIn = true; }
+                    else if ("discard".equals(ttt.head())) { dataIn = true; latch = false; }
+                    else if ("take".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("collect".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = true;
+                    }
+                    else if ("collect path".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = false;
+                        dispatch = true;
+                    }
+                    else if ("collect packet".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = true;
+                        dispatch = true;
+                    }
+                    else if ("collect nothing".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                    }
+                    else if ("recv".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = true;
+                    }
+                    else if ("recv path".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = false;
+                        dispatch = true;
+                    }
+                    else if ("recv packet".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = true;
+                        dispatch = true;
+                    }
+                    else if ("recv nothing".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                    }
+                    else if ("send".equals(ttt.head()))  {
+                        dataOut = true;
+                    }
+                    else if ("send to".equals(ttt.head()))  { dataOut = true; path = path(dock, ttt.child(0)); }
+                    else if ("deliver".equals(ttt.head())) { dataOut = true;  }
+                    else if ("send token".equals(ttt.head()))     { tokenOut = true; }
+                    else if ("send token to".equals(ttt.head()))     { tokenOut = true; path = path(dock, ttt.child(0)); }
+                }
+                cb.add(new Move(dock, predicate,
+                                interruptible, path, tokenIn, dataIn,
+                                latch, dispatch, dataOut, tokenOut));
+            }
+        }
+    }
+
+    private class CodeBag extends ArrayList<Instruction> {
+        public long address = -1;
+        public final String name;
+        private HashSet<Integer> isCBD = new HashSet<Integer>();
+        public CodeBag() { codeBags.add(this); this.name = "root"; }
+        public CodeBag(String name) { codeBags.add(this); codeBagsByName.put(name, this); this.name = name; }
+        public long getFakeAddress() { return codeBags.indexOf(this); }
+        public boolean equals(Object o) { return this==o; }
+        public void add(Instruction i, boolean isCBD) {
+            if (isCBD) this.isCBD.add(size());
+            add(i);
+        }
+    }
+
+    // hideous hack
+    public static ArrayList<Long> expect;
+    public static boolean         skip;
+
+    private static long number(Tree t) {
+        String ret = "";
+        for(Object c : t.child(2)) ret += ((Tree)c).head();
+        boolean negative = "-".equals(t.child(0).head());
+        ret = ret.trim();
+        long val = 0;
+        if      ("0x".equals(t.child(1).head())) val = Long.parseLong(ret, 16);
+        else if ("0b".equals(t.child(1).head())) val = Long.parseLong(ret, 2);
+        else                                     val = Long.parseLong(ret);
+        if (negative) val = -1L * val;
+        return val;
+    }
+    /**
+     *  This interface marks Fleets which can create ships on the fly, like the fleeterpreter;
+     *  if available, the parser will use this interface to create ships out of #ship definitions.
+     */
+    public static interface FleetWithDynamicShips {
+        public Ship createShip(String shiptype, String shipname);
+    }
+
+    private static Move discard(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
+    private static Move deliver(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
+    private static Move wait(Dock dock)              { return new Move(dock, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
+    private static Move sendto(Dock dock, Path path) { return new Move(dock, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
+}
diff --git a/src/edu/berkeley/fleet/assembler/fleet.g b/src/edu/berkeley/fleet/assembler/fleet.g
new file mode 100644 (file)
index 0000000..219fb21
--- /dev/null
@@ -0,0 +1,83 @@
+// The FLEET Assembly Language Grammar [22-Aug-2008]
+
+// Note that this is the *entire, complete* formal specification of
+// the grammar.  An equivalent lex+yacc grammar and support code would
+// be several times as long.
+
+s               = ws Program ws
+Program::       = Directives CodeBagBody /ws
+Directives::    = Directive */ ws
+CodeBagBody::   = (Fiber | CodeBagDef) */ ws
+CodeBagDef::    = CodeBagName ":" "{" CodeBagBody "}" /ws
+Fiber::         = Dock        ":" Instructions        /ws
+
+Instructions::  = Instruction +/ ws
+Instruction     = Instruction:: (Tags:: Tag*) InstructionX
+                | ^"head" ";" /ws
+                | ^"tail" ";" /ws
+Tag             = ^"[a]"  ws |  ^"[b]" ws
+                | ^"[!a]" ws | ^"[!b]" ws
+                | ^"[d]" ws
+                | ^"[*]" ws
+InstructionX    = (() | ^"[T]" ws) ^"nop"                                            ";" /ws
+                | (() | ^"[T]" ws)  (Commands:: Command +/ (ws "," ws))             ^";" /ws
+                | "olc=word"::      "set"  "olc" "=" "word"                          ";" /ws
+                | "ilc=word"::      "set"  "ilc" "=" "word"                          ";" /ws
+                | "olc=int"::       "set"  "olc" "=" int                             ";" /ws
+                | "ilc=int"::       "set"  "ilc" "=" int                             ";" /ws
+                |                   "set"  "ilc" "=" ^"*"                            ";" /ws
+                |                   "set"  "olc" ^"--"                               ";" /ws
+                |                   "set" ^"flags" "a" "=" Flags "," "b" "=" Flags   ";" /ws
+                |                   "set" ^"word"      "=" Literal                   ";" /ws
+                |              ^"shift" Literal                                      ";" /ws
+                |              ^"flush"                                              ";" /ws
+                |              ^"abort"                                              ";" /ws
+
+Flags:: = (^"0") |  (^"1") | (^"a" |  ^"b" |  ^"c" | ^"!a" | ^"!b" | ^"!c") +/ (ws "|" ws)
+
+Command         = "recv token"::       "recv" ws "token"
+                |                     ^"recv"
+                | "recv"::             "recv" ws "word"
+                | "recv nothing"::     "recv" ws "nothing"
+                | "recv path"::        "recv" ws "path"
+                | "recv packet"::      "recv" ws "packet"
+                |                     ^"collect"
+                | "collect"::          "collect" ws "word"
+                | "collect nothing"::  "collect" ws "nothing"
+                | "collect path"::     "collect" ws "path"
+                | "collect packet"::   "collect" ws "packet"
+                |                     ^"deliver"
+                |                     ^"send"
+                | "send to"::          "send" "to"          Destination /ws
+                | "send token"::       "send" "token"       Destination /ws
+                | "send token to"::    "send" "token" "to"  Destination /ws
+
+Literal         = int
+                | ShipType "." DockName ^"[" Constants "]"
+                | CodeBagName
+                | "{" CodeBagBody "}" /ws
+
+Dock::          = ShipName "." DockName
+Destination::   = ShipName "." DockName ( ^"" | ^":i" | ^":0" | ^":1" )
+Constants::     = Constant +/ ","
+Constant::      = [a-zA-Z0-9=_\-]++
+
+CodeBagName     = UpcaseWord
+ShipType        = UpcaseWord
+ShipName        = DowncaseWord
+DockName        = DowncaseWord
+Word            = UpcaseWord | DowncaseWord
+UpcaseWord      = Name:: [A-Z]    ("":: [A-Za-z0-9_]**)
+DowncaseWord    = Name:: [a-z]    ("":: [A-Za-z0-9_]**)
+int::           = (^"-"|^"") (^"0x"|^"0b"|^"") (digits:: [0-9A-Fa-f]++)
+
+ws!             = wsx -> ~[\r\n ]
+wsx!            = ()
+                | wsx [\r\n ]
+                | wsx Comment
+Comment!        = "//" ~[\n\r]* [\r\n]
+                | "/*" ~[\n\r]* "*/"
+
+Directive      = ^"#ship" ShipName ":" ("":: [0-9A-Za-z_.]++) /ws
+               | ^"#expect" int /ws
+               | ^"#skip"
diff --git a/src/edu/berkeley/fleet/dataflow/AluNode.java b/src/edu/berkeley/fleet/dataflow/AluNode.java
new file mode 100644 (file)
index 0000000..47aeae0
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class AluNode extends Node {
+    private final Ship    ship = dfg.pool.allocateShip("Alu");
+
+    public final InPort  in1 = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  in2 = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"));
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+
+    public AluNode(DataFlowGraph dfg) { super(dfg); }
+    public AluNode(DataFlowGraph dfg, String opcode) {
+        super(dfg);
+        inOp.connect(new ForeverNode(dfg, ((Node.DockInPort)inOp).getConstant(opcode)).out);
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/DataFlowGraph.java b/src/edu/berkeley/fleet/dataflow/DataFlowGraph.java
new file mode 100644 (file)
index 0000000..7916538
--- /dev/null
@@ -0,0 +1,40 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+import java.net.*;
+
+/**
+ *  A dataflow graph.
+ */
+public class DataFlowGraph implements Iterable<Node> {
+
+    public final Fleet    fleet;
+    public final ShipPool pool;
+
+    /**
+     *  Use LinkedHashSet to get a predictable/repeatable iteration
+     *  order, which leads to predictable/repeatable code
+     */
+    private LinkedHashSet<Node> nodes = new LinkedHashSet<Node>();
+
+    public DataFlowGraph(Fleet fleet, ShipPool pool) {
+        this.fleet = fleet;
+        this.pool  = pool;
+    }
+
+    public Iterator<Node> iterator() { return nodes.iterator(); }
+    public void addNode(Node node) { this.nodes.add(node); }
+
+    public CodeBag build(CodeBag cb) {
+        boolean oldAutoflush = cb.getAutoflush();
+        cb.setAutoflush(true);
+        for(Node mod : nodes) mod.build(cb);
+        // this breaks stuff, but it shouldn't!
+        //cb.setAutoflush(oldAutoflush);
+        return cb;
+    }
+}
+
+
diff --git a/src/edu/berkeley/fleet/dataflow/DebugNode.java b/src/edu/berkeley/fleet/dataflow/DebugNode.java
new file mode 100644 (file)
index 0000000..af734ea
--- /dev/null
@@ -0,0 +1,11 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/** Items supplied to the "in" port will appear at the debug output of the Fleet */
+public class DebugNode extends Node {
+    private final Ship ship = dfg.pool.allocateShip("Debug");
+    public final InPort in = new DockInPort("in", ship.getDock("in"));
+    public DebugNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/DiscardNode.java b/src/edu/berkeley/fleet/dataflow/DiscardNode.java
new file mode 100644 (file)
index 0000000..f931e27
--- /dev/null
@@ -0,0 +1,37 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+public class DiscardNode extends Node {
+
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    private final InPort  op    = new DockInPort("op",    ship.getDock("inOp"), "PASS_C2_V1");
+    public  final InPort  in    = new DockInPort("val",   ship.getDock("in1"));
+    public  final InPort  count = new DockInPort("count", ship.getDock("in2"));
+
+    public  final OutPort out   = new DockOutPort("out", ship.getDock("out")) {
+            protected void build(CodeBag ctx, LoopFactory lf) {
+
+                lf = lf.makeNext(0);
+
+                lf.abortLoopIfTorpedoPresent();
+                lf.collectWord();
+                lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+
+                lf.setPredicate(Predicate.FlagA);
+                lf.abortLoopIfTorpedoPresent();
+                peer.recvToken(lf);
+                peer.sendWord(lf);
+                lf.setPredicate(null);
+
+            }
+        };
+
+    public DiscardNode(DataFlowGraph dfg) {
+        super(dfg);
+    }
+
+}
+
diff --git a/src/edu/berkeley/fleet/dataflow/DoneNode.java b/src/edu/berkeley/fleet/dataflow/DoneNode.java
new file mode 100644 (file)
index 0000000..7c966cf
--- /dev/null
@@ -0,0 +1,213 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+/**
+ *  This class contains all of the shutdown and cleanup logic.
+ */
+public class DoneNode extends Node {
+
+    private final Ship    counter = dfg.pool.allocateShip("Counter");
+    private final Program program;
+    private       CodeBag shutdownCodeBag = null;
+
+    public  final InPort  in       = new InPort("in") {
+            private Dock dock = counter.getDock("out");
+            public void recvToken(LoopFactory lf) { }
+            public void sendWord(LoopFactory lf) { lf.sendToken(dock); }
+            public int getInflight() { return 1; }
+            public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+            protected void build(CodeBag ctx, LoopFactory lf) {
+                lf.recvToken();
+                lf.literal(getShutdownCodeBag());
+                lf.sendWord(program.getCBDDestination());
+            }
+        };
+
+    public DoneNode(DataFlowGraph dfg, Program program) {
+        super(dfg);
+        this.program = program;
+    }
+
+    public Destination getDestinationToSendNextCodeBagDescriptorTo() {
+        return counter.getDock("in1").getDataDestination();
+    }
+
+    private static final int PHASES = 4;
+
+    private CodeBag getShutdownCodeBag() {
+        if (shutdownCodeBag!=null) return shutdownCodeBag;
+
+        CodeBag[] cb = new CodeBag[PHASES];
+        for(int phase=0; phase<PHASES; phase++)
+            cb[phase] = new CodeBag(dfg.fleet, program);
+
+        for(int phase=0; phase<PHASES; phase++) {
+            // ctx_counter sets up the counter ship which will tally
+            // the acknowledgement tokens coming back from the
+            // torpedoed docks.
+            CodeBag ctx_counter = cb[phase];
+
+            // ctx_reset is the context holding the reset code (not including torpedoes) for this phase
+            CodeBag ctx_reset = new CodeBag(dfg.fleet, program);
+
+            int expected_tokens = 0;
+            for(Node node : dfg)
+                expected_tokens += node.reset(ctx_reset, phase, counter.getDock("in2").getDataDestination());
+            if (expected_tokens==0) throw new RuntimeException("should not happen");
+
+            // The loops below use a count of zero and an
+            // unconditional abort instead of a count of 1.  This is
+            // to ensure that the loop will not start executing until
+            // all instructions are safely in the instruction ring.
+            // That in turn ensures that the "ready" tokens are not
+            // sent until the counter is truly prepared to consume a
+            // deluge of tokens.
+
+            LoopFactory lf;
+            lf = ctx_counter.loopFactory(counter.getDock("inOp"), 0);
+            lf.sendToken(counter.getDock("out")); // ready->
+            lf.literal("DROP_C1_V2");
+            lf.deliver();
+            lf.literal("PASS_C1_V1");
+            lf.deliver();
+            lf.abort();
+
+            lf = ctx_counter.loopFactory(counter.getDock("in1"), 0);
+            lf.sendToken(counter.getDock("out")); // ready->
+            lf.literal(expected_tokens);
+            lf.deliver();
+            lf.literal(1);
+            lf.deliver();
+            if (phase<PHASES-1) lf.literal(cb[phase+1]);
+            else lf.recvWord();
+            lf.deliver();
+            lf.abort();
+
+            lf = ctx_counter.loopFactory(counter.getDock("in2"), 1);
+            lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO);
+            lf = lf.makeNext(0);
+            lf.setPredicate(Predicate.FlagD);
+            lf.sendToken(counter.getDock("out"));
+            lf.setPredicate(null);
+            lf.setPredicate(Predicate.NotFlagA);
+            lf.sendToken(counter.getDock("out")); // ready->
+            lf.setPredicate(null);
+            lf.setFlags(FlagFunction.ONE, FlagFunction.ZERO);
+            lf.abortLoopIfTorpedoPresent();
+            lf.recvWord();
+            lf.deliver();
+
+            lf = ctx_counter.loopFactory(counter.getDock("out"), 1);
+            lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO);
+            lf.literal(ctx_reset);
+            lf = lf.makeNext(0);
+            lf.setPredicate(Predicate.NotFlagA);
+            lf.recvToken();
+            lf.recvToken();
+            lf.recvToken();
+            lf.sendWord(program.getCBDDestination());
+            lf.setFlags(FlagFunction.ONE, FlagFunction.ZERO);
+            lf.setPredicate(null);
+            lf.collectWord();
+            lf.sendTorpedo(counter.getDock("in2"));
+            lf.recvToken();
+            lf.sendWord(program.getCBDDestination());
+            lf.abort();
+
+            cb[phase].seal();
+            ctx_reset.seal();
+        }
+        return (shutdownCodeBag = cb[0]);
+    }
+
+    // Reset //////////////////////////////////////////////////////////////////////////////
+
+    static int doReset(CodeBag ctx,
+                       int phase,
+                       Dock dock,
+                       Port self,
+                       Port peer,
+                       Destination ackDestination,
+                       boolean peerUsed) {
+        int ret = 0;
+
+        switch(phase) {
+
+            // Phase 0: torpedo every output dock, put it in
+            // collecting mode.  Cannot combine with phase 1,
+            // because until output docks are in vacuum mode we
+            // cannot be sure that the tokens to the input docks
+            // will eventually succeed.  This may cause the
+            // instructions sent after the tokens to back up into
+            // the switch fabric.
+            case 0: {
+                if (!dock.isInputDock()) {
+                    ctx.sendTorpedo(dock);
+                    LoopFactory lf = ctx.loopFactory(dock, 1);
+                    lf.sendToken(ackDestination);
+                    lf = lf.makeNext(0);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.collectWord();
+                    ret++;
+                }
+                break;
+            }
+
+                // [wait for all output docks to confirm that they've been torpedoed]
+                // Phase 1: torpedo every input dock (causing them to flush), put it in loopback mode
+            case 1: {
+                if (dock.isInputDock()) {
+                    ctx.sendTorpedo(dock);
+                    LoopFactory lf = ctx.loopFactory(dock, 1);
+                    lf.sendToken(ackDestination);
+
+                    // FIXME: this won't work right for ports that
+                    // get "shared" by two senders (for example,
+                    // inAddrRead1/2)
+
+                    if (peerUsed && peer!=null) {
+                        lf = lf.makeNext(0);
+                        lf.abortLoopIfTorpedoPresent();
+                        ((OutPort)peer).recvWord(lf);
+                        ((OutPort)peer).sendToken(lf);
+                    }
+                    ret++;
+                }
+                break;
+            }
+
+                // [wait for all input docks to confirm that they've been torpedoed and have flushed]
+                // Phase 2: torpedo every output dock, have it absorb tokens
+            case 2: {
+                if (!dock.isInputDock()) {
+                    ctx.sendTorpedo(dock);
+                    LoopFactory lf = ctx.loopFactory(dock, 1);
+                    for(int i=0; i<((OutPort)self).getTokensToAbsorb(); i++)
+                        lf.recvToken();
+                    lf.sendToken(ackDestination);
+                    ret++;
+                }
+                break;
+            }
+
+                // [wait for all output docks to confirm that they've absorbed enough tokens]
+                // Phase 3: torpedo every input dock, await confirmation, and we're done
+            case 3: {
+                if (dock.isInputDock()) {
+                    if (peerUsed && peer!=null) {
+                        ctx.sendTorpedo(dock);
+                    }
+                    LoopFactory lf = ctx.loopFactory(dock, 1);
+                    lf.sendToken(ackDestination);
+                    ret++;
+                }
+                break;
+            }
+        }
+        return ret;
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/DownCounterNode.java b/src/edu/berkeley/fleet/dataflow/DownCounterNode.java
new file mode 100644 (file)
index 0000000..61efbc9
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ *  Takes a starting value at "start" and a (positive) decrement
+ *  amount at "incr" and counts down; the first value emitted will be
+ *  (start-incr).
+ */
+public class DownCounterNode extends Node {
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    private final InPort  inOp  = new DockInPort("inOp", ship.getDock("inOp"), "COUNT");
+    public  final InPort  start = new DockInPort("start", ship.getDock("in1"));
+    public  final InPort  incr  = new DockInPort("incr",  ship.getDock("in2"));
+    public  final OutPort out   = new DockOutPort("out",  ship.getDock("out"));
+
+    public DownCounterNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/DropNode.java b/src/edu/berkeley/fleet/dataflow/DropNode.java
new file mode 100644 (file)
index 0000000..a1da02a
--- /dev/null
@@ -0,0 +1,24 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ *  Discards all items provided; does not require any ships.
+ */
+public class DropNode extends Node {
+
+    public  final InPort  in    = new InPort("in") {
+            // FIXME: I'm still not sure if this screws up the protocol somewhere
+            public void recvToken(LoopFactory loopfactory_at_output_dock) { }
+            public void sendWord(LoopFactory loopfactory_at_output_dock) { }
+            public int  reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            public void build(CodeBag ctx) { }
+        };
+
+    public DropNode(DataFlowGraph dfg) {
+        super(dfg);
+    }
+
+}
+
diff --git a/src/edu/berkeley/fleet/dataflow/FifoNode.java b/src/edu/berkeley/fleet/dataflow/FifoNode.java
new file mode 100644 (file)
index 0000000..7c984f8
--- /dev/null
@@ -0,0 +1,14 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/** A simple FIFO */
+public class FifoNode extends Node {
+    private final Ship    ship = dfg.pool.allocateShip("Fifo");
+
+    public final InPort  in = new DockInPort("in",  ship.getDock("in"));
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+
+    public FifoNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/ForeverNode.java b/src/edu/berkeley/fleet/dataflow/ForeverNode.java
new file mode 100644 (file)
index 0000000..556ff5f
--- /dev/null
@@ -0,0 +1,30 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ *  Deliver the constant at out forever.  Flow control in<->out is
+ *  maintained, but out is not flow-controlled, so be sure
+ *  that every datum sent there is consumed synchronously wiht
+ *  data items sent to out.
+ */
+public class ForeverNode extends Node {
+    private BitVector bv;
+    public final OutPort out = new OutPort("out") {
+            public void sendToken(LoopFactory lf) { }
+            public void recvWord(LoopFactory lf) { }
+            public void build(CodeBag ctx) { }
+            public int  reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            public void setPeer(InPort peer) {
+                this.peer = peer;
+                DockInPort pip = ((DockInPort)peer);
+                for(int i=0; i<pip.pattern.length; i++) {
+                    if (pip.pattern[i]==null)
+                        pip.pattern[i] = bv;
+                }
+            }
+        };
+    public ForeverNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
+    public ForeverNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/Lut3Node.java b/src/edu/berkeley/fleet/dataflow/Lut3Node.java
new file mode 100644 (file)
index 0000000..c2eb366
--- /dev/null
@@ -0,0 +1,16 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class Lut3Node extends Node {
+    private final Ship    ship = dfg.pool.allocateShip("Lut3");
+
+    public final InPort  in1   = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  in2   = new DockInPort("in2",  ship.getDock("in2"));
+    public final InPort  in3   = new DockInPort("in3",  ship.getDock("in3"));
+    public final InPort  inLut = new DockInPort("inLut", ship.getDock("inLut"));
+    public final OutPort out   = new DockOutPort("out", ship.getDock("out"));
+
+    public Lut3Node(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/MemoryNode.java b/src/edu/berkeley/fleet/dataflow/MemoryNode.java
new file mode 100644 (file)
index 0000000..a892672
--- /dev/null
@@ -0,0 +1,182 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+
+public class MemoryNode extends Node {
+    private final Ship    ship;
+    public final InPort  inCBD;
+    public final InPort  inAddrRead1;
+    public final InPort  inAddrRead2;
+    public final InPort  inAddrWrite;
+    public final InPort  inDataWrite;
+    public final OutPort outRead1;
+    public final OutPort outRead2;
+    public final OutPort outWrite;
+    public MemoryNode(DataFlowGraph dfg, Ship memoryShip) {
+        super(dfg);
+        this.ship = memoryShip;
+
+        // ugly hack
+        if (ship.getType().equals("Dvi")) {
+            new DockInPort("inPixelX", ship.getDock("inPixelX"), 0, new BitVector[] { null });
+            new DockInPort("inPixelY", ship.getDock("inPixelY"), 0, new BitVector[] { null });
+            new DockInPort("inPixelValue", ship.getDock("inPixelValue"), 0, new BitVector[] { null });
+        }
+
+        this.inCBD        = ship.getType().equals("Memory") ? new DockInPort("inCBD", ship.getDock("inCBD")) : null;
+        this.inDataWrite  = new DockInPort("inDataWrite", ship.getDock("inDataWrite"));
+        this.inAddrWrite  = new InPort("inAddrWrite") {
+                public void recvToken(LoopFactory lf) { lf.recvToken(); }
+                public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrWrite").getDataDestination()); }
+                public void build(CodeBag ctx) {
+                    LoopFactory lf = ctx.loopFactory(ship.getDock("inAddrWrite"), 0);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.recvWord();
+                    lf.deliver();
+                }
+                public int getTokensToAbsorb() { return outWrite.peer.getTokensToAbsorb(); }
+                public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+                    return DoneNode.doReset(ctx, phase, ship.getDock("inAddrWrite"), this, null, ackDestination, false);
+                }
+            };
+        this.inAddrRead1  = new InPort("inAddrRead1") {
+                public void recvToken(LoopFactory lf) { lf.recvToken(); }
+                public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(0)); }
+                public void build(CodeBag ctx) { }
+                public int getTokensToAbsorb() { return outRead1.peer.getTokensToAbsorb(); }
+                public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+                    return DoneNode.doReset(ctx, phase, ship.getDock("inAddrRead"), this, null, ackDestination, false);
+                }
+            };
+        this.inAddrRead2  = new InPort("inAddrRead2") {
+                public void recvToken(LoopFactory lf) { lf.recvToken(); }
+                public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(1)); }
+                public void build(CodeBag ctx) { }
+                public int getTokensToAbsorb() { return outRead2.peer.getTokensToAbsorb(); }
+                public int reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            };
+        this.outRead1 = new OutPort("outRead1") {
+                public void sendToken(LoopFactory lf) { inAddrRead1.peer.sendToken(lf); }
+                public void recvWord(LoopFactory lf) { lf.recvWord(); }
+                public int getNumInitialTokens() { return Math.max(1,Node.CAPACITY/2); }
+                public void build(CodeBag ctx) { }
+                public int  reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            };
+        this.outRead2 = new OutPort("outRead2") {
+                public void sendToken(LoopFactory lf) { inAddrRead2.peer.sendToken(lf); }
+                public void recvWord(LoopFactory lf) { lf.recvWord(); }
+                public int getNumInitialTokens() { return Math.max(1,Node.CAPACITY/2); }
+                public void build(CodeBag ctx) { }
+                public int  reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            };
+        this.outWrite = new DockOutPort("out", ship.getDock("out")) {
+                public void sendToken(LoopFactory lf) { inAddrWrite.peer.sendToken(lf); }
+                public void recvWord(LoopFactory lf) { lf.recvWord(); }
+                public int getTokensToAbsorb() { return 0; }
+                protected void build(CodeBag ctx, LoopFactory lf) {
+                    lf = lf.makeNext(0);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.collectWord();
+                        
+                    lf.setFlags(FlagFunction.ONE, FlagFunction.ZERO.add(FlagC));
+                    if (this.peer != null) {
+                        lf.setPredicate(Predicate.FlagB);
+                        lf.literal(77);
+                        lf.abortLoopIfTorpedoPresent();
+                        this.peer.sendWord(lf);
+                    }
+                        
+                    lf.setPredicate(Predicate.NotFlagB);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.recvToken();
+                    lf.setFlags(FlagFunction.ZERO.add(NotFlagC).add(FlagB), FlagFunction.ZERO.add(FlagC).add(FlagB));
+                    if (outRead1.peer != null) {
+                        lf.setPredicate(Predicate.NotFlagB);
+                        outRead1.peer.sendWord(lf);
+                    }
+                    if (outRead2.peer != null) {
+                        lf.setPredicate(Predicate.NotFlagA);
+                        outRead2.peer.sendWord(lf);
+                    }
+                    lf.setPredicate(null);
+                }
+            };
+    }
+    public void build(CodeBag ctx) {
+        super.build(ctx);
+        LoopFactory lf;
+
+        lf = ctx.loopFactory(ship.getDock("inAddrRead"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvWord();
+        lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+        lf.setPredicate(Predicate.NotFlagA);
+        lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(0));
+        lf.setPredicate(Predicate.FlagA);
+        lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(1));
+        lf.setPredicate(null);
+        lf.deliver();
+    }
+
+
+
+    public static void clearMem(FleetProcess fp,
+                                Ship memory,
+                                ShipPool pool,
+                                long offset,
+                                long count) throws RuntimeException {
+
+        DataFlowGraph dfg = new DataFlowGraph(fp.getFleet(), pool);
+
+        MemoryNode mem = new MemoryNode(dfg, memory);
+        UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+        discard.count.connect(new OnceNode(dfg, (int)(count)).out);
+        DebugNode debug = new DebugNode(dfg);
+        DownCounterNode c1 = new DownCounterNode(dfg);
+        c1.start.connect(new OnceNode(dfg, count).out);
+        c1.incr.connect(new OnceNode(dfg, 1).out);
+        mem.inAddrWrite.connect(c1.out);
+        mem.inDataWrite.connect(new ForeverNode(dfg, 0).out);
+        mem.outWrite.connect(discard.val);
+        discard.out.connect(debug.in);
+
+        CodeBag ctx = new CodeBag(fp.getFleet());
+        dfg.build(ctx);
+        ctx.dispatch(fp, true);
+        System.out.println("waiting...");
+        fp.recvWord();
+        System.out.println("... done");
+
+        // FIXME: cleanup?
+    }
+
+    public static void main(String[] s) throws Exception {
+        Fleet fleet = new Fpga();
+        FleetProcess fp;
+        ShipPool pool = new ShipPool(fleet);
+        Ship mem1 = pool.allocateShip("Memory");
+        Ship mem2 = pool.allocateShip("Memory");
+        Ship mem3 = pool.allocateShip("Memory");
+
+        fp = fleet.run(new Instruction[0]);
+        clearMem(fp, mem1, new ShipPool(fleet), 0, 16 * 1024);
+        fp.terminate();
+
+        fp = fleet.run(new Instruction[0]);
+        clearMem(fp, mem2, new ShipPool(fleet), 0, 16 * 1024);
+        fp.terminate();
+
+        fp = fleet.run(new Instruction[0]);
+        clearMem(fp, mem3, new ShipPool(fleet), 0, 16 * 1024);
+        fp.terminate();
+    }
+
+
+}
diff --git a/src/edu/berkeley/fleet/dataflow/MergeSort.java b/src/edu/berkeley/fleet/dataflow/MergeSort.java
new file mode 100644 (file)
index 0000000..b478462
--- /dev/null
@@ -0,0 +1,451 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import java.io.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.fpga.*;
+import org.ibex.graphics.*;
+
+public class MergeSort {
+
+    private final Fleet fleet;
+    private final Ship mem1;
+    private final Ship mem2;
+    private final int arity;
+    private final ShipPool pool;
+    private final Program program;
+    private final DataFlowGraph dfg;
+
+    private ParameterNode[] pn0;
+    private ParameterNode[] pn1;
+    private ParameterNode[] pn2;
+    private ParameterNode[] pn3;
+    private ParameterNode[] pn4;
+    private ParameterNode[] pn_base1;
+    private ParameterNode   pn_base2;
+    private ParameterNode   pn5;
+    private ParameterNode   pn6;
+    private ParameterNode   pn_end;
+
+    CodeBag cb2 = null;
+    Destination next_dest = null;
+
+    public MergeSort(Fleet fleet, Program program, ShipPool pool, int arity, Ship mem1, Ship mem2) {
+        this.fleet = fleet;
+        this.mem1 = mem1;
+        this.mem2 = mem2;
+        this.arity = arity;
+        this.pool = pool;
+        this.program = program;
+        this.dfg = new DataFlowGraph(fleet, pool);
+        /*
+        pool.allocateShip(mem1);
+        if (mem2 != mem1) pool.allocateShip(mem2);
+        */
+        next_dest = makeDfgCodeBag(dfg);
+        cb2 = dfg.build(new CodeBag(dfg.fleet, program));
+        cb2.seal();
+    }
+
+    public Destination makeDfgCodeBag(DataFlowGraph dfg) {
+
+        MemoryNode mem_read  = new MemoryNode(dfg, mem1);
+        MemoryNode mem_write = (mem1==mem2) ? mem_read : new MemoryNode(dfg, mem2);
+
+        AluNode sm = new AluNode(dfg, "MAXMERGE");
+
+        pn0 = new ParameterNode[arity];
+        pn1 = new ParameterNode[arity];
+        pn2 = new ParameterNode[arity];
+        pn3 = new ParameterNode[arity];
+        pn4 = new ParameterNode[arity];
+        pn_base1 = new ParameterNode[arity];
+        pn_base2 = new ParameterNode(dfg, true);
+        pn_end = new ParameterNode(dfg);
+        pn5 = new ParameterNode(dfg);
+        pn6 = new ParameterNode(dfg, true);
+
+        // So far: we have four spare Counter ships; one can be used for resetting
+        for(int i=0; i<arity; i++) {
+
+            DownCounterNode c0 = new DownCounterNode(dfg);
+            DownCounterNode c1 = new DownCounterNode(dfg);
+
+            c0.start.connect((pn0[i] = new ParameterNode(dfg, true)).out);
+            c0.incr.connect(new ForeverNode(dfg, 1).out);
+            c1.start.connect((pn1[i] = new ParameterNode(dfg)).out);
+            c1.incr.connect((pn2[i] = new ParameterNode(dfg)).out);
+
+            RepeatNode r1 = new RepeatNode(dfg);
+            r1.val.connect(c1.out);
+            r1.count.connect((pn3[i] = new ParameterNode(dfg, true)).out);
+
+            AluNode alu1 = new AluNode(dfg, "ADD");
+            AluNode alu2 = new AluNode(dfg, "ADD");
+            alu1.in1.connect(r1.out);
+            alu1.in2.connect(c0.out);
+            alu1.out.connect(alu2.in2);
+            alu2.in1.connect((pn_base1[i] = new ParameterNode(dfg, true)).out);
+            alu2.out.connect(i==0 ? mem_read.inAddrRead1 : mem_read.inAddrRead2);
+
+            PunctuatorNode punc = new PunctuatorNode(dfg, -1);
+            punc.count.connect((pn4[i] = new ParameterNode(dfg, true)).out);
+            punc.val.connect(i==0 ? mem_read.outRead1 : mem_read.outRead2);
+            punc.out.connect(i==0 ? sm.in1 : sm.in2);
+        }
+
+        UnPunctuatorNode unpunc = new UnPunctuatorNode(dfg);
+        unpunc.val.connect(sm.out);
+        unpunc.count.connect(pn6.out);
+
+        DownCounterNode cw = new DownCounterNode(dfg);
+        cw.start.connect(pn5.out);
+        cw.incr.connect(new OnceNode(dfg, 1).out);
+
+        AluNode alu = new AluNode(dfg, "ADD");
+        alu.in1.connect(pn_base2.out);
+        cw.out.connect(alu.in2);
+        mem_write.inAddrWrite.connect(alu.out);
+        mem_write.inDataWrite.connect(unpunc.out);
+
+        UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+        discard.count.connect(pn_end.out);
+        mem_write.outWrite.connect(discard.val);
+        DoneNode done = new DoneNode(dfg, program);
+        discard.out.connect(done.in);
+
+        return done.getDestinationToSendNextCodeBagDescriptorTo();
+    }
+
+    public CodeBag build(DataFlowGraph dfg,
+                         CodeBag ctx,
+                         int vals_length, int stride_length,
+                         long base1,
+                         long base2,
+                         CodeBag next) throws Exception {
+       
+        for(int i=0; i<arity; i++) {
+            if (pn0[i]!=null) pn0[i].set(ctx, stride_length);
+            if (pn1[i]!=null) pn1[i].set(ctx, vals_length + i*stride_length);
+            if (pn2[i]!=null) pn2[i].set(ctx, 2*stride_length);
+            if (pn3[i]!=null) pn3[i].set(ctx, stride_length);
+            if (pn4[i]!=null) pn4[i].set(ctx, stride_length);
+            if (pn_base1[i]!=null) pn_base1[i].set(ctx, base1);
+        }
+        pn5.set(ctx, vals_length);
+        pn6.set(ctx, 2*stride_length+1);
+        pn_base2.set(ctx, base2);
+        pn_end.set(ctx, vals_length);
+        ctx.sendWord(cb2.getDescriptor(), program.getCBDDestination());
+        ctx.sendWord(next.getDescriptor(), next_dest);
+        ctx.seal();
+
+        return ctx;
+    }
+
+    public static void main(String[] s) throws Exception {
+        //mergeSort(1024*64, 4, "Dvi",
+        mergeSort(1024*128, 4, "Dvi",
+                  4194304
+                  );
+                  //548*478);
+    }
+
+    /** demo */
+    public static void main0(String[] s) throws Exception {
+        PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("stats.txt")));
+        //int inflight = 1;
+        for(int inflight=1; inflight <= 8; inflight++)
+        for(int count = 32; count < 2097152; count *= 2) {
+            System.out.println("==============================================================================");
+            System.out.println("count="+count);
+            System.out.println("inflight="+inflight);
+            //long time = timeit(count, inflight);
+            long time = mergeSort(count, inflight, "DDR2", 0);
+            pw.println(inflight + ", " + count + ", " + time);
+            pw.flush();
+        }
+    }
+
+    public static long timeit(int count, int inflight) throws Exception {
+        Fleet fleet = new Fpga();
+        FleetProcess fp = fleet.run(new Instruction[0]);
+        ShipPool pool = new ShipPool(fleet);
+        //Program program = new Program(pool.allocateShip("Memory"));
+        CodeBag cb = new CodeBag(fleet);
+
+        Ship counter1 = pool.allocateShip("Counter");
+        Ship counter2 = pool.allocateShip("Counter");
+
+        Ship timer    = pool.allocateShip("Timer");
+        Ship debug    = pool.allocateShip("Debug");
+
+        LoopFactory lf;
+
+        lf = cb.loopFactory(debug.getDock("in"), 2);
+        lf.recvWord();
+        lf.deliver();
+
+
+        // First counter //////////////////////////////////////////////////////////////////////////////
+
+        lf = cb.loopFactory(counter1.getDock("in1"), 1);
+        lf.recvToken();
+        lf.literal(count);
+        lf.deliver();
+
+        lf = cb.loopFactory(counter1.getDock("in2"), 1);
+        lf.literal(1);
+        lf.deliver();
+
+        lf = cb.loopFactory(counter1.getDock("inOp"), 1);
+        lf.literal("COUNT");
+        lf.deliver();
+
+        lf = cb.loopFactory(counter1.getDock("out"), 0);
+        lf.recvToken();
+        lf.collectWord();
+        lf.sendWord(counter2.getDock("in2"));
+
+
+        // Second counter //////////////////////////////////////////////////////////////////////////////
+
+        lf = cb.loopFactory(counter2.getDock("in1"), 1);
+        lf.literal(count);
+        lf.deliver();
+        lf.literal(1);
+        lf.deliver();
+        lf.literal(1);
+        lf.deliver();
+
+        lf = cb.loopFactory(counter2.getDock("in2"), 1);
+        for(int i=0; i<inflight; i++)
+            lf.sendToken(counter1.getDock("out"));
+        lf = lf.makeNext(0);
+        lf.recvWord();
+        lf.sendToken(counter1.getDock("out"));
+        lf.deliver();
+
+        lf = cb.loopFactory(counter2.getDock("inOp"), 1);
+        lf.literal("DROP_C1_V2");
+        lf.deliver();
+        lf.literal("PASS_C1_V1");
+        lf.deliver();
+
+        lf = cb.loopFactory(counter2.getDock("out"), 1);
+        lf.collectWord();
+        lf.sendToken(timer.getDock("out"));
+
+
+        // Timer //////////////////////////////////////////////////////////////////////////////
+
+        lf = cb.loopFactory(timer.getDock("out"), 1);
+        lf.collectWord();
+        lf.sendToken(counter1.getDock("in1"));
+        lf.sendWord(debug.getDock("in"));
+        lf.recvToken();
+        lf.collectWord();
+        lf.sendWord(debug.getDock("in"));
+
+        FpgaDock out = (FpgaDock)counter1.getDock("out");
+        FpgaDock in  = (FpgaDock)counter2.getDock("in2");
+        System.out.println("distance is " + out.getPathLength((FpgaDestination)in.getDataDestination()));
+        System.out.println("reverse distance is " + in.getPathLength((FpgaDestination)out.getDataDestination()));
+
+        for(Instruction i : cb.emit()) System.out.println(i);
+        cb.dispatch(fp, true);
+        long time1 = fp.recvWord().toLong();
+        System.out.println("got " + time1);
+        long time2 = fp.recvWord().toLong();
+        System.out.println("got " + time2);
+        System.out.println("diff=" + (time2-time1));
+
+        fp.terminate();
+
+        return (time2-time1);
+    }
+
+    public static long mergeSort(int vals_length, int inflight, String shipType, int clearAmount) throws Exception {
+        Node.CAPACITY = inflight;
+
+        Fleet fleet = new Fpga();
+        FleetProcess fp = fleet.run(new Instruction[0]);
+        ShipPool pool = new ShipPool(fleet);
+        Ship mem1 = pool.allocateShip(shipType);
+
+
+        if (clearAmount > 0)
+            randomizeMemory(fp, pool, mem1, 0, clearAmount, false);
+
+        //randomizeMemory(fp, pool, mem1, 0, vals_length, true);
+
+        BitVector[] bvs = new BitVector[vals_length];
+
+        long index = 0;
+        Picture p = new Picture(new FileInputStream("campus.png"));
+        for(int y=0; y<(478/2); y++)
+            for(int x=0; x<544; x++) {
+                if (index >= vals_length) break;
+                int pixel = (x>=p.width) ? 0 : p.data[p.width*y+x];
+                long r = (pixel>>0)  & 0xff;
+                long g = (pixel>>8)  & 0xff;
+                long b = (pixel>>16) & 0xff;
+                r >>= 2;
+                g >>= 2;
+                b >>= 2;
+                //r = ~(-1L<<6);
+                //g = ~(-1L<<6);
+                //b = ~(-1L<<6);
+                bvs[(int)index] = new BitVector(fleet.getWordWidth()).set( r | (g<<6) | (b<<12) | (index<<18) );
+                index++;
+            }
+
+        for(; index<vals_length; index++) {
+            long tag = index<<18;
+            bvs[(int)index] = new BitVector(fleet.getWordWidth()).set( tag );
+        }
+
+        System.out.println("final index " + index);
+
+        Random random = new Random(System.currentTimeMillis());
+        for(int i=0; i<bvs.length*10; i++) {
+            int from = Math.abs(random.nextInt()) % bvs.length;
+            int to   = Math.abs(random.nextInt()) % bvs.length;
+            BitVector bv = bvs[from];
+            bvs[from] = bvs[to];
+            bvs[to] = bv;
+        }
+
+        MemoryUtils.writeMem(fp, pool, mem1, offset, bvs);
+
+        Program program = new Program(pool.allocateShip("Memory"));
+        long ret = new MergeSort(fleet, program, pool, 2, mem1, mem1).main(fp, vals_length);
+
+        //long ret = 0;
+        // verify the cleanup?
+        //CleanupUtils.verifyClean(fp);
+        //MemoryUtils.readMem(fp, new ShipPool(fp.getFleet()), mem1, 0, bvs);
+
+        BitVector[] bvx = new BitVector[1024];
+        MemoryUtils.readMem(fp, new ShipPool(fp.getFleet()), mem1, 0, bvx);
+        for(int i=0; i<bvx.length; i++)
+            System.out.println(bvx[i]);
+        /*
+        System.out.println("results:");
+        for(int i=0; i<vals_length-1; i++)
+            if ( (bvs[i].toLong() & ~(-1L<<18)) != ~(-1L<<18))
+                System.out.println(bvs[i]);
+        */
+        /*
+        for(int i=0; i<vals_length-1; i++) {
+            if (bvs[i].toLong() > bvs[i+1].toLong())
+                System.out.println("sort failure at "+i+":\n  "+bvs[i]+"\n  "+bvs[i+1]);
+        }
+        */
+        fp.terminate();
+        return ret;
+    }
+
+    static int offset = 40;
+
+    //static int offset = 32;
+    //static int offset = 544*2;
+    //static int offset = 544;
+
+    public long main(FleetProcess fp, int vals_length) throws Exception {
+
+        long base_read = offset;
+        //long base_write = offset+((vals_length/544)+1)*544;
+        //long base_write = offset;
+        long base_write = vals_length + offset;
+
+        int stride = 1;
+        ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+        codeBags.add(new CodeBag(dfg.fleet, program));
+        for(; ;) {
+            CodeBag cb = codeBags.get(codeBags.size()-1);
+            //System.out.println("cb="+i+", stride="+stride);
+            boolean last = /*(base_write==offset) && */ (stride*2 >= vals_length);
+            CodeBag next;
+            if (last) {
+                next = program.getEndProgramCodeBag();
+            } else {
+                next = new CodeBag(dfg.fleet, program);
+                codeBags.add(codeBags.size(), next);
+            }
+            build(dfg, cb, vals_length, stride, base_read, base_write, next);
+            cb.seal();
+            long base = base_read; base_read=base_write; base_write=base;
+            //i++;
+            if (last) break;
+            if ((stride*2) < vals_length) stride *= 2;
+        }
+        System.out.println("done building codebags; installing...");
+        System.out.println("cb.length=="+codeBags.size());
+
+        Ship button = pool.allocateShip("Button");
+        CodeBag cb = new CodeBag(dfg.fleet, program);
+        LoopFactory lf = cb.loopFactory(button.getDock("out"), 1);
+        lf.collectWord();
+        lf.literal(codeBags.get(0).getDescriptor());
+        lf.sendWord(program.getCBDDestination());
+        cb.seal();
+
+        // FIXME
+        return program.run(fp, cb, new ShipPool(fp.getFleet()));
+    }
+
+    public static void randomizeMemory(FleetProcess fp, ShipPool pool_, Ship memory, long start, long length, boolean randomize) {
+        ShipPool pool = new ShipPool(pool_);
+        Ship mem = pool.allocateShip("Memory");
+        Program prog = new Program(mem);
+
+        DataFlowGraph dfg = new DataFlowGraph(fp.getFleet(), pool);
+        DownCounterNode dcn = new DownCounterNode(dfg);
+        dcn.start.connectOnce(length);
+        dcn.incr.connectOnce(1);
+
+        AluNode alu = new AluNode(dfg, "ADD");
+        alu.in1.connectForever(start);
+        alu.in2.connect(dcn.out);
+
+        MemoryNode mn = new MemoryNode(dfg, memory);
+        mn.inAddrWrite.connect(alu.out);
+
+        AluNode aluAnd = new AluNode(dfg, "AND");
+        if (randomize) {
+            aluAnd.in1.connect(new RandomNode(dfg).out);
+        } else {
+            //aluAnd.in1.connectForever( ~(-1L<<36) );
+            aluAnd.in1.connectForever( 0 );
+        }
+        aluAnd.in2.connectForever( ~(-1<<18) );
+        mn.inDataWrite.connect(aluAnd.out);
+        
+        UnPunctuatorNode discard = new UnPunctuatorNode(dfg, true);
+        discard.count.connectOnce(length);
+        discard.val.connect(mn.outWrite);
+        DoneNode done = new DoneNode(dfg, prog);
+        discard.out.connect(done.in);
+
+        CodeBag cb = new CodeBag(fp.getFleet(), prog);
+        dfg.build(cb);
+        cb.seal();
+
+        CodeBag cb2 = new CodeBag(fp.getFleet(), prog);
+        Ship button = fp.getFleet().getShip("Button",0);
+
+        LoopFactory lf = cb2.loopFactory(button.getDock("out"), 1);
+        //lf.collectWord();
+        lf.literal(prog.getEndProgramCodeBag().getDescriptor());
+        lf.sendWord(done.getDestinationToSendNextCodeBagDescriptorTo());
+        lf.literal(cb.getDescriptor());
+        lf.sendWord(prog.getCBDDestination());
+        cb2.seal();
+
+        System.out.println("dispatching randomization codebag...");
+        prog.run(fp, cb2, pool);
+        System.out.println("  randomization done.");
+        pool.releaseAll();
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/Node.java b/src/edu/berkeley/fleet/dataflow/Node.java
new file mode 100644 (file)
index 0000000..f090050
--- /dev/null
@@ -0,0 +1,216 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import java.util.concurrent.Semaphore;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+
+public class Node {
+
+    public static int CAPACITY = 4;
+
+    public final DataFlowGraph dfg;
+    public Node(DataFlowGraph dfg) {
+        this.dfg = dfg;
+        dfg.addNode(this);
+    }
+
+    private HashMap<String,Port> ports = new HashMap<String,Port>();
+    public void build(CodeBag ctx) { for(Port p : ports.values()) p.build(ctx); }
+    public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+        int ret = 0;
+        for(Port p : ports.values()) ret += p.reset(ctx, phase, ackDestination);
+        return ret;
+    }
+
+    public abstract class Port {
+        public final String name;
+        public Port(String name) {
+            this.name = name;
+            if (Node.this.ports.get(name)!=null) throw new RuntimeException();
+            Node.this.ports.put(name,this);
+        }
+        public abstract void build(CodeBag ctx);
+        public abstract int  reset(CodeBag ctx, int phase, Destination ackDestination);
+        public String toString() { return Node.this+"."+name; }
+    }
+
+    public abstract class InPort extends Port {
+        OutPort peer;
+        public InPort(String name) { super(name); }
+        public void connect(OutPort peer) {
+            this.setPeer(peer);
+            peer.setPeer(this);
+        }
+
+        public void connectOnce(long val) { connect(new OnceNode(dfg, val).out); }
+        public void connectForever(long val) { connect(new ForeverNode(dfg, val).out); }
+
+        public void setPeer(OutPort peer) {
+            if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
+            this.peer = peer;
+        }
+
+        /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
+        public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
+        /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
+        public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
+
+        public int getTokensToAbsorb() { return 0; }
+        public int getMaxInFlight() { return 0; }
+    }
+
+    public abstract class OutPort extends Port {
+        InPort peer;
+        public OutPort(String name) { super(name); }
+        public void connect(InPort peer) {
+            this.setPeer(peer);
+            peer.setPeer(this);
+        }
+        public void setPeer(InPort peer) {
+            if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
+            this.peer = peer;
+        }
+
+        public int getNumInitialTokens() {
+            return peer.getMaxInFlight();
+        }
+
+        /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
+        public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
+        /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
+        public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
+
+        public int getTokensToAbsorb() {
+            if (peer==null) return 0;
+            return peer.getTokensToAbsorb();
+        }
+    }
+
+    public final class DockInPort extends InPort {
+        final Dock dock;
+        int count;
+        BitVector[] pattern;
+        public boolean sticky = false;
+        public DockInPort(String name, Dock dock) { this(name, dock, 0); }
+        public DockInPort(String name, Dock dock, String constant) {
+            this(name, dock, 0, new BitVector[] { dock.getConstant(constant) }); }
+        public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
+        public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
+            super(name);
+            this.dock = dock;
+            this.count = count;
+            this.pattern = pattern;
+        }
+        public void recvToken(LoopFactory lf) { lf.recvToken(); }
+        public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
+        public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+
+        // this is the input dock's upper limit on how many data items
+        // may be in flight; the output dock to which it is connected
+        // also has a say
+        public int getMaxInFlight() { return CAPACITY; }
+
+        public int getTokensToAbsorb() { return sticky ? 0 : peer==null ? 0 : peer.getNumInitialTokens(); }
+        private boolean peerUsed() {
+            if (sticky) return false;
+            if (peer==null) return false;
+            for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
+            return false;
+        }
+        public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+            return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, peerUsed());
+        }
+        protected void build(CodeBag ctx, LoopFactory lf) {
+            /*
+            if (sticky) {
+                if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
+                lf = lf.makeNext(1, true);
+                lf.recvWord();
+                }
+            */
+            if (sticky) {
+                if (count != 0) throw new RuntimeException("expected count==0, but count=="+count);
+                lf = lf.makeNext(1, true);
+                lf.setFlags(FlagFunction.ZERO,  FlagFunction.ZERO);
+            }
+
+            if (peer!=null) {
+                int inflight = (count != 0 && count < peer.getNumInitialTokens()) ? count : peer.getNumInitialTokens();
+                for(int i=0; i<inflight; i++) peer.sendToken(lf);
+            }
+
+            lf = lf.makeNext(count, true);
+
+            // ugly hack!
+            if (sticky) {
+                lf.setPredicate(Predicate.NotFlagB);
+                lf.recvWord();
+                lf.setPredicate(null);
+                lf.setFlags(FlagFunction.ZERO,  FlagFunction.ONE);
+            }
+            for(int i=0; i<pattern.length; i++) {
+                if (pattern[i]==null) {
+                    if (peer!=null) {
+                        lf.abortLoopIfTorpedoPresent();
+                        peer.recvWord(lf);
+                        peer.sendToken(lf);
+                        lf.deliver();
+                    } else {
+                        lf.interruptibleNop();
+                    }
+                } else {
+                    lf.literal(pattern[i]);
+                    lf.abortLoopIfTorpedoPresent();
+                    lf.deliver();
+                }
+            }
+
+            if (count!=0) {
+                // "torpedoable nop" to keep the dock in a receptive state
+                lf.abortLoopIfTorpedoPresent();
+                lf.recvToken();
+            }
+        }
+        public BitVector getConstant(String constantName) {
+            return dock.getConstant(constantName);
+        }
+    }
+
+    public /*final*/ class DockOutPort extends OutPort {
+        public final Dock dock;
+        public final int count;
+        public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
+        public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
+        public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
+        public void recvWord(LoopFactory lf) { lf.recvWord(); }
+        public void build(CodeBag ctx) { build(ctx, ctx.loopFactory(dock, 1)); }
+        protected void build(CodeBag ctx, LoopFactory lf) {
+            if (peer==null) return;
+            lf = lf.makeNext(count);
+            lf.abortLoopIfTorpedoPresent();
+            peer.recvToken(lf);
+            lf.collectWord();
+            peer.sendWord(lf);
+        }
+        public int reset(CodeBag ctx, int phase, Destination ackDestination) {
+            return DoneNode.doReset(ctx, phase, dock, this, peer, ackDestination, true);
+        }
+    }
+
+    BitVector bv(long l) { return new BitVector(dfg.fleet.getWordWidth()).set(l); }
+    BitVector[] bv(long[] l) {
+        BitVector[] ret = new BitVector[l.length];
+        for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);
+        return ret;
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/dataflow/OnceNode.java b/src/edu/berkeley/fleet/dataflow/OnceNode.java
new file mode 100644 (file)
index 0000000..1d4d2aa
--- /dev/null
@@ -0,0 +1,40 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class OnceNode extends Node {
+    private BitVector bv;
+    public final OutPort out = new OutPort("out") {
+            public void sendToken(LoopFactory lf) { }
+            public void recvWord(LoopFactory lf) { }
+            public void build(CodeBag ctx) { }
+            public int  reset(CodeBag ctx, int phase, Destination ackDestination) { return 0; }
+            public void setPeer(InPort peer) {
+                this.peer = peer;
+                DockInPort pip = ((DockInPort)peer);
+                BitVector[] pip_pattern = pip.pattern;
+                BitVector[] temp = new BitVector[pip_pattern.length * 2];
+                int j = 0;
+                int i = 0;
+                boolean done = false;
+                // FIXME: if peer.count is already 1, this gets simpler and different
+                for(i=0; i<temp.length; i++) {
+                    if (pip_pattern[j] != null) {
+                        temp[i] = pip_pattern[j];
+                    } else {
+                        if (done) break;
+                        done = true;
+                        temp[i] = bv;
+                    }
+                    j++;
+                    if (j >= pip_pattern.length) j = 0;
+                }
+                pip.pattern = new BitVector[i];
+                System.arraycopy(temp, 0, pip.pattern, 0, i);
+                pip.count = 1;
+            }
+        };
+    public OnceNode(DataFlowGraph dfg, long l) { this(dfg, new BitVector(dfg.fleet.getWordWidth()).set(l)); }
+    public OnceNode(DataFlowGraph dfg, final BitVector bv) { super(dfg); this.bv = bv; }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/ParameterNode.java b/src/edu/berkeley/fleet/dataflow/ParameterNode.java
new file mode 100644 (file)
index 0000000..365a114
--- /dev/null
@@ -0,0 +1,58 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+// derived from OnceNode
+public class ParameterNode extends Node {
+
+    private boolean forever;
+
+    public void set(CodeBag ctx, long l) {
+        set(ctx, new BitVector(ctx.fleet.getWordWidth()).set(l));
+    }
+    public void set(CodeBag ctx, BitVector bv) {
+        ctx.sendWord(bv, ((DockInPort)out.peer).dock.getDataDestination());
+    }
+
+    public final OutPort out = new OutPort("out") {
+            public void sendToken(LoopFactory lf) { }
+            public void recvWord(LoopFactory lf) { if (!forever) lf.recvWord(); }
+            public void build(CodeBag ctx) { }
+            public int  reset(CodeBag ctx, int phase,
+                              Destination ackDestination) {
+                return 0; }
+            public void setPeer(InPort peer) {
+                this.peer = peer;
+                DockInPort pip = ((DockInPort)peer);
+                BitVector[] pip_pattern = pip.pattern;
+
+                if (forever) {
+                    pip.sticky = true;
+                    return;
+                }
+
+                BitVector[] temp = new BitVector[pip_pattern.length * 2];
+                int j = 0;
+                int i = 0;
+                boolean done = false;
+                // FIXME: if peer.count is already 1, this gets simpler and different
+                for(i=0; i<temp.length; i++) {
+                    if (pip_pattern[j] != null) {
+                        temp[i] = pip_pattern[j];
+                    } else {
+                        if (done) break;
+                        done = true;
+                        //temp[i] = bv;
+                    }
+                    j++;
+                    if (j >= pip_pattern.length) j = 0;
+                }
+                pip.pattern = new BitVector[i];
+                System.arraycopy(temp, 0, pip.pattern, 0, i);
+                pip.count = 1;
+            }
+        };
+    public ParameterNode(DataFlowGraph dfg) { this(dfg, false); }
+    public ParameterNode(DataFlowGraph dfg, boolean forever) { super(dfg); this.forever = forever; }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/PunctuatorNode.java b/src/edu/berkeley/fleet/dataflow/PunctuatorNode.java
new file mode 100644 (file)
index 0000000..dab8d4a
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+/**
+ *  Takes an item from "count", passes that many items from "val" to
+ *  "out", and then supplies one instance of "punc" at "out".
+ */
+public class PunctuatorNode extends Node {
+    private final long    punc;
+    public  final InPort  count;
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    private final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), "PASS_C2_V1");
+    public  final InPort  val   = new DockInPort("val",  ship.getDock("in1"));
+    public  final OutPort out   = new DockOutPort("out", ship.getDock("out")) {
+            protected void build(CodeBag ctx, LoopFactory lf) {
+                lf = lf.makeNext(0);
+                lf.abortLoopIfTorpedoPresent();
+                peer.recvToken(lf);
+                lf.collectWord();
+                peer.sendWord(lf);
+
+                lf.literal(punc);
+                lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+                lf.setPredicate(Predicate.FlagA);
+                peer.recvToken(lf);
+                peer.sendWord(lf);
+                lf.setPredicate(null);
+            }
+        };
+
+    public PunctuatorNode(DataFlowGraph dfg, long punc) {
+        super(dfg);
+        this.punc = punc;
+        this.count = new DockInPort("in2", ship.getDock("in2"));
+    }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/RandomNode.java b/src/edu/berkeley/fleet/dataflow/RandomNode.java
new file mode 100644 (file)
index 0000000..9143cf2
--- /dev/null
@@ -0,0 +1,10 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class RandomNode extends Node {
+    private final Ship    ship = dfg.pool.allocateShip("Random");
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+    public RandomNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/RepeatNode.java b/src/edu/berkeley/fleet/dataflow/RepeatNode.java
new file mode 100644 (file)
index 0000000..f17586a
--- /dev/null
@@ -0,0 +1,18 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+/**
+ *  Takes a count from "count" and an item from "val" and emits
+ *  count-many copies of val at "out".
+ */
+public class RepeatNode extends Node {
+    private final Ship    ship   = dfg.pool.allocateShip("Counter");
+    private final InPort  inOp   = new DockInPort("inOp", ship.getDock("inOp"), "REPEAT_C1_V2");
+    public final InPort   count  = new DockInPort("count",  ship.getDock("in1"));
+    public final InPort   val    = new DockInPort("val",  ship.getDock("in2"));
+    public final OutPort  out    = new DockOutPort("out", ship.getDock("out"));
+
+    public RepeatNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/SortedMergeNode.java b/src/edu/berkeley/fleet/dataflow/SortedMergeNode.java
new file mode 100644 (file)
index 0000000..7de8a8b
--- /dev/null
@@ -0,0 +1,16 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+
+public class SortedMergeNode extends Node {
+    private final Ship    ship = dfg.pool.allocateShip("Alu");
+    private final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
+            ship.getDock("inOp").getConstant("MAXMERGE") });
+
+    public final InPort  in1  = new DockInPort("in1",  ship.getDock("in1"));
+    public final InPort  in2  = new DockInPort("in2",  ship.getDock("in2"));
+    public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
+
+    public SortedMergeNode(DataFlowGraph dfg) { super(dfg); }
+}
diff --git a/src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java b/src/edu/berkeley/fleet/dataflow/UnPunctuatorNode.java
new file mode 100644 (file)
index 0000000..62bf886
--- /dev/null
@@ -0,0 +1,36 @@
+package edu.berkeley.fleet.dataflow;
+import java.util.*;
+import edu.berkeley.fleet.loops.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+
+/**
+ *  Takes an item from the "count" port, then passes/drops through count-1
+ *  items from "val" to "out" and drops/passes the count-th item.
+ */
+public class UnPunctuatorNode extends Node {
+    private final Ship    ship  = dfg.pool.allocateShip("Counter");
+    private final InPort  op    = new DockInPort("op",    ship.getDock("inOp"), "PASS_C2_V1");
+    public  final InPort  val   = new DockInPort("val",   ship.getDock("in1"));
+    public  final InPort  count = new DockInPort("count", ship.getDock("in2"));
+    public  final OutPort out   = new DockOutPort("out", ship.getDock("out")) {
+            protected void build(CodeBag ctx, LoopFactory lf) {
+                lf = lf.makeNext(0);
+                lf.abortLoopIfTorpedoPresent();
+                lf.collectWord();
+                lf.setFlags(FlagFunction.ZERO.add(Predicate.FlagC), FlagFunction.ZERO);
+                lf.setPredicate(passPunctuationInsteadOfValues ? Predicate.FlagA : Predicate.NotFlagA);
+                lf.abortLoopIfTorpedoPresent();
+                peer.recvToken(lf);
+                peer.sendWord(lf);
+                lf.setPredicate(null);
+            }
+        };
+
+    private boolean passPunctuationInsteadOfValues;
+    public UnPunctuatorNode(DataFlowGraph dfg) { this(dfg, false); }
+    public UnPunctuatorNode(DataFlowGraph dfg, boolean passPunctuationInsteadOfValues) {
+        super(dfg);
+        this.passPunctuationInsteadOfValues = passPunctuationInsteadOfValues;
+    }
+}
diff --git a/src/edu/berkeley/fleet/fpga/Client.java b/src/edu/berkeley/fleet/fpga/Client.java
new file mode 100644 (file)
index 0000000..235e183
--- /dev/null
@@ -0,0 +1,138 @@
+package edu.berkeley.fleet.fpga;
+
+import static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.net.*;
+import edu.berkeley.fleet.util.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import static edu.berkeley.fleet.api.Instruction.*;
+
+
+public class Client extends FleetProcess {
+
+    private Socket s;
+    private BlockingQueue<BitVector> queue = new LinkedBlockingQueue<BitVector>();
+
+    public Fleet getFleet() { return fpga; }
+    public Dock getDebugInputDock() {
+        return fpga.getShip("Debug",0).getDock("in");
+    }
+    public BitVector recvWord() {
+        if (isTerminated())
+            throw new RuntimeException("this fleet has been terminated");
+        try {
+            return queue.take();
+        } catch (InterruptedException e) { throw new RuntimeException(e); }
+    }
+
+    protected void _terminate() {
+        try {
+            s.close();
+        } catch (Exception e) { e.printStackTrace(); }
+    }
+
+    private Fpga fpga;
+    private OutputStream os = null;
+
+    public void flush() {
+        try {
+            os.flush();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public Client(Fpga fpga, String bitfile, Instruction[] instructions) throws Exception {
+        this.fpga = fpga;
+
+        s = new Socket(InetAddress.getByName("goliath.megacz.com"), 3133);
+        //s = new Socket(InetAddress.getByName("localhost"), 3133);
+        this.os = new BufferedOutputStream(s.getOutputStream());
+        final InputStream is = new BufferedInputStream(s.getInputStream());
+        PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
+        pw.print(Server.pass_string+" "+bitfile+"\n");
+        pw.flush();
+
+        // goofy reset sequence
+        new Thread() {
+            public void run() {
+                try {
+                    for(int i=0; i<255; i++) os.write( (3<<6) | 0);
+                    for(int i=0; i<60; i++) os.write( (3<<6) | i);
+                    os.flush();
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+        }.start();
+        int k = 1;
+        while(k<60) {
+            int i = is.read();
+            if ( (i & (3<<6)) != (3<<6) ) { k=1; continue; }
+            i = i & ~((-1)<<6);
+            if (i==k) k++; else k = 1;
+        }
+        
+        // initial flow-control credits
+        os.write( (1<<6) | 15);
+
+        Thread t = new Thread() {
+            public void run() {
+                try {
+                    OUTER: while(true) {
+                        long result = 0;
+                        for(int i=0; i<8; i++) {
+                            int val = is.read();
+                            if (val==-1) break OUTER;
+                            result |= ((val & 0xffL) << (i * 6L));
+                        }
+                        BitVector bs = new BitVector(37);
+                        for(int i=0; i<37; i++)
+                            bs.set(i, ((result >> i) & 1L)!=0);
+                        queue.put(bs);
+                    }
+                } catch (SocketException e) {
+                } catch (Exception e) { throw new RuntimeException(e);
+                } finally { terminate(); }
+            }
+            };
+        t.setDaemon(true);
+        t.start();
+
+        for(Instruction inst : instructions) sendInstruction(inst);
+        flush();
+    }
+
+    public void sendToken(Destination d) { sendWord(d, new BitVector(fpga.getWordWidth()), true); }
+    public void sendWord(Destination d, BitVector word) { sendWord(d, word, false); }
+    private void sendWord(Destination d, BitVector word, boolean token) {
+        try {
+            Dock dispatchFrom = fpga.debugShip.getDock("in");
+            long out = 0;
+            out = fpga.PACKET_DATA.setval(out, word);
+            out = fpga.PACKET_TOKEN.setval(out, token ? 1 : 0);
+            out = fpga.PACKET_SIGNAL.setval(out, 0);
+            out = fpga.PACKET_DEST.setval(out, ((FpgaPath)dispatchFrom.getPath(d, null)).toLong());
+            synchronized(this) {
+                for(int i=9; i>=0; i--)
+                    os.write(BitManipulations.getIntField(i*6+5, i*6, out));
+                os.flush();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+    public void sendInstruction(Instruction inst) {
+        Dock dispatchFrom = fpga.debugShip.getDock("in");
+        sendWord(inst.dock.getInstructionDestination(),
+                 new BitVector(fpga.getWordWidth()).set(fpga.writeInstruction(inst, dispatchFrom)));
+    }
+
+    private static Move discard(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
+    private static Move deliver(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
+    private static Move wait(Dock dock)              { return new Move(dock, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
+    private static Move sendto(Dock dock, Path path) { return new Move(dock, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
+}
diff --git a/src/edu/berkeley/fleet/fpga/FabricElement.java b/src/edu/berkeley/fleet/fpga/FabricElement.java
new file mode 100644 (file)
index 0000000..c340c99
--- /dev/null
@@ -0,0 +1,36 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+
+public interface FabricElement {
+
+    public FpgaPath getPath(FpgaDestination dest, BitVector signal);
+    public int      getPathLength(FpgaDestination dest);
+
+    public void addInput(FabricElement in, Module.Port inPort);
+    public void addOutput(FabricElement out, Module.Port outPort);
+
+    public Module.SourcePort getOutputPort();
+    public Module.Port getInputPort();
+
+    public static abstract class AbstractFabricElement implements FabricElement {
+        public abstract FpgaPath getPath(FpgaDestination dest, BitVector signal);
+        public abstract int getPathLength(FpgaDestination dest);
+        public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
+        public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
+        public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
+        public Module.Port getInputPort() { throw new RuntimeException(); }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/FanoutModule.java b/src/edu/berkeley/fleet/fpga/FanoutModule.java
new file mode 100644 (file)
index 0000000..05bda6b
--- /dev/null
@@ -0,0 +1,31 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+public class FanoutModule extends Module {
+    public FanoutModule(int width) {
+        super("fanout"+width);
+        Module.SourcePort in   = createInputPort ("in",   width);
+        Module.SinkPort   out0 = createOutputPort("out0", width);
+        Module.SinkPort   out1 = createOutputPort("out1", width);
+
+        out0.connectValue(in);
+        out1.connectValue(in);
+
+        Module.StateWire  busy    = new StateWire("busy", false);
+        new Event(new Object[] { in, out0, out1, busy.isEmpty() },
+                  new Action[] {     out0, out1, busy.doFill() });
+        new Event(new Object[] { in, out0, out1, busy.isFull() },
+                  new Action[] { in,             busy.doDrain() });
+    }
+}
diff --git a/src/edu/berkeley/fleet/fpga/FifoModule.java b/src/edu/berkeley/fleet/fpga/FifoModule.java
new file mode 100644 (file)
index 0000000..21ceab6
--- /dev/null
@@ -0,0 +1,74 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+public class FifoModule extends Module {
+    private int len;
+    private int width;
+    private boolean doubleSpeed;
+    public FifoModule(int len, int width) { this(len, width, false); }
+    public FifoModule(int len, int width, boolean doubleSpeed) {
+        super("fifo"+len+"x"+width+(doubleSpeed?"_2x":""));
+        this.len = len;
+        this.width = width;
+        this.doubleSpeed = doubleSpeed;
+        Module.SourcePort  in  = createInputPort("in", width);
+        Module.SinkPort    out = createOutputPort("out", width);
+        Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
+        if (len==0) {
+            in.connect(out);
+        } else if (len==1) {
+            if (doubleSpeed) throw new RuntimeException();
+            new Event(new Object[] { in, out },
+                      new Action[] { in, out, new AssignAction(out, in) });
+        } else {
+            Module fifo1 = new FifoModule(1,width);
+            for(int i=0; i<=len; i++) {
+                if (i<len) stages[i] = new Module.InstantiatedModule(this, fifo1);
+                Module.SourcePort driver = i==0 ? in : stages[i-1].getOutputPort("out");
+                Module.SinkPort   driven = i==len ? out : stages[i].getInputPort("in");
+                driver.connect(driven);
+            }
+        }
+    }
+
+    int dislog(int num) {
+        for(int i=0; i<32; i++)
+            if ((1<<i) >= num)
+                return i;
+        throw new RuntimeException();
+    }
+
+    public void dump(String prefix) throws IOException {
+        if (len>16) throw new RuntimeException("FifoModule(i>16) not supported due to SRL16 limitation");
+
+        if (len>=2) {
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+            pw.println("`define ADDR_BITS "+dislog(len));
+            pw.println("`define WIDTH " + width);
+            pw.println("`define MODULE_NAME "+name);
+            if (doubleSpeed) {
+                pw.println("`define DELAY 2");
+            } else {
+                pw.println("`define DELAY 5");
+            }
+            pw.println("`include \"ramfifo.inc\"");
+            pw.flush();
+            return;
+        }
+        if (doubleSpeed) throw new RuntimeException();
+
+        super.dump(prefix);
+        return;
+    }
+}
diff --git a/src/edu/berkeley/fleet/fpga/Fpga.java b/src/edu/berkeley/fleet/fpga/Fpga.java
new file mode 100644 (file)
index 0000000..20567ed
--- /dev/null
@@ -0,0 +1,345 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import edu.berkeley.fleet.two.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+import edu.berkeley.fleet.two.PercolatedPort;
+
+
+public class Fpga extends FleetTwoFleet {
+
+    public  Module top;
+    Ship debugShip;
+
+    public LinkedHashMap<String,FpgaShip> ships = new LinkedHashMap<String,FpgaShip>();
+    public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
+
+    public Ship getShip(String type, int ordinal) {
+        for(Ship s : this)
+            if (s.getType().equals(type))
+                if (--ordinal < 0)
+                    return s;
+        return null;
+    }
+
+    public static void main(String[] s) throws Exception { 
+        new Fpga(new Module("main")).top.dump(s[0]);
+        PrintWriter pw;
+
+        pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(s[0]+"/timescale.v")));
+        pw.println("`timescale 1ns / 10ps");
+        pw.close();
+
+        pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(s[0]+"/vram.v")));
+        pw.println("`define BRAM_ADDR_WIDTH 19");
+        pw.println("`define BRAM_DATA_WIDTH 3");
+        pw.println("`define BRAM_SIZE (640*480)");
+        pw.println("`define BRAM_NAME vram");
+        pw.println("`include \"bram.inc\"");
+        pw.close();
+    }
+
+    public Module getVerilogModule() { return top; }
+
+    public FleetProcess run(Instruction[] instructions) {
+        try {
+            return new Client(this, "none", instructions);
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    protected BitVector getDestAddr(Path path) {
+        return ((FpgaPath)path).toBitVector();
+    }
+
+    // Setup //////////////////////////////////////////////////////////////////////////////
+
+    Ship createShip(String type) throws IOException {
+        ShipDescription sd = new ShipDescription(this, type, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
+        int count = 0;
+        for(Ship ship : ships.values()) if (ship.getType().equals(type)) count++;
+        String name = type+count;
+        FpgaShip ship = new FpgaShip(this, sd);
+        ships.put(name, ship);
+        return ship;
+    }
+
+    public Fpga() throws Exception { this(new Module("main")); }
+    public Fpga(Module top) throws Exception {
+        this.top = top;
+        debugShip = createShip("Debug");
+
+        //boolean small = true;
+        boolean small = false;
+
+        if (small) {
+            for(int i=0; i<2; i++) createShip("Alu");
+            for(int i=0; i<1; i++) createShip("Memory");
+            for(int i=0; i<2; i++) createShip("Fifo");
+            createShip("Counter");
+            createShip("CarrySaveAdder");
+            createShip("Rotator");
+            createShip("Lut3");
+
+        } else {
+
+            for(int i=0; i<2; i++)  createShip("Memory");
+            for(int i=0; i<6; i++)  createShip("Alu");
+            //for(int i=0; i<2; i++)  createShip("Fifo");
+            for(int i=0; i<12; i++) createShip("Counter");
+            //for(int i=0; i<2; i++)  createShip("Null");
+
+            //createShip("CarrySaveAdder");
+            //createShip("Rotator");
+            createShip("Random");
+            createShip("Button");
+
+        }
+
+        createShip("Timer");
+        createShip("DDR2");
+        createShip("Dvi");
+
+        // for FifoShip
+        new Module.InstantiatedModule(top, new FifoModule(8, WIDTH_WORD));
+
+        ArrayList dests   = new ArrayList<FabricElement>();
+        ArrayList sources = new ArrayList<FabricElement>();
+        for(FpgaShip ship : (Iterable<FpgaShip>)(Object)this) {
+            for(Dock port : ship) {
+                if (port.isInputDock()) {
+                    sources.add(((FpgaDock)port));
+                    dests.add(port.getInstructionDestination());
+                    dests.add(port.getDataDestination());
+                } else {
+                    sources.add(((FpgaDock)port));
+                    dests.add(port.getInstructionDestination());
+                    dests.add(port.getDataDestination());
+                }
+            }
+            for(Module.SourcePort sp0 : ship.docklessPorts.values()) {
+                final Module.SourcePort sp = sp0;
+                sources.add(new FabricElement.AbstractFabricElement() {
+                        private FabricElement upstream;
+                        public int      getPathLength(FpgaDestination dest) { return upstream.getPathLength(dest); }
+                        public FpgaPath getPath(FpgaDestination dest, BitVector signal) { return upstream.getPath(dest, signal); }
+                        public void addOutput(FabricElement out, Module.Port outPort) {
+                            this.upstream = out;
+                            sp.connect((Module.SinkPort)outPort);
+                        }
+                    });
+            }
+        }
+        FabricElement top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true);
+        mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false)
+            .addOutput(top_horn, top_horn.getInputPort());
+    }
+
+    public FabricElement mkNode(FabricElement[] ports, boolean is_horn) { return mkNode(ports, is_horn, 0, ports.length); }
+    public FabricElement mkNode(FabricElement[] ports, boolean is_horn, int start, int end) {
+        switch(end-start) {
+            case 0: throw new RuntimeException("this should never happen");
+            case 1: return ports[start];
+            default: {
+                FabricElement leftPort  = mkNode(ports, is_horn,  start,         (end+start)/2);
+                FabricElement rightPort = mkNode(ports, is_horn,  (end+start)/2, end);
+                return is_horn
+                    ? new HornModule.HornInstance(this, top,     leftPort, rightPort)
+                    : new FunnelModule.FunnelInstance(this, top, leftPort, rightPort);
+            }
+        }
+    }
+
+
+    // Expand //////////////////////////////////////////////////////////////////////////////
+
+    public void expand(ShipDescription sd) {
+        try {
+            if (sd.getSection("fpga")==null) return;
+            String filename = sd.getName().toLowerCase();
+
+            if (sd.getSection("ucf") != null) {
+                File outf = new File("build/fpga/"+filename+".ucf");
+                FileOutputStream out = new FileOutputStream(outf);
+                PrintWriter pw = new PrintWriter(out);
+                pw.println(sd.getSection("ucf"));
+                pw.flush();
+                pw.close();
+            }
+
+            File outf = new File("build/fpga/"+filename+".v");
+            new File(outf.getParent()).mkdirs();
+            System.err.println("writing to " + outf);
+            FileOutputStream out = new FileOutputStream(outf);
+            PrintWriter pw = new PrintWriter(out);
+
+            pw.println("`define WORDWIDTH                "+WIDTH_WORD);
+            pw.println("`define CODEBAG_SIZE_BITS        "+CBD_SIZE.valmaskwidth);
+            pw.println();
+
+            for(DockDescription dd : sd.ports()) {
+                String name = dd.getName();
+                pw.println("`define "+name+"_full    ("+name+"_r && !"+name+"_a)");
+                pw.println("`define "+name+"_empty  (!"+name+"_r && !"+name+"_a)");
+                if (dd.isInputDock()) {
+                    // gets stuck on colliding-tokens
+                    //pw.println("`define drain_"+name+"  if ("+name+"_r && !"+name+"_a) "+name+"_a <= 1;");
+
+                    // gets stuck on colliding-tokens
+                    //pw.println("`define drain_"+name+"  if ("+name+"_r) "+name+"_a <= 1;");
+
+                    // also gets stuck
+                    //pw.println("`define drain_"+name+"  if (!"+name+"_a) "+name+"_a <= 1;");
+                    pw.println("`define drain_"+name+"  "+name+"_a <= 1;");
+                } else {
+                    pw.println("`define fill_"+name+"  "+name+"_r <= 1;");
+                }
+            }
+
+            pw.print("`define reset ");
+            for(DockDescription bb : sd.ports()) {
+                String bb_name = bb.getName();
+                if (bb.isInputDock()) pw.print(bb_name+"_a <= 1; ");
+                else                  pw.print(bb_name+"_r <= 0; ");
+            }
+            pw.println();
+
+            pw.print("`define cleanup ");
+
+            // output docks
+            for(DockDescription dd : sd.ports())
+                if (!dd.isInputDock())
+                    pw.print("if ( "+dd.getName()+"_r && "+dd.getName()+"_a) "+dd.getName()+"_r <= 0; ");
+
+            // input docks: if all inputs are flushing, drain them all
+            pw.print("if (1");
+            for(DockDescription bb : sd.ports())
+                if (bb.isInputDock())
+                    pw.print(" && "+bb.getName()+"_f");
+            pw.print(") begin ");
+            for(DockDescription bb : sd.ports())
+                if (bb.isInputDock())
+                    pw.print(bb.getName()+"_a <= 1; ");
+
+            // input docks: if no inputs are flushing, do normal stuff
+            pw.print("end else if (1");
+            for(DockDescription bb : sd.ports())
+                if (bb.isInputDock())
+                    pw.print(" && !"+bb.getName()+"_f");
+            pw.print(") begin ");
+
+            for(DockDescription bb : sd.ports())
+                if (bb.isInputDock())
+                    pw.print("if (!"+bb.getName()+"_r_ && "+bb.getName()+"_a) "+bb.getName()+"_a <= 0; ");
+
+            // input docks: if some-but-not-all inputs are flushing, drain all non-flushing docks
+            pw.print("end else begin ");
+
+            for(DockDescription bb : sd.ports())
+                if (bb.isInputDock()) {
+                    pw.print("if (!"+bb.getName()+"_r && "+bb.getName()+"_a) "+bb.getName()+"_a <= 0; ");
+                    pw.print("if ("+bb.getName()+"_r && !"+bb.getName()+"_a) "+bb.getName()+"_a <= 1; ");
+                }
+
+            pw.print(" end");
+
+            pw.println();
+            
+            pw.println("module " + filename + "( clk, rst ");
+            for(DockDescription bb : sd.ports()) {
+                String bb_name = bb.getName();
+                pw.print("        ");
+                if (bb.isInputDock()) {
+                    pw.print(", " + bb_name+"_r_");
+                    pw.print(", " + bb_name+"_a_");
+                    pw.print(", " + bb_name+"_d");
+                } else {
+                    pw.print(", " + bb_name+"_r_");
+                    pw.print(", " + bb_name+"_a");
+                    pw.print(", " + bb_name+"_d_");
+                }
+                pw.println();
+            }
+            for(PercolatedPort pp : sd.percolatedPorts) {
+                pw.print("    , ");
+                pw.println(pp.name);
+            }
+            pw.println("        );");
+            pw.println();
+            pw.println("    input clk;");
+            pw.println("    input rst;");
+            for(PercolatedPort pp : sd.percolatedPorts) {
+                switch(pp.type) {
+                    case UP:    pw.print("output"); break;
+                    case DOWN:  pw.print("input");  break;
+                    case INOUT: pw.print("inout");  break;
+                }
+                pw.print("  ");
+                if (pp.width > 1)
+                    pw.print("["+(pp.width-1)+":0]");
+                pw.print(" ");
+                pw.print(pp.name);
+                pw.println(";");
+            }
+
+            for(DockDescription bb : sd.ports()) {
+                String bb_name = bb.getName();
+                int width = bb.isDockless() ? WIDTH_PACKET : WIDTH_WORD;
+                if (bb.isInputDock()) {
+                    pw.println("        input   ["+width+":0] "+bb_name+"_d;");
+                    pw.println("        input   "+bb_name+"_r_;");
+                    pw.println("        wire    "+bb_name+"_r;");
+                    pw.println("        assign  "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+width+"];");
+                    pw.println("        output  "+bb_name+"_a_;");
+                    pw.println("        reg     "+bb_name+"_a;");
+                    pw.println("        initial "+bb_name+"_a  = 0;");
+                    pw.println("        wire    "+bb_name+"_f;");
+                    pw.println("        assign  "+bb_name+"_f  = "+bb_name+"_r_ & "+bb_name+"_d["+width+"] && ~"+bb_name+"_a;");
+                    pw.println("        assign  "+bb_name+"_a_ = "+bb_name+"_a;");
+                } else {
+                    pw.println("        output  ["+width+":0] "+bb_name+"_d_;");
+                    pw.println("        input   "+bb_name+"_a;");
+                    pw.println("        output  "+bb_name+"_r_;");
+                    pw.println("        reg     "+bb_name+"_r;");
+                    pw.println("        initial "+bb_name+"_r  = 0;");
+                    pw.println("        assign  "+bb_name+"_r_ = "+bb_name+"_r;");
+                }
+                pw.println();
+            }
+
+            if (filename.equals("fifo")) {
+                pw.println("  wire in_a__;");
+                pw.println("  wire out_r__;");
+                pw.println("  fifo8x37 fifo8x37(clk, rst,");
+                pw.println("                    in_r,    in_a__, in_d,");
+                pw.println("                    out_r__, out_a,  out_d_);");
+                pw.println("  always @(posedge clk) begin");
+                pw.println("    if (rst) begin");
+                pw.println("      `reset");
+                pw.println("    end else begin");
+                pw.println("      `cleanup");
+                pw.println("      out_r <= out_r__;");
+                pw.println("      if (in_a__) in_a  <= 1;");
+                pw.println("    end");
+                pw.println("  end");
+            } else {
+                pw.println(sd.getSection("fpga"));
+            }
+
+            pw.println("endmodule");
+
+            pw.flush();
+            pw.close();
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/FpgaDestination.java b/src/edu/berkeley/fleet/fpga/FpgaDestination.java
new file mode 100644 (file)
index 0000000..37677ce
--- /dev/null
@@ -0,0 +1,51 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Dock;
+import java.util.*;
+
+
+public class FpgaDestination extends Destination implements FabricElement {
+    private Module.Port port;
+    private boolean isInstructionDestination;
+    FpgaDock dock;
+
+    public FpgaDestination(FpgaDock dock, Module.Port port, boolean isInstructionDestination) {
+        super(dock);
+        this.port = port;
+        this.dock = dock;
+        this.isInstructionDestination = isInstructionDestination;
+    }
+
+    public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
+    public Module.Port getInputPort()  { throw new RuntimeException(); }
+    public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
+
+    public int      getPathLength(FpgaDestination dest) {
+        if (dest==this) {
+            return isInstructionDestination ? 0 : FpgaDock.DATA_FIFO_SIZE;
+        }
+        return 0;
+    }
+    public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
+        if (dest==this) return FpgaPath.emptyPath(this, signal);
+        return null;
+    }
+    public void addInput(FabricElement in, Module.Port inPort) {
+        ((Module.SourcePort)inPort).connect((Module.SinkPort)port);
+    }
+    public String toString() {
+        return dock.toString() + (isInstructionDestination ? ":i" : "");
+    }
+}
diff --git a/src/edu/berkeley/fleet/fpga/FpgaDock.java b/src/edu/berkeley/fleet/fpga/FpgaDock.java
new file mode 100644 (file)
index 0000000..b06bc68
--- /dev/null
@@ -0,0 +1,398 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Dock;
+import edu.berkeley.fleet.two.*;
+import java.util.*;
+
+public class FpgaDock extends FleetTwoDock implements FabricElement {
+
+    //private static final int INSTRUCTION_FIFO_SIZE = 12;
+
+    // Marina has 12 latches in the ring, 9 of which are wagged (plus
+    // M1, OD, RQ), so max capacity is 11 instructions
+    static final int INSTRUCTION_FIFO_SIZE = 11;
+    static final int INSTRUCTION_WAGGED_STAGES = 8;
+
+    //private static final int DATA_FIFO_SIZE        = 4;
+    static final int DATA_FIFO_SIZE        = 8;
+        
+    private FpgaDestination dataDestination;
+    private FpgaDestination instructionDestination;
+
+    private Module.InstantiatedModule instance;
+
+    public Module.InstantiatedModule getInstance() { return instance; }
+
+    private Fpga fpga;
+
+    public Destination getDataDestination() { return dataDestination; }
+    public Destination getInstructionDestination() { return instructionDestination; }
+    public int         getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; }
+
+    FpgaDock(FpgaShip ship, DockDescription bbd) {
+        super(ship, bbd);
+        this.fpga = (Fpga)ship.getFleet();
+        this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock()));
+        this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false);
+        this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true);
+        Module.InstantiatedModule shipm = ship.getVerilogModule();            
+        if (isInputDock()) {
+            instance.getOutputPort("ship").connect(shipm.getInputPort(getName()));
+        } else {
+            shipm.getOutputPort(getName()).connect(instance.getInputPort("ship"));
+        }
+    }
+
+
+    // FabricElement methods //////////////////////////////////////////////////////////////////////////////
+
+    private FabricElement upstream;
+    public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
+    public Module.Port getInputPort()  { throw new RuntimeException(); }
+    public Path getPath(Destination dest,BitVector signal) { return getPath((FpgaDestination)dest, signal); }
+    public FpgaPath getPath(FpgaDestination dest,BitVector signal) { return upstream.getPath(dest, signal); }
+    public int      getPathLength(FpgaDestination dest) { return upstream.getPathLength(dest)-1; }
+    public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
+    public void addOutput(FabricElement out, Module.Port outPort) {
+        this.upstream = out;
+        instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort);
+    }
+
+    public class TorpedoBranchModule extends Module {
+        public TorpedoBranchModule() {
+            super("torpedobranch");
+            Module.SourcePort in      = createInputPort ("in",  fpga.WIDTH_PACKET);
+            Module.SinkPort   out     = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+            Module.SinkPort   torpedo = createOutputPort("torpedo", 0);
+            Module.StateWire  busy    = new StateWire("busy", false);
+
+            new Event(new Object[] { in, busy.isFull(), out },
+                      new Action[] { in, busy.doDrain() });
+            new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.testMask(fpga.PACKET_IS_TOKEN) },
+                      new Action[] { in,                      torpedo });
+            new Event(new Object[] { in, busy.isEmpty(), out,          in.testMask(fpga.PACKET_IS_TOKEN).invert() },
+                      new Action[] {     busy.doFill(),  out });
+
+            out.connectValue(in.getBits(fpga.PACKET_DATA));
+        }
+    }
+
+    public class RequeueModule extends Module {
+        public RequeueModule() {
+            super("requeue");
+            Module.SourcePort fabric_in     = createInputPort ("fabric_in",  fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+            Module.SourcePort ondeck_in     = createInputPort ("ondeck_in",  fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+            Module.SourcePort abort         = createInputPort ("abort",     1);
+            Module.SinkPort   out           = createOutputPort("out",        fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+
+            Module.StateWire  circulating   = new StateWire("circulating", false);
+            Module.StateWire  doResetFabric = new StateWire("doResetFabric", false);
+            Module.StateWire  doResetOndeck = new StateWire("doResetOndeck", false);
+
+            out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
+
+            // always: discard one-shot instructions
+            new Event(new Object[] { doResetFabric.isFull(),  out },
+                      new Action[] { doResetFabric.doDrain(), fabric_in });
+            new Event(new Object[] { doResetOndeck.isFull(),  out },
+                      new Action[] { doResetOndeck.doDrain(), ondeck_in });
+
+            // Updating->Circulating transition
+            new Event(new Object[] { doResetFabric.isEmpty(),
+                                     doResetOndeck.isEmpty(),
+                                     circulating.isEmpty(),
+                                     fabric_in,
+                                     fpga.TAIL.verilog(fabric_in.getName()),
+                                     ondeck_in,
+                                     fpga.HEAD.verilog(ondeck_in.getName()) },
+                      new Action[] { circulating.doFill(),
+                                     fabric_in,
+                                     ondeck_in });
+
+            // Circulating->Updating transition
+            new Event(new Object[] { doResetFabric.isEmpty(),
+                                     doResetOndeck.isEmpty(),
+                                     circulating.isFull(),
+                                     ondeck_in,
+                                     abort.getVerilog() },
+                      new Action[] { circulating.doDrain(),
+                                     ondeck_in });
+
+            // Updating
+            new Event(new Object[] { doResetFabric.isEmpty(),
+                                     doResetOndeck.isEmpty(),
+                                     circulating.isEmpty(),
+                                     fabric_in,
+                                     "!"+fpga.TAIL.verilog(fabric_in.getName()) },
+                      new Action[] { doResetFabric.doFill(),
+                                     out });
+            new Event(new Object[] { doResetFabric.isEmpty(),
+                                     doResetOndeck.isEmpty(),
+                                     circulating.isEmpty(),
+                                     ondeck_in,
+                                     "!"+fpga.HEAD.verilog(ondeck_in.getName()) },
+                      new Action[] { ondeck_in });
+                                     
+            // Circulating
+            new Event(new Object[] { doResetFabric.isEmpty(),
+                                     doResetOndeck.isEmpty(),
+                                     circulating.isFull(),
+                                     ondeck_in,
+                                     "!"+abort.getVerilog() },
+                      new Action[] { doResetOndeck.doFill(),
+                                     out });
+        }
+    }
+
+    public class DockModule extends Module {
+
+        public DockModule(boolean inbox) {
+            super(inbox ? "inbox" : "outbox");
+
+            int dfifo_width = inbox ? fpga.getWordWidth()+1 : 1;
+
+            // FIXME: assumes fpga.DISPATCH_PATH is at top of word!!!
+            Module ififo_m_1   = new FifoModule(INSTRUCTION_FIFO_SIZE, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+            //Module ififo_m_1   = new FifoModule(INSTRUCTION_FIFO_SIZE-INSTRUCTION_WAGGED_STAGES, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+            //Module ififo_m_2   = new FifoModule(INSTRUCTION_WAGGED_STAGES, fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, true);
+
+            Module dfifo_m   = new FifoModule(DATA_FIFO_SIZE,        dfifo_width);
+
+            Module.SourcePort instruction   = createInputPort("instruction", fpga.WIDTH_PACKET);
+            Module.SourcePort fabric_in     = createInputPort("fabric_in",   fpga.WIDTH_PACKET);
+
+            // FIXME: at inboxes, no need for a full set of latches
+            Module.SinkPort   fabric_out    = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
+            
+            Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
+
+            fabric_in.connect(dfifo.getInputPort("in"));
+            dfifo.getInputPort("in").connectValue(
+                !inbox
+                ? fabric_in.getBits(fpga.PACKET_SIGNAL)
+                : new CatValue(new Value[] {
+                        fabric_in.getBits(fpga.PACKET_SIGNAL),
+                        fabric_in.getBits(fpga.PACKET_DATA)
+                    }));
+        
+            Module.SourcePort dfifo_out     = dfifo.getOutputPort("out");
+            Module.SourcePort ship_out      = !inbox ? createInputPort("ship",  fpga.getWordWidth()+1) : null;
+            Module.SinkPort   ship_in       =  inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null;
+
+            Module.Latch     ilc            = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
+            Module.Latch     olc            = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
+            Module.Latch     flag_a         = new Latch("flag_a", 1);
+            Module.Latch     flag_b         = new Latch("flag_b", 1);
+            Module.Latch     flag_c         = new Latch("flag_c", 1);
+            Module.Latch     flag_d         = new Latch("flag_d", 1);
+
+            Module.SinkPort   token_out     = fabric_out;
+            Module.SourcePort token_in      = dfifo_out;
+            Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
+            Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
+
+            Module.InstantiatedModule ififo_1 = new Module.InstantiatedModule(this, ififo_m_1);
+            //Module.InstantiatedModule ififo_2 = new Module.InstantiatedModule(this, ififo_m_2);
+            //ififo_1.getOutputPort("out").connect(ififo_2.getInputPort("in"));
+            Module.SinkPort   ififo_in      = ififo_1.getInputPort("in");
+            //Module.SourcePort ififo_out     = ififo_2.getOutputPort("out");
+            Module.SourcePort ififo_out     = ififo_1.getOutputPort("out");
+
+            Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
+            instruction.connect(torpedo_branch.getInputPort("in"));
+            Module.SourcePort efifo_out              = torpedo_branch.getOutputPort("out");
+            Module.SourcePort torpedo_branch_torpedo = torpedo_branch.getOutputPort("torpedo");
+
+            Module.InstantiatedModule fanout_module = new Module.InstantiatedModule(this, new FanoutModule(fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth));
+            Module.SinkPort   fanout_module_in   = fanout_module.getInputPort("in");
+            Module.SourcePort fanout_module_out0 = fanout_module.getOutputPort("out0");
+            Module.SourcePort fanout_module_out1 = fanout_module.getOutputPort("out1");
+
+            Module.InstantiatedModule requeue_module = new Module.InstantiatedModule(this, new RequeueModule());
+            Module.SinkPort   requeue_fabric_in = requeue_module.getInputPort("fabric_in");
+            Module.SinkPort   requeue_ondeck    = requeue_module.getInputPort("ondeck_in");
+            Module.SinkPort   requeue_abort     = requeue_module.getInputPort("abort");
+            Module.SourcePort requeue_out       = requeue_module.getOutputPort("out");
+
+            efifo_out.connect(requeue_fabric_in);
+            requeue_out.connect(ififo_in);
+            ififo_out.connect(fanout_module_in);
+            fanout_module_out0.connect(requeue_ondeck);
+            Module.SourcePort ondeck = fanout_module_out1;
+
+            WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width),
+                                                  new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+
+                                                                  " ? {1'b0, olc} : ilc)-1"));
+            WireValue data_latch_output_p = new WireValue("data_latch_output",
+                                                           inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(),
+                                                           (inbox
+                                                            ? new SimpleValue(data_out.getName())
+                                                            : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
+                                                          );
+
+            Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog());
+            Module.SourcePort  data_latch_input = inbox ? data_in : data_in;
+
+            BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1);
+            bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true);
+            Value magic_standing_value = new ConstantValue(bv);
+
+            Trigger done_executing       = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
+
+            String predicate_met = 
+                "("+
+                "("+
+                "!"+fpga.MOVE.verilog(ondeck.getName())+" || (ilc!=0)"+
+                ") && ("+
+                "("+
+                fpga.P_ALWAYS.verilog(ondeck.getName())+
+                ") || ("+
+                fpga.P_OLC_ZERO.verilog(ondeck.getName())+"==flag_d"+
+                ")"+
+                ") && ("+
+                " " + fpga.P_A.verilog(ondeck.getName())+" ? flag_a"+
+                ":" + fpga.P_B.verilog(ondeck.getName())+" ? flag_b"+
+                ":" + fpga.P_NOT_A.verilog(ondeck.getName())+" ? !flag_a"+
+                ":" + fpga.P_NOT_B.verilog(ondeck.getName())+" ? !flag_b "+
+                ": 1"+
+                ")"+
+                ")";
+
+            requeue_abort.connectValue(new SimpleValue("("+predicate_met+") && "+fpga.ABORT.verilog(ondeck.getName())));
+
+            // Torpedo strikes
+            new Event(new Object[] {
+                    ondeck,
+                    data_out,
+                    token_out,
+                    predicate_met,
+                    fpga.MOVE.verilog(ondeck.getName()),
+                    "!"+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName()),
+                    torpedo_branch_torpedo
+                },
+                new Object[] {
+                    ondeck,
+                    torpedo_branch_torpedo,
+                    new AssignAction(olc,    new ConstantValue(new BitVector(olc.width).set(0))),
+                    new AssignAction(flag_d, new ConstantValue(new BitVector(1).set(1))),
+                    new AssignAction(ilc,    new ConstantValue(new BitVector(ilc.width).set(1)))
+                });
+
+            // Predicate not met
+            new Event(new Object[] { ondeck, "!("+predicate_met+")" },
+                      new Action[] { ondeck,
+                                     new ConditionalAction(ondeck.testMask(fpga.MOVE),
+                                                           new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))))
+                      });
+
+            new Event(new Object[] { ondeck,
+                                     data_out,
+                                     token_out,
+                                     predicate_met,
+                                     "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")",
+                                     new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in),
+                                     new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in)
+                      },
+                      new Action[] { 
+                          new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)),
+                                                new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))),
+                          new ConditionalAction(done_executing, ondeck),
+                          new ConditionalAction(done_executing.invert(),
+                                                new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value),
+                                                                                   magic_standing_value,
+                                                                                   decremented))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
+                                                new AssignAction(olc, new SimpleValue("data_latch_output"))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
+                                                new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
+                                                new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))),
+
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
+                                                new AssignAction(flag_d, new SimpleValue("data_latch_output==0"))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
+                                                new AssignAction(flag_d, new SimpleValue(ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE).getVerilog()+"==0"))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
+                                                new AssignAction(flag_d, new SimpleValue("(olc==0 || olc==1)"))),
+
+                          new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
+                                                new AssignAction(ilc, new SimpleValue("data_latch_output"))),
+
+                          new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE),
+                                                new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY),
+                                                new AssignAction(ilc, magic_standing_value)),
+                          new ConditionalAction(ondeck.testMask(fpga.SHIFT),
+                                                new AssignAction(data_latch,
+                                                                 new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
+                                                                                 ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE),
+                                                new AssignAction(data_latch,
+                                                                 new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
+                                                                                 "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+
+                                                                                 ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
+                                                new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))),
+                          new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
+                                                new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))),
+                          new ConditionalAction(ondeck.testMask(fpga.MOVE),
+                                                new AssignAction(flag_c,
+                                                                 inbox
+                                                                 ? dfifo_out.getBits(dfifo_width-1, dfifo_width-1)
+                                                                 : new MuxValue(ondeck.testMask(fpga.DC),
+                                                                                ship_out.getBits(fpga.getWordWidth(), fpga.getWordWidth()),
+                                                                                dfifo_out.getBits(dfifo_width-1, dfifo_width-1))
+                                                                 )),
+                          new ConditionalAction(ondeck.testMask(fpga.DI),    data_in),
+                          new ConditionalAction(ondeck.testMask(fpga.DO),    data_out),
+                          new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out),
+                          inbox
+                          ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"),
+                                             new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
+                          : null,
+                          new ConditionalAction(ondeck.testMask(fpga.TI),    token_in),
+                          new ConditionalAction(ondeck.testMask(fpga.TO),    token_out),
+                          new ConditionalAction(ondeck.testMask(fpga.DC),   new AssignAction(data_latch, data_latch_input)),
+                          new AssignAction(token_out.getBits(fpga.PACKET_TOKEN),
+                                           new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")),
+                          new ConditionalAction(ondeck.testMask(fpga.PATH_DATA),
+                                                new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
+                                                                                      token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
+                                                                 data_latch_input.getBits(fpga.DISPATCH_PATH))),
+                          new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE),
+                                                new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
+                                                                                      token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
+                                                                 ondeck.getBits(fpga.PATH_IMMEDIATE)))
+                      }
+                );
+        }
+
+        private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) {
+            Value[] vals = new Value[] {
+                new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()),
+                new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c),
+                new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()),
+                new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b),
+                new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()),
+                new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a),
+            };
+            Value ret = new ConstantValue(new BitVector(1).set(0));
+            for(int i=0; i<vals.length; i++)
+                ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);
+            return ret;
+        }
+    }
+}
+
diff --git a/src/edu/berkeley/fleet/fpga/FpgaPath.java b/src/edu/berkeley/fleet/fpga/FpgaPath.java
new file mode 100644 (file)
index 0000000..2bc194a
--- /dev/null
@@ -0,0 +1,82 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+
+public class FpgaPath extends FleetTwoPath {
+
+    private boolean[] path;
+    private FpgaDestination dest;
+    public final BitVector signal;
+
+    public Dock        getSource() { throw new RuntimeException("not implemented"); }
+    public Destination getDestination() { return dest; }
+    
+    private FpgaPath(boolean[] path, FpgaDestination dest, BitVector signal) {
+        this.signal = signal;
+        this.path = path;
+        this.dest = dest;
+    }
+
+    public BitVector toBitVector() {
+        BitVector bv = new BitVector(((Fpga)dest.dock.getShip().getFleet()).PACKET_DEST.getWidth() +
+                                     ((Fpga)dest.dock.getShip().getFleet()).PACKET_SIGNAL.getWidth());
+        bv.set(toLong());
+        return bv;
+    }
+    public long toLong() {
+        long ret = 0;
+        for(int i=0; i<path.length; i++) {
+            if (path[i]) ret |= (1 << i);
+        }
+        if (signal != null)
+            for(int i=0; i<signal.length(); i++) {
+                if (signal.get(i))
+                    ret |= (1L << (i+11));
+            }
+        return ret;
+    }
+
+    public String toString() {
+        StringBuffer ret = new StringBuffer();
+        for(int i=0; i<path.length; i++) {
+            if (i>0) ret.append('_');
+            ret.append(path[i] ? "1" : "0");
+        }
+        return ret.toString()+(signal==null?"":(":"+signal));
+    }
+
+    public FpgaPath prepend(boolean b) {
+        boolean[] newpath = new boolean[path.length+1];
+        System.arraycopy(path, 0, newpath, 1, path.length);
+        newpath[0] = b;
+        return new FpgaPath(newpath, dest, signal);
+    }
+    public FpgaPath append(boolean b, FpgaDestination newdest) {
+        boolean[] newpath = new boolean[path.length+1];
+        System.arraycopy(path, 0, newpath, 0, path.length);
+        newpath[newpath.length-1] = b;
+        return new FpgaPath(newpath, newdest, signal);
+    }
+
+    public int getBufferingAmount() {
+        throw new RuntimeException("not implemented");
+    }
+
+    public int getLatencyMetric() {
+        return 0;
+    }
+
+    public static FpgaPath emptyPath(FpgaDestination dest, BitVector signal) {
+        return new FpgaPath(new boolean[0], dest, signal);
+    }
+
+    public BitVector getSignal() { return signal; }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/FpgaShip.java b/src/edu/berkeley/fleet/fpga/FpgaShip.java
new file mode 100644 (file)
index 0000000..072aae4
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+import java.io.*;
+import edu.berkeley.fleet.two.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+/** a ship, which belongs to a fleet and which may have many ports */
+public class FpgaShip extends FleetTwoShip {
+        
+    private Module module;
+    private Module.InstantiatedModule instance;
+    private LinkedHashMap<String,FpgaDock> ports = new LinkedHashMap<String,FpgaDock>();
+    LinkedHashMap<String,Module.SourcePort> docklessPorts = new LinkedHashMap<String,Module.SourcePort>();
+
+    /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
+    public FpgaShip(Fpga fleet, ShipDescription sd) {
+        super(fleet, sd);
+        this.module = new Module(getType().toLowerCase());
+        this.instance = new Module.InstantiatedModule(fleet.getVerilogModule(), module);
+        for(DockDescription sdbb : sd.ports()) {
+            if (sdbb.isDockless()) {
+                module.createOutputPort(sdbb.getName(), fleet.WIDTH_PACKET);
+                docklessPorts.put(sdbb.getName(), instance.getOutputPort(sdbb.getName()));
+            } else {
+                if (sdbb.isInputDock()) module.createInputPort(sdbb.getName(), getFleet().getWordWidth()+1);
+                else                    module.createOutputPort(sdbb.getName(), getFleet().getWordWidth()+1);
+                ports.put(sdbb.getName(), new FpgaDock(this, sdbb));
+            }
+        }
+        for(PercolatedPort pp : sd.percolatedPorts)
+            this.module.percolatedPorts.add(pp);
+    }
+
+    public Iterator<Dock> iterator() { return (Iterator<Dock>)(Object)ports.values().iterator(); }
+
+    public Module.InstantiatedModule getVerilogModule() { return instance; }
+}
diff --git a/src/edu/berkeley/fleet/fpga/FunnelModule.java b/src/edu/berkeley/fleet/fpga/FunnelModule.java
new file mode 100644 (file)
index 0000000..7593133
--- /dev/null
@@ -0,0 +1,64 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+
+public class FunnelModule extends Module {
+
+    public FunnelModule(Fpga fpga) {
+        super("funnel");
+        Module.SinkPort    outp = createOutputPort("out", fpga.WIDTH_PACKET);
+        Module.SourcePort  in1p = createInputPort("in1", fpga.WIDTH_PACKET);
+        Module.SourcePort  in2p = createInputPort("in2", fpga.WIDTH_PACKET);
+
+        // FIXME: biased towards in2p side
+        new Event(new Object[] { in1p, outp, "!"+in2p.isFull() },
+                  new Action[] { in1p, outp,
+                                 new AssignAction(outp, in1p) });
+        new Event(new Object[] { in2p, outp },
+                  new Action[] { in2p, outp,
+                                 new AssignAction(outp, in2p) });
+    }
+
+    public static class FunnelInstance extends Module.InstantiatedModule implements FabricElement {
+        private FabricElement in1 = null;
+        private FabricElement in2 = null;
+        public FabricElement out = null;
+        public Module.SourcePort getOutputPort() { return getOutputPort("out"); }
+        public Module.Port getInputPort()  { throw new RuntimeException("funnel has multiple inputs"); }
+        public FunnelInstance(Fpga fpga, Module thisModule, Module.SourcePort p1, Module.SourcePort p2) {
+            super(thisModule, new FunnelModule(fpga));
+            if (p1 != null) p1.connect(this.getInputPort("in1"));
+            if (p2 != null) p2.connect(this.getInputPort("in2"));
+        }
+        public FunnelInstance(Fpga fpga, Module thisModule, FabricElement in1, FabricElement in2) {
+            super(thisModule, new FunnelModule(fpga));
+            this.in1 = in1;
+            this.in2 = in2;
+            in1.addOutput(this, this.getInputPort("in1"));
+            in2.addOutput(this, this.getInputPort("in2"));
+        }
+        public void addOutput(FabricElement out, Module.Port outPort) {
+            this.out = out;
+            getOutputPort("out").connect((Module.SinkPort)outPort);
+        }
+        public void addInput(FabricElement in, Module.Port source) {
+            throw new RuntimeException("cannot add inputs to a funnel once constructed");
+        }
+        public int      getPathLength(FpgaDestination dest) { return out.getPathLength(dest)+1; }
+        public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
+            return out.getPath(dest, signal);
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/HornModule.java b/src/edu/berkeley/fleet/fpga/HornModule.java
new file mode 100644 (file)
index 0000000..1b62922
--- /dev/null
@@ -0,0 +1,85 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.fpga.verilog.Verilog.*;
+
+
+public class HornModule extends Module {
+
+    public HornModule(Fpga fpga) {
+        this(fpga.PACKET_DEST.width-1,
+             fpga.PACKET_DEST.valmaskmax,
+             fpga.PACKET_DEST.valmaskmin,
+             0);
+    }
+    private HornModule(int top,
+                       int top_of_addr_field,
+                       int bot_of_addr_field,
+                       int bot) {
+        super("horn");
+        Module.SourcePort in   = createInputPort("in",    top+1);
+        Module.SinkPort   out0 = createOutputPort("out0", top+1);
+        Module.SinkPort   out1 = createOutputPort("out1", top+1);
+        Module.Latch      out  = new Module.Latch("out",  top+1);
+        out0.connectValue(out);
+        out1.connectValue(out);
+        Value shifted_packet =
+            new CatValue(new Value[] {
+                    (top_of_addr_field < top) ? in.getBits(top, top_of_addr_field+1) : null,
+                    //in.getBits(bot_of_addr_field, bot_of_addr_field),
+                    // we drop address bits instead of rotating to help synthesis eliminate unused junk
+                    new ConstantValue(new BitVector(1).set(0)),
+                    in.getBits(top_of_addr_field, bot_of_addr_field+1),
+                    (bot_of_addr_field > 0) ? in.getBits(bot_of_addr_field-1, 0) : null,
+                });
+        new Event(new Object[] { in, out0, out1, in.testBit(bot_of_addr_field, false) },
+                  new Action[] { in, out0, new AssignAction(out, shifted_packet) });
+        new Event(new Object[] { in, out0, out1, in.testBit(bot_of_addr_field, true) },
+                  new Action[] { in, out1, new AssignAction(out, shifted_packet) });
+    }
+
+    public static class HornInstance extends Module.InstantiatedModule implements FabricElement {
+        private FabricElement out0;
+        private FabricElement out1;
+        public void addInput(FabricElement in, Module.Port source) { ((Module.SourcePort)source).connect(getInputPort("in")); }
+        public Module.SourcePort getOutputPort() { throw new RuntimeException("horn has multiple outputs"); }
+        public Module.Port getInputPort()  { return getInputPort("in"); }
+        public HornInstance(Fpga fpga, Module thisModule, FabricElement out0, FabricElement out1) {
+            super(thisModule, new HornModule(fpga));
+            this.out0 = out0;
+            this.out1 = out1;
+            out0.addInput(this, getOutputPort("out0"));
+            out1.addInput(this, getOutputPort("out1"));
+        }
+        public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
+        public int      getPathLength(FpgaDestination dest) {
+            FpgaPath path0 = out0==null ? null : out0.getPath(dest, null);
+            FpgaPath path1 = out1==null ? null : out1.getPath(dest, null);
+            if (path0==null) return out1.getPathLength(dest)+1;
+            if (path1==null) return out0.getPathLength(dest)+1;
+            return Math.min(out1.getPathLength(dest)+1, out0.getPathLength(dest)+1);
+        }
+        public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
+            FpgaPath path0 = out0==null ? null : out0.getPath(dest, signal);
+            FpgaPath path1 = out1==null ? null : out1.getPath(dest, signal);
+            if (path0 != null) path0 = path0.prepend(false);
+            if (path1 != null) path1 = path1.prepend(true);
+            if (path0==null) return path1;
+            if (path1==null) return path0;
+            if (path0.getLatencyMetric() < path1.getLatencyMetric()) return path0;
+            // FIXME: choke if latency metrics equal?
+            // FIXME: determinism of path-search?
+            return path1;
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/Server.java b/src/edu/berkeley/fleet/fpga/Server.java
new file mode 100644 (file)
index 0000000..623da49
--- /dev/null
@@ -0,0 +1,177 @@
+package edu.berkeley.fleet.fpga;
+
+import gnu.io.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.Semaphore;
+
+// FIXME: accept connections, but stall, during programming
+public class Server {
+    static boolean sign = false;
+
+    static long jarFileTime = 0;
+    static long bitFileTime = 0;
+    static {
+        try {
+            jarFileTime = new File("fleet.jar").lastModified();
+            bitFileTime = new File("build/fpga/main.bit").lastModified();
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    public static ServerSocket ss;
+    public static void main(String[] args) throws Exception {
+        System.err.println("programming...");
+        Process proc = Runtime.getRuntime().exec(new String[] {
+                "misc/program.sh",
+                "build/fpga/main.bit"
+            });
+        BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+        String str = null;
+        while((str = br.readLine()) != null) {
+            System.err.println("  " + str);
+        }
+        int ret = proc.waitFor();
+        if (ret != 0) {
+            System.err.println("programming error: " + ret);
+            return;
+        }
+        System.err.println("done programming.");
+        new Thread() {
+            public void run() {
+                try {
+                    while(true) {
+                        Thread.sleep(500);
+                        if (jarFileTime != new File("fleet.jar").lastModified()) {
+                            System.err.println("jarfile modified; exiting...");
+                            System.exit(0);
+                        }
+                        if (bitFileTime != new File("build/fpga/main.bit").lastModified()) {
+                            System.err.println("bitfile modified; exiting...");
+                            System.exit(0);
+                        }
+                    }
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+        }.start();
+        ss = new ServerSocket(3133);
+        while(true) {
+            try {
+                Socket s = ss.accept();
+                System.out.println("accept!");
+                new Handler(s).start();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static String pass_string = "password=security_is_for_wimps ";
+    static class Handler extends Thread {
+        private Socket socket;
+        boolean closed = false;
+        private SerialPort sp;
+        public Handler(Socket s) { this.socket = s; this.sp = sp; }
+        public void run() {
+            System.err.println("waiting for Server.class lock...");
+            synchronized(Server.class) {
+                System.err.println("   (got it)");
+                try {
+                    if (new File("/dev/cu.usbserial-FTCBWI2P").exists())
+                        this.sp = new RXTXPort("/dev/cu.usbserial-FTCBWI2P");
+                    else
+                        this.sp = new RXTXPort("/dev/ttyS0");
+                    sp.setInputBufferSize(0);
+                    sp.setOutputBufferSize(0);
+                    //sp.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+                    sp.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+                    //sp.setFlowControlMode(sp.FLOWCONTROL_RTSCTS_IN | sp.FLOWCONTROL_RTSCTS_OUT);
+                    sp.setFlowControlMode(0);
+                    try {
+                        _run();
+                    } finally {
+                        sp.close();
+                    }
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+        }
+        public void _run() {
+            try {
+                final InputStream is = new BufferedInputStream(socket.getInputStream());
+                final OutputStream os = socket.getOutputStream();
+                final OutputStream fos = sp.getOutputStream();
+                final InputStream fis = new BufferedInputStream(sp.getInputStream());
+
+                sp.sendBreak(100);
+
+                // read login string
+                byte[] buf = new byte[1024];
+                StringBuffer sb = new StringBuffer();
+                while(true) {
+                    int i = is.read();
+                    if (i==-1) return;
+                    if (((char)i)=='\n') break;
+                    sb.append((char)i);
+                }
+                System.err.println("login string: " + sb.toString());
+                if (!sb.toString().startsWith(pass_string)) return;
+
+                System.err.println("sending instructions...");
+                new Thread() {
+                    public void run() {
+                        try {
+                            while(true) {
+                                int r = is.read();
+                                if (r == -1) break;
+                                System.err.println("write: 0x"+Integer.toString(r & 0xff, 16));
+                                synchronized(fos) {
+                                    fos.write(r);
+                                    if (is.available()==0) fos.flush();
+                                }
+                            }
+                            synchronized(fos) {
+                                fos.flush();
+                            }
+                        } catch (Exception e) { throw new RuntimeException(e);
+                        } finally {
+                            System.err.println("closing...");
+                            closed = true;
+                            try { fos.close(); } catch (Throwable t) { t.printStackTrace(); }
+                        }
+                    }
+                }.start();
+
+                System.err.println("reading back...");
+                while(true) {
+                    int val = 0;
+                    for(int i=0; i<6; i++) {
+                        int k = 0;
+                        while (fis.available()==0) {
+                            if (closed) return;
+                            Thread.sleep(10);
+                        }
+                        val = fis.read();
+                        if (val==-1) break;
+                        if ((val & (3<<6)) == 0) {
+                            synchronized(fos) {
+                                fos.write( (1<<6) | 1);
+                            }
+                        }
+                        System.err.println("read: 0x"+Integer.toString(val & 0xff, 16));
+                        os.write((byte)val);
+                    }
+                    if (val==-1) break;
+                }
+                os.flush();
+                System.err.println("done.");
+
+            } catch (Exception e) { throw new RuntimeException(e);
+            } finally {
+                try {
+                    System.err.println("closing...");
+                } catch (Throwable t) { t.printStackTrace(); }
+            }
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/fpga/bram.inc b/src/edu/berkeley/fleet/fpga/bram.inc
new file mode 100644 (file)
index 0000000..f0c8334
--- /dev/null
@@ -0,0 +1,23 @@
+/* bram.inc */
+module `BRAM_NAME(clk, rst, we, a, dpra, di, spo, dpo); 
+    input  clk; 
+    input  rst; 
+    input  we; 
+    input  [(`BRAM_ADDR_WIDTH-1):0] a; 
+    input  [(`BRAM_ADDR_WIDTH-1):0] dpra; 
+    input  [(`BRAM_DATA_WIDTH-1):0] di; 
+    output [(`BRAM_DATA_WIDTH-1):0] spo; 
+    output [(`BRAM_DATA_WIDTH-1):0] dpo; 
+    reg    [(`BRAM_DATA_WIDTH-1):0] ram [((`BRAM_SIZE)-1):0];
+    reg    [(`BRAM_ADDR_WIDTH-1):0] read_a; 
+    reg    [(`BRAM_ADDR_WIDTH-1):0] read_dpra; 
+    always @(posedge clk) begin 
+        if (we) 
+            ram[a] <= di; 
+        read_a <= a; 
+        read_dpra <= dpra; 
+    end
+    assign spo = ram[read_a]; 
+    assign dpo = ram[read_dpra]; 
+endmodule 
+/* bram.inc */
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_chipscope.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_chipscope.v
new file mode 100644 (file)
index 0000000..d1d8ebe
--- /dev/null
@@ -0,0 +1,118 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_chipscope.v
+// /___/   /\     Date Last Modified: $Data$ 
+// \   \  /  \   Date Created: 9/14/06
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Purpose:
+//   Skeleton Chipscope module declarations - for simulation only
+//Reference:
+//Revision History:
+//
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module icon4 
+  (
+      control0,
+      control1,
+      control2,
+      control3
+  )
+  /* synthesis syn_black_box syn_noprune = 1 */;
+  output [35:0] control0;
+  output [35:0] control1;
+  output [35:0] control2;
+  output [35:0] control3;
+endmodule
+
+module vio_async_in192
+  (
+    control,
+    async_in
+  )
+  /* synthesis syn_black_box syn_noprune = 1 */;
+  input  [35:0] control;
+  input  [191:0] async_in;
+endmodule
+
+module vio_async_in96
+  (
+    control,
+    async_in
+  )
+  /* synthesis syn_black_box syn_noprune = 1 */;
+  input  [35:0] control;
+  input  [95:0] async_in;
+endmodule
+
+module vio_async_in100
+  (
+    control,
+    async_in
+  )
+  /* synthesis syn_black_box syn_noprune = 1 */;
+  input  [35:0] control;
+  input  [99:0] async_in;
+endmodule
+
+module vio_sync_out32
+  (
+    control,
+    clk,
+    sync_out
+  )
+  /* synthesis syn_black_box syn_noprune = 1 */;
+  input  [35:0] control;
+  input  clk;
+  output [31:0] sync_out;
+endmodule
\ No newline at end of file
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_ctrl.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_ctrl.v
new file mode 100644 (file)
index 0000000..1160208
--- /dev/null
@@ -0,0 +1,1227 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_ctrl.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/29 15:24:03 $
+// \   \  /  \    Date Created: Wed Aug 30 2006
+//  \___\/\___\
+//
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+//   This module is the main control logic of the memory interface. All
+//   commands are issued from here according to the burst, CAS Latency and the
+//   user commands.
+//Reference:
+//Revision History:
+//   Rev 1.2 - Fixed auto refresh to activate bug. KP 11-19-2007
+//   Rev 1.3 - For Dual Rank parts support CS logic modified. KP. 05/08/08
+//   Rev 1.4 - AUTO_REFRESH_WAIT state modified for Auto Refresh flag asserted
+//             immediately after calibration is completed. KP. 07/28/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_ctrl #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH    = 2,
+   parameter COL_WIDTH     = 10,
+   parameter CS_BITS       = 0,
+   parameter CS_NUM        = 1,
+   parameter ROW_WIDTH     = 14,
+   parameter ADDITIVE_LAT  = 0,
+   parameter BURST_LEN     = 4,
+   parameter CAS_LAT       = 5,
+   parameter ECC_ENABLE    = 0,
+   parameter REG_ENABLE    = 1,
+   parameter TREFI_NS      = 7800,
+   parameter TRAS          = 40000,
+   parameter TRCD          = 15000,
+   parameter TRRD          = 10000,
+   parameter TRFC          = 105000,
+   parameter TRP           = 15000,
+   parameter TRTP          = 7500,
+   parameter TWR           = 15000,
+   parameter TWTR          = 10000,
+   parameter CLK_PERIOD    = 3000,
+   parameter MULTI_BANK_EN = 1,
+   parameter TWO_T_TIME_EN = 0,
+   parameter DDR_TYPE      = 1
+   )
+  (
+   input                   clk,
+   input                   rst,
+   input [2:0]             af_cmd,
+   input [30:0]            af_addr,
+   input                   af_empty,
+   input                   phy_init_done,
+   output                  ctrl_ref_flag,
+   output                  ctrl_af_rden,
+   output reg              ctrl_wren,
+   output reg              ctrl_rden,
+   output [ROW_WIDTH-1:0]  ctrl_addr,
+   output [BANK_WIDTH-1:0] ctrl_ba,
+   output                  ctrl_ras_n,
+   output                  ctrl_cas_n,
+   output                  ctrl_we_n,
+   output [CS_NUM-1:0]     ctrl_cs_n
+   );
+
+  // input address split into various ranges
+  localparam ROW_RANGE_START     = COL_WIDTH;
+  localparam ROW_RANGE_END       = ROW_WIDTH + ROW_RANGE_START - 1;
+  localparam BANK_RANGE_START    = ROW_RANGE_END + 1;
+  localparam BANK_RANGE_END      = BANK_WIDTH + BANK_RANGE_START - 1;
+  localparam CS_RANGE_START      = BANK_RANGE_START + BANK_WIDTH;
+  localparam CS_RANGE_END        = CS_BITS + CS_RANGE_START - 1;
+  // compare address (for determining bank/row hits) split into various ranges
+  // (compare address doesn't include column bits)
+  localparam CMP_WIDTH            = CS_BITS + BANK_WIDTH + ROW_WIDTH;
+  localparam CMP_ROW_RANGE_START  = 0;
+  localparam CMP_ROW_RANGE_END    = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
+  localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
+  localparam CMP_BANK_RANGE_END   = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
+  localparam CMP_CS_RANGE_START   = CMP_BANK_RANGE_END + 1;
+  localparam CMP_CS_RANGE_END     = CS_BITS + CMP_CS_RANGE_START-1;
+
+  localparam BURST_LEN_DIV2      = BURST_LEN / 2;
+  localparam OPEN_BANK_NUM       = 4;
+  localparam CS_BITS_FIX         = (CS_BITS == 0) ? 1 : CS_BITS;
+
+  // calculation counters based on clock cycle and memory parameters
+  // TRAS: ACTIVE->PRECHARGE interval - 2
+  localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD;
+  // TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
+  localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD;
+  localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) >
+                                 ADDITIVE_LAT )?
+             ((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0;
+  // TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
+  localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD;
+  // TRP: PRECHARGE->COMMAND interval - 2
+   // for precharge all add 1 extra clock cycle
+  localparam integer TRP_CYC =  ((TRP + CLK_PERIOD)/CLK_PERIOD) +1;
+  // TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2
+  localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)?
+                                     ((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2;
+  localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT
+                                + BURST_LEN_DIV2 - 2;
+  // TWR: WRITE->PRECHARGE interval - 2
+  localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
+  localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) +
+             WR_LAT + BURST_LEN_DIV2 ;
+  // TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
+  // DDR2 = CL-1 + BL/2 +TWTR
+  localparam integer TWTR_TMP_MIN = (TWTR + CLK_PERIOD)/CLK_PERIOD;
+  localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1)
+                                 + BURST_LEN_DIV2 ): 2;
+
+  //  TRTW: READ->WRITE interval - 3
+  //  DDR1: CL + (BL/2)
+  //  DDR2: (BL/2) + 2. Two more clocks are added to
+  //  the DDR2 counter to account for the delay in
+  //  arrival of the DQS during reads (pcb trace + buffer
+  //  delays + memory parameters).
+  localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 :
+             (CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2;
+
+  localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;
+
+  // Make sure all values >= 0 (some may be = 0)
+  localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
+  localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
+  localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0;
+  localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
+  localparam TRP_COUNT  = (TRP_CYC > 0)  ? TRP_CYC  : 0;
+  localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
+  localparam TWR_COUNT  = (TWR_CYC > 0)  ? TWR_CYC  : 0;
+  localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;
+  localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0;
+
+  // Auto refresh interval
+  localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;
+
+  // memory controller states
+  localparam   CTRL_IDLE                =     5'h00;
+  localparam   CTRL_PRECHARGE           =     5'h01;
+  localparam   CTRL_PRECHARGE_WAIT      =     5'h02;
+  localparam   CTRL_AUTO_REFRESH        =     5'h03;
+  localparam   CTRL_AUTO_REFRESH_WAIT   =     5'h04;
+  localparam   CTRL_ACTIVE              =     5'h05;
+  localparam   CTRL_ACTIVE_WAIT         =     5'h06;
+  localparam   CTRL_BURST_READ          =     5'h07;
+  localparam   CTRL_READ_WAIT           =     5'h08;
+  localparam   CTRL_BURST_WRITE         =     5'h09;
+  localparam   CTRL_WRITE_WAIT          =     5'h0A;
+  localparam   CTRL_PRECHARGE_WAIT1     =     5'h0B;
+
+
+  reg [CMP_WIDTH-1:0]                      act_addr_r;
+  wire [30:0]                              af_addr_r;
+  reg [30:0]                               af_addr_r1;
+  reg [30:0]                               af_addr_r2;
+  reg [30:0]                               af_addr_r3;
+  wire [2:0]                               af_cmd_r;
+  reg [2:0]                                af_cmd_r1;
+  reg [2:0]                                af_cmd_r2;
+  reg                                      af_valid_r;
+  reg                                      af_valid_r1;
+  reg                                      af_valid_r2;
+  reg [CS_BITS_FIX :0]                     auto_cnt_r;
+  reg                                      auto_ref_r;
+  reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0]      bank_cmp_addr_r;
+  reg [OPEN_BANK_NUM-1:0]                  bank_hit;
+  reg [OPEN_BANK_NUM-1:0]                  bank_hit_r;
+  reg [OPEN_BANK_NUM-1:0]                  bank_hit_r1;
+  reg [OPEN_BANK_NUM-1:0]                  bank_valid_r;
+  reg                                      bank_conflict_r;
+  reg                                      conflict_resolved_r;
+  reg                                      ctrl_af_rden_r;
+  reg                                      conflict_detect_r;
+  wire                                     conflict_detect;
+  reg                                      cs_change_r;
+  reg                                      cs_change_sticky_r;
+  reg [ROW_WIDTH-1:0]                      ddr_addr_r;
+  wire [ROW_WIDTH-1:0]                     ddr_addr_col;
+  wire [ROW_WIDTH-1:0]                     ddr_addr_row;
+  reg [BANK_WIDTH-1:0]                     ddr_ba_r;
+  reg                                      ddr_cas_n_r;
+  reg [CS_NUM-1:0]                         ddr_cs_n_r;
+  reg                                      ddr_ras_n_r;
+  reg                                      ddr_we_n_r;
+  reg [4:0]                                next_state;
+  reg                                      no_precharge_wait_r;
+  reg                                      no_precharge_r;
+  reg                                      no_precharge_r1;
+  reg                                      phy_init_done_r;
+  reg [4:0]                                precharge_ok_cnt_r;
+  reg                                      precharge_ok_r;
+  reg [4:0]                                ras_cnt_r;
+  reg [3:0]                                rcd_cnt_r;
+  reg                                      rcd_cnt_ok_r;
+  reg [2:0]                                rdburst_cnt_r;
+  reg                                      rdburst_ok_r;
+  reg                                      rdburst_rden_ok_r;
+  reg                                      rd_af_flag_r;
+  wire                                     rd_flag;
+  reg                                      rd_flag_r;
+  reg [4:0]                                rd_to_wr_cnt_r;
+  reg                                      rd_to_wr_ok_r;
+  reg                                      ref_flag_r;
+  reg [11:0]                               refi_cnt_r;
+  reg                                      refi_cnt_ok_r;
+  reg                                      rst_r
+                                           /* synthesis syn_preserve = 1 */;
+  reg                                      rst_r1
+                                           /* synthesis syn_maxfan = 10 */;
+  reg [7:0]                                rfc_cnt_r;
+  reg                                      rfc_ok_r;
+  reg [3:0]                                row_miss;
+  reg [3:0]                                row_conflict_r;
+  reg [3:0]                                rp_cnt_r;
+  reg                                      rp_cnt_ok_r;
+  reg [CMP_WIDTH-1:0]                      sb_open_add_r;
+  reg [4:0]                                state_r;
+  reg [4:0]                                state_r1;
+  wire                                     sm_rden;
+  reg                                      sm_rden_r;
+  reg [2:0]                                trrd_cnt_r;
+  reg                                      trrd_cnt_ok_r;
+  reg [2:0]                                two_t_enable_r;
+  reg [CS_NUM-1:0]                         two_t_enable_r1;
+  reg [2:0]                                wrburst_cnt_r;
+  reg                                      wrburst_ok_r;
+  reg                                      wrburst_wren_ok_r;
+  wire                                     wr_flag;
+  reg                                      wr_flag_r;
+  reg [4:0]                                wr_to_rd_cnt_r;
+  reg                                      wr_to_rd_ok_r;
+
+  // XST attributes for local reset "tree"
+  // synthesis attribute shreg_extract of rst_r is "no";
+  // synthesis attribute shreg_extract of rst_r1 is "no";
+  // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+  //***************************************************************************
+
+  // sm_rden is used to assert read enable to the address FIFO
+  assign sm_rden = ((state_r == CTRL_BURST_WRITE) ||
+                    (state_r == CTRL_BURST_READ)) ;
+
+  // assert read flag to the adress FIFO
+  assign ctrl_af_rden = sm_rden || rd_af_flag_r;
+
+  // local reset "tree" for controller logic only. Create this to ease timing
+  // on reset path. Prohibit equivalent register removal on RST_R to prevent
+  // "sharing" with other local reset trees (caution: make sure global fanout
+  // limit is set to large enough value, otherwise SLICES may be used for
+  // fanout control on RST_R.
+  always @(posedge clk) begin
+    rst_r  <= rst;
+    rst_r1 <= rst_r;
+  end
+
+  //*****************************************************************
+  // interpret commands from Command/Address FIFO
+  //*****************************************************************
+
+  assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0;
+  assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0;
+
+  always @(posedge clk) begin
+    rd_flag_r <= rd_flag;
+    wr_flag_r <= wr_flag;
+  end
+
+  //////////////////////////////////////////////////
+  // The data from the address FIFO is fetched and
+  // stored in two register stages. The data will be
+  // pulled out of the second register stage whenever
+  // the state machine can handle new data from the
+  // address FIFO.
+
+  // This flag is asserted when there is no
+  // cmd & address in the pipe. When there is
+  // valid cmd & addr from the address FIFO the
+  // af_valid signals will be asserted. This flag will
+  // be set the cycle af_valid_r is de-asserted.
+  always @(posedge clk) begin
+    // for simulation purposes - to force CTRL_AF_RDEN low during reset
+    if (rst_r1)
+      rd_af_flag_r <= 1'd0;
+    else if((ctrl_af_rden_r) ||
+            (rd_af_flag_r && (af_valid_r || af_valid_r1)))
+         rd_af_flag_r <= 1'd0;
+    else if (~af_valid_r1 || ~af_valid_r)
+         rd_af_flag_r <= 1'd1;
+
+  end
+
+  // First register stage for the cmd & add from the FIFO.
+  // The af_valid_r signal gives the status of the data
+  // in this stage. The af_valid_r will be asserted when there
+  // is valid data. This register stage will be updated
+  // 1. read to the FIFO and the FIFO not empty
+  // 2. After write and read states
+  // 3. The valid signal is not asserted in the last stage.
+  always @(posedge clk) begin
+    if (rst_r1)begin
+      af_valid_r <= 1'd0;
+    end else begin
+      if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1
+          || ~af_valid_r2)begin
+        af_valid_r <= ctrl_af_rden_r;
+      end
+    end
+  end
+
+  // The output register in the FIFO is used. The addr
+  // and command are already registered in the FIFO.
+  assign af_addr_r = af_addr;
+  assign af_cmd_r = af_cmd;
+
+  // Second register stage for the cmd & add from the FIFO.
+  // The af_valid_r1 signal gives the status of the data
+  // in this stage. The af_valid_r will be asserted when there
+  // is valid data. This register stage will be updated
+  // 1. read to the FIFO and the FIFO not empty and there
+  // is no valid data on this stage
+  // 2. After write and read states
+  // 3. The valid signal is not asserted in the last stage.
+  always@(posedge clk) begin
+    if (rst_r1)begin
+      af_valid_r1 <= 1'd0;
+      af_addr_r1 <= {31{1'bx}};
+      af_cmd_r1 <= {3{1'bx}};
+    end else if (~af_valid_r1 || sm_rden_r ||
+                  ~af_valid_r2) begin
+      af_valid_r1 <= af_valid_r;
+      af_addr_r1 <= af_addr_r;
+      af_cmd_r1 <= af_cmd_r;
+    end
+  end
+
+  // The state machine uses the address and command in this
+  // register stage. The data is fetched from the second
+  // register stage whenever the state machine can accept new
+  // addr. The conflict flags are also generated based on the
+  // second register stage and updated when the new address
+  // is loaded for the state machine.
+  always@(posedge clk) begin
+    if (rst_r1)begin
+      af_valid_r2 <= 1'd0;
+      af_addr_r2 <= {31{1'bx}};
+      af_cmd_r2 <= {3{1'bx}};
+      bank_hit_r <= {OPEN_BANK_NUM{1'bx}};
+      bank_conflict_r <= 1'bx;
+      row_conflict_r <= 4'bx;
+    end else if(sm_rden || ~af_valid_r2)begin
+      af_valid_r2 <= af_valid_r1;
+      af_addr_r2 <= af_addr_r1;
+      af_cmd_r2 <= af_cmd_r1;
+      if(MULTI_BANK_EN)begin
+        bank_hit_r <= bank_hit;
+        row_conflict_r <= row_miss;
+        bank_conflict_r <= (~(|bank_hit));
+      end else begin
+        bank_hit_r <= {OPEN_BANK_NUM{1'b0}};
+        bank_conflict_r <= 1'd0;
+        row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]
+                              != sb_open_add_r[CMP_WIDTH-1:0]);
+      end
+    end
+  end // always@ (posedge clk)
+
+  //detecting cs change for multi chip select case
+  generate
+    if(CS_NUM > 1) begin: gen_cs_change
+       always @(posedge clk) begin
+          if(sm_rden || ~af_valid_r2)begin
+            cs_change_r <= af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
+                       af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
+            cs_change_sticky_r <=
+             af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
+             af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
+          end else
+            cs_change_r <= 1'd0;
+       end
+    end // block: gen_cs_change
+    else begin: gen_cs_0
+       always @(posedge clk) begin
+          cs_change_r <= 1'd0;
+          cs_change_sticky_r <= 1'd0;
+       end
+    end
+ endgenerate
+
+  assign conflict_detect = (MULTI_BANK_EN) ?
+                           ((|(row_conflict_r[3:0] & bank_hit_r[3:0]))
+                            | bank_conflict_r) & af_valid_r2 :
+                           row_conflict_r[0] & af_valid_r2;
+
+  always @(posedge clk) begin
+    conflict_detect_r <= conflict_detect;
+    sm_rden_r <= sm_rden;
+    af_addr_r3 <= af_addr_r2;
+    ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;
+  end
+
+  // conflict resolved signal. When this signal is asserted
+  // the conflict is resolved. The address to be compared
+  // for the conflict_resolved_r will be stored in act_add_r
+  // when the bank is opened.
+  always @(posedge clk) begin
+   conflict_resolved_r <= (act_addr_r ==
+                           af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);
+    if((state_r == CTRL_ACTIVE))
+      act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
+  end
+
+  //***************************************************************************
+  // Bank management logic
+  // Semi-hardcoded for now for 4 banks
+  // will keep multiple banks open if MULTI_BANK_EN is true.
+  //***************************************************************************
+
+  genvar bank_i;
+  generate // if multiple bank option chosen
+    if(MULTI_BANK_EN) begin: gen_multi_bank_open
+
+      for (bank_i = 0; bank_i < OPEN_BANK_NUM;
+           bank_i = bank_i + 1) begin: gen_bank_hit1
+        // asserted if bank address match + open bank entry is valid
+        always @(*) begin
+          bank_hit[bank_i]
+            = ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
+                                (CMP_WIDTH*bank_i)+ROW_WIDTH] ==
+                af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&
+               bank_valid_r[bank_i]);
+          // asserted if row address match (no check for bank entry valid, rely
+          // on this term to be used in conjunction with BANK_HIT[])
+          row_miss[bank_i]
+            = (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
+                               (CMP_WIDTH*bank_i)] !=
+               af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);
+        end
+      end
+
+      always @(posedge clk) begin
+        no_precharge_wait_r  <= bank_valid_r[3] & bank_conflict_r;
+        bank_hit_r1 <= bank_hit_r;
+      end
+
+      always@(*)
+        no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;
+
+      always@(posedge clk)
+        no_precharge_r1 <= no_precharge_r;
+
+
+      always @(posedge clk) begin
+        // Clear all bank valid bits during AR (i.e. since all banks get
+        // precharged during auto-refresh)
+        if ((state_r1 == CTRL_AUTO_REFRESH)) begin
+          bank_valid_r    <= {(OPEN_BANK_NUM-1){1'b0}};
+          bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'b0}};
+        end else begin
+          if (state_r1 == CTRL_ACTIVE) begin
+            // 00 is always going to have the latest bank and row.
+            bank_cmp_addr_r[CMP_WIDTH-1:0]
+              <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
+            // This indicates the bank was activated
+            bank_valid_r[0] <= 1'b1;
+
+            case ({bank_hit_r1[2:0]})
+              3'b001: begin
+                bank_cmp_addr_r[CMP_WIDTH-1:0]
+                  <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
+                // This indicates the bank was activated
+                bank_valid_r[0] <= 1'b1;
+              end
+              3'b010: begin //(b0->b1)
+                bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+                  <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+                bank_valid_r[1] <= bank_valid_r[0];
+              end
+              3'b100:begin //(b0->b1, b1->b2)
+                bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+                  <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+                bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
+                  <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
+                bank_valid_r[1] <= bank_valid_r[0];
+                bank_valid_r[2] <= bank_valid_r[1];
+              end
+              default: begin //(b0->b1, b1->b2, b2->b3)
+                bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+                  <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+                bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
+                  <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
+                bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
+                  <= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
+                bank_valid_r[1] <= bank_valid_r[0];
+                bank_valid_r[2] <= bank_valid_r[1];
+                bank_valid_r[3] <= bank_valid_r[2];
+              end
+            endcase
+          end
+        end
+      end
+    end else begin: gen_single_bank_open // single bank option
+      always @(posedge clk) begin
+        no_precharge_r       <= 1'd0;
+        no_precharge_r1      <= 1'd0;
+        no_precharge_wait_r  <= 1'd0;
+        if (rst_r1)
+          sb_open_add_r <= {CMP_WIDTH{1'b0}};
+        else if (state_r == CTRL_ACTIVE)
+          sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
+      end
+    end
+  endgenerate
+
+  //***************************************************************************
+  // Timing counters
+  //***************************************************************************
+
+  //*****************************************************************
+  // Write and read enable generation for PHY
+  //*****************************************************************
+
+  // write burst count. Counts from (BL/2 to 1).
+  // Also logic for controller write enable.
+  always @(posedge clk) begin
+    if (state_r == CTRL_BURST_WRITE) begin
+      wrburst_cnt_r <= BURST_LEN_DIV2;
+    end else if (wrburst_cnt_r >= 3'd1)
+      wrburst_cnt_r <= wrburst_cnt_r - 1;
+  end // always @ (posedge clk)
+
+
+  always @(posedge clk) begin
+    if (rst_r1) begin
+      ctrl_wren   <= 1'b0;
+    end else if (state_r == CTRL_BURST_WRITE) begin
+      ctrl_wren   <= 1'b1;
+    end else if (wrburst_wren_ok_r)
+      ctrl_wren   <= 1'b0;
+  end
+
+
+  always @(posedge clk) begin
+    if ((state_r == CTRL_BURST_WRITE)
+        && (BURST_LEN_DIV2 > 2))
+      wrburst_ok_r <= 1'd0;
+    else if ((wrburst_cnt_r <= 3'd3) ||
+             (BURST_LEN_DIV2 <= 2))
+      wrburst_ok_r <= 1'b1;
+  end
+
+  // flag to check when wrburst count has reached
+  // a value of 1. This flag is used in the ctrl_wren
+  // logic
+  always @(posedge clk) begin
+     if(wrburst_cnt_r == 3'd2)
+       wrburst_wren_ok_r <=1'b1;
+     else
+       wrburst_wren_ok_r <= 1'b0;
+  end
+
+
+  // read burst count. Counts from (BL/2 to 1)
+  always @(posedge clk) begin
+   if (state_r == CTRL_BURST_READ) begin
+      rdburst_cnt_r <= BURST_LEN_DIV2;
+    end else if (rdburst_cnt_r >= 3'd1)
+      rdburst_cnt_r <= rdburst_cnt_r - 1;
+  end // always @ (posedge clk)
+
+
+   always @(posedge clk) begin
+    if (rst_r1) begin
+      ctrl_rden   <= 1'b0;
+    end else if (state_r == CTRL_BURST_READ) begin
+      ctrl_rden   <= 1'b1;
+    end else if (rdburst_rden_ok_r)
+      ctrl_rden   <= 1'b0;
+   end
+
+  // the rd_burst_ok_r signal will be asserted one cycle later
+  // in multi chip select cases if the back to back read is to
+  // different chip selects. The cs_changed_sticky_r signal will
+  // be asserted only for multi chip select cases.
+  always @(posedge clk) begin
+    if ((state_r == CTRL_BURST_READ)
+        && (BURST_LEN_DIV2 > 2))
+      rdburst_ok_r <= 1'd0;
+    else if ((rdburst_cnt_r <=( 3'd3 - cs_change_sticky_r)) ||
+             (BURST_LEN_DIV2 <= 2))
+      rdburst_ok_r <= 1'b1;
+  end
+
+  // flag to check when rdburst count has reached
+  // a value of 1. This flag is used in the ctrl_rden
+  // logic
+  always @(posedge clk) begin
+     if (rdburst_cnt_r == 3'd2)
+       rdburst_rden_ok_r <= 1'b1;
+     else
+       rdburst_rden_ok_r <= 1'b0;
+  end
+
+
+  //*****************************************************************
+  // Various delay counters
+  // The counters are checked for value of <= 3 to determine the
+  // if the count values are reached during different commands.
+  // It is checked for 3 because
+  // 1. The counters are loaded during the state when the command
+  //    state is reached (+1)
+  // 2. After the <= 3 condition is reached the sm takes two cycles
+  //    to transition to the new command state (+2)
+  //*****************************************************************
+
+  // tRP count - precharge command period
+  always @(posedge clk) begin
+    if (state_r == CTRL_PRECHARGE)
+      rp_cnt_r <= TRP_COUNT;
+    else if (rp_cnt_r != 4'd0)
+      rp_cnt_r <= rp_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if (state_r == CTRL_PRECHARGE)
+      rp_cnt_ok_r <= 1'd0;
+    else if (rp_cnt_r <= 4'd3)
+      rp_cnt_ok_r <= 1'd1;
+  end
+
+  // tRFC count - refresh-refresh, refresh-active
+  always @(posedge clk) begin
+    if (state_r == CTRL_AUTO_REFRESH)
+      rfc_cnt_r <= TRFC_COUNT;
+    else if (rfc_cnt_r != 8'd0)
+      rfc_cnt_r <= rfc_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if (state_r == CTRL_AUTO_REFRESH)
+      rfc_ok_r <= 1'b0;
+    else if(rfc_cnt_r <= 8'd3)
+      rfc_ok_r <= 1'b1;
+  end
+
+  // tRCD count - active to read/write
+  always @(posedge clk) begin
+    if (state_r == CTRL_ACTIVE)
+      rcd_cnt_r <= TRCD_COUNT;
+    else if (rcd_cnt_r != 4'd0)
+      rcd_cnt_r <= rcd_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if ((state_r == CTRL_ACTIVE)
+        && (TRCD_COUNT > 2))
+      rcd_cnt_ok_r <= 1'd0;
+    else if (rcd_cnt_r <= 4'd3)
+      rcd_cnt_ok_r <= 1;
+  end
+
+  // tRRD count - active to active
+  always @(posedge clk) begin
+    if (state_r == CTRL_ACTIVE)
+      trrd_cnt_r <= TRRD_COUNT;
+    else if (trrd_cnt_r != 3'd0)
+      trrd_cnt_r <= trrd_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if (state_r == CTRL_ACTIVE)
+      trrd_cnt_ok_r <= 1'd0;
+    else if (trrd_cnt_r <= 3'd3)
+      trrd_cnt_ok_r <= 1;
+  end
+
+  // tRAS count - active to precharge
+  always @(posedge clk) begin
+    if (state_r == CTRL_ACTIVE)
+      ras_cnt_r <= TRAS_COUNT;
+    else if (ras_cnt_r != 5'd0)
+      ras_cnt_r <= ras_cnt_r - 1;
+  end
+
+  // counter for write to prcharge
+  // read to precharge and
+  // activate to precharge
+  // precharge_ok_cnt_r is added with trtp count,
+  // there can be cases where the sm can go from
+  // activate to read and the act->pre count time
+  // would not have been satisfied. The rd->pre
+   // time is very less. wr->pre time is almost the
+   // same as act-> pre
+  always @(posedge clk) begin
+    if (state_r == CTRL_BURST_READ) begin
+      // assign only if the cnt is < TRTP_COUNT
+      if (precharge_ok_cnt_r < TRTP_COUNT)
+        precharge_ok_cnt_r <= TRTP_COUNT;
+    end else if (state_r == CTRL_BURST_WRITE)
+      precharge_ok_cnt_r <= TWR_COUNT;
+    else if (state_r == CTRL_ACTIVE)
+      precharge_ok_cnt_r <= TRAS_COUNT;
+    else if (precharge_ok_cnt_r != 5'd0)
+      precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if ((state_r == CTRL_BURST_READ) ||
+        (state_r == CTRL_BURST_WRITE)||
+        (state_r == CTRL_ACTIVE))
+      precharge_ok_r <= 1'd0;
+    else if(precharge_ok_cnt_r <= 5'd3)
+      precharge_ok_r <=1'd1;
+  end
+
+  // write to read counter
+  // write to read includes : write latency + burst time + tWTR
+  always @(posedge clk) begin
+    if (rst_r1)
+      wr_to_rd_cnt_r <= 5'd0;
+    else if (state_r == CTRL_BURST_WRITE)
+      wr_to_rd_cnt_r <= (TWTR_COUNT);
+    else if (wr_to_rd_cnt_r != 5'd0)
+      wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if (state_r == CTRL_BURST_WRITE)
+      wr_to_rd_ok_r <= 1'd0;
+    else if (wr_to_rd_cnt_r <= 5'd3)
+      wr_to_rd_ok_r <= 1'd1;
+  end
+
+  // read to write counter
+  always @(posedge clk) begin
+    if (rst_r1)
+      rd_to_wr_cnt_r <= 5'd0;
+    else if (state_r == CTRL_BURST_READ)
+      rd_to_wr_cnt_r <= (TRTW_COUNT);
+    else if (rd_to_wr_cnt_r != 5'd0)
+      rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;
+  end
+
+  always @(posedge clk) begin
+    if (state_r == CTRL_BURST_READ)
+      rd_to_wr_ok_r <= 1'b0;
+    else if (rd_to_wr_cnt_r <= 5'd3)
+      rd_to_wr_ok_r <= 1'b1;
+  end
+
+  always @(posedge clk) begin
+     if(refi_cnt_r == (TREFI_COUNT -1))
+       refi_cnt_ok_r <= 1'b1;
+     else
+       refi_cnt_ok_r <= 1'b0;
+  end
+
+  // auto refresh interval counter in refresh_clk domain
+  always @(posedge clk) begin
+    if ((rst_r1) || (refi_cnt_ok_r))  begin
+      refi_cnt_r <= 12'd0;
+    end else begin
+      refi_cnt_r <= refi_cnt_r + 1;
+    end
+  end // always @ (posedge clk)
+
+  // auto refresh flag
+  always @(posedge clk) begin
+    if (refi_cnt_ok_r) begin
+      ref_flag_r <= 1'b1;
+    end else begin
+      ref_flag_r <= 1'b0;
+    end
+  end // always @ (posedge clk)
+
+  assign ctrl_ref_flag = ref_flag_r;
+
+  //refresh flag detect
+  //auto_ref high indicates auto_refresh requirement
+  //auto_ref is held high until auto refresh command is issued.
+  always @(posedge clk)begin
+    if (rst_r1)
+      auto_ref_r <= 1'b0;
+    else if (ref_flag_r)
+      auto_ref_r <= 1'b1;
+    else if (state_r == CTRL_AUTO_REFRESH)
+      auto_ref_r <= 1'b0;
+  end
+
+
+  // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
+  // all CS's at once to avoid current spike)
+  always @(posedge clk)begin
+    if (rst_r1 || (state_r1 == CTRL_PRECHARGE))
+      auto_cnt_r <= 'd0;
+    else if (state_r1 == CTRL_AUTO_REFRESH)
+      auto_cnt_r <= auto_cnt_r + 1;
+  end
+
+  // register for timing purposes. Extra delay doesn't really matter
+  always @(posedge clk)
+    phy_init_done_r <= phy_init_done;
+
+  always @(posedge clk)begin
+    if (rst_r1) begin
+      state_r    <= CTRL_IDLE;
+      state_r1 <= CTRL_IDLE;
+    end else begin
+      state_r    <= next_state;
+      state_r1 <= state_r;
+    end
+  end
+
+  //***************************************************************************
+  // main control state machine
+  //***************************************************************************
+
+  always @(*) begin
+    next_state = state_r;
+    (* full_case, parallel_case *) case (state_r)
+      CTRL_IDLE: begin
+        // perform auto refresh as soon as we are done with calibration.
+        // The calibration logic does not do any refreshes.
+        if (phy_init_done_r)
+          next_state = CTRL_AUTO_REFRESH;
+      end
+
+      CTRL_PRECHARGE: begin
+        if (auto_ref_r)
+          next_state = CTRL_PRECHARGE_WAIT1;
+        // when precharging an LRU bank, do not have to go to wait state
+        // since we can't possibly be activating row in same bank next
+        // disabled for 2t timing. There needs to be a gap between cmds
+        // in 2t timing
+        else if (no_precharge_wait_r && !TWO_T_TIME_EN)
+          next_state = CTRL_ACTIVE;
+        else
+          next_state = CTRL_PRECHARGE_WAIT;
+      end
+
+      CTRL_PRECHARGE_WAIT:begin
+        if (rp_cnt_ok_r)begin
+          if (auto_ref_r)
+            // precharge again to make sure we close all the banks
+            next_state = CTRL_PRECHARGE;
+          else
+            next_state = CTRL_ACTIVE;
+        end
+      end
+
+      CTRL_PRECHARGE_WAIT1:
+        if (rp_cnt_ok_r)
+          next_state = CTRL_AUTO_REFRESH;
+
+      CTRL_AUTO_REFRESH:
+        next_state = CTRL_AUTO_REFRESH_WAIT;
+
+      CTRL_AUTO_REFRESH_WAIT:
+      //staggering Auto refresh for multi
+      // chip select designs. The SM waits
+      // for the rfc time before issuing the
+      // next auto refresh.
+        if (auto_cnt_r < (CS_NUM))begin
+           if (rfc_ok_r )
+              next_state = CTRL_AUTO_REFRESH;
+           end else if (rfc_ok_r)begin
+              if(auto_ref_r)
+                // MIG 2.3: For deep designs if Auto Refresh
+                // flag asserted immediately after calibration is completed
+                next_state = CTRL_PRECHARGE;
+              else if  ( wr_flag || rd_flag)
+                next_state = CTRL_ACTIVE;
+            end
+
+      CTRL_ACTIVE:
+        next_state = CTRL_ACTIVE_WAIT;
+
+      CTRL_ACTIVE_WAIT: begin
+        if (rcd_cnt_ok_r) begin
+          if ((conflict_detect_r && ~conflict_resolved_r) ||
+              auto_ref_r) begin
+            if (no_precharge_r1 && ~auto_ref_r && trrd_cnt_ok_r)
+              next_state = CTRL_ACTIVE;
+            else  if(precharge_ok_r)
+              next_state = CTRL_PRECHARGE;
+          end else if ((wr_flag_r) && (rd_to_wr_ok_r))
+            next_state = CTRL_BURST_WRITE;
+          else if ((rd_flag_r)&& (wr_to_rd_ok_r))
+            next_state = CTRL_BURST_READ;
+        end
+      end
+
+      // beginning of write burst
+      CTRL_BURST_WRITE: begin
+        if (BURST_LEN_DIV2 == 1) begin
+          // special case if BL = 2 (i.e. burst lasts only one clk cycle)
+          if (wr_flag)
+            // if we have another non-conflict write command right after the
+            // current write, then stay in this state
+            next_state = CTRL_BURST_WRITE;
+          else
+            // otherwise, if we're done with this burst, and have no write
+            // immediately scheduled after this one, wait until write-read
+            // delay has passed
+            next_state = CTRL_WRITE_WAIT;
+        end else
+          // otherwise BL > 2, and we  have at least one more write cycle for
+          // current burst
+          next_state = CTRL_WRITE_WAIT;
+        // continuation of write burst (also covers waiting after write burst
+        // has completed for write-read delay to pass)
+      end
+
+      CTRL_WRITE_WAIT: begin
+        if ((conflict_detect) || auto_ref_r) begin
+          if (no_precharge_r && ~auto_ref_r && wrburst_ok_r)
+            next_state = CTRL_ACTIVE;
+          else if (precharge_ok_r)
+            next_state = CTRL_PRECHARGE;
+        end else if (wrburst_ok_r && wr_flag)
+          next_state = CTRL_BURST_WRITE;
+        else if ((rd_flag) && (wr_to_rd_ok_r))
+          next_state = CTRL_BURST_READ;
+      end
+
+      CTRL_BURST_READ: begin
+        if (BURST_LEN_DIV2 == 1) begin
+          // special case if BL = 2 (i.e. burst lasts only one clk cycle)
+          if (rd_flag)
+            next_state = CTRL_BURST_READ;
+          else
+            next_state = CTRL_READ_WAIT;
+        end else
+          next_state = CTRL_READ_WAIT;
+      end
+
+      CTRL_READ_WAIT: begin
+        if ((conflict_detect) || auto_ref_r)begin
+          if (no_precharge_r && ~auto_ref_r && rdburst_ok_r)
+            next_state = CTRL_ACTIVE;
+          else if (precharge_ok_r)
+            next_state = CTRL_PRECHARGE;
+        // for burst of 4 in multi chip select
+        // if there is a change in cs wait one cycle before the
+        // next read command. cs_change_r will be asserted.
+        end else if (rdburst_ok_r  && rd_flag && ~cs_change_r)
+          next_state = CTRL_BURST_READ;
+        else if (wr_flag && (rd_to_wr_ok_r))
+          next_state = CTRL_BURST_WRITE;
+      end
+    endcase
+  end
+
+  //***************************************************************************
+  // control signals to memory
+  //***************************************************************************
+
+  always @(posedge clk) begin
+     if ((state_r == CTRL_AUTO_REFRESH) ||
+         (state_r == CTRL_ACTIVE) ||
+         (state_r == CTRL_PRECHARGE)) begin
+       ddr_ras_n_r <= 1'b0;
+       two_t_enable_r[0] <= 1'b0;
+     end else begin
+       if (TWO_T_TIME_EN)
+         ddr_ras_n_r <= two_t_enable_r[0] ;
+       else
+         ddr_ras_n_r <= 1'd1;
+       two_t_enable_r[0] <= 1'b1;
+     end
+  end
+
+  always @(posedge clk)begin
+    if ((state_r == CTRL_BURST_WRITE) ||
+        (state_r == CTRL_BURST_READ) ||
+        (state_r == CTRL_AUTO_REFRESH)) begin
+      ddr_cas_n_r <= 1'b0;
+      two_t_enable_r[1] <= 1'b0;
+    end else begin
+      if (TWO_T_TIME_EN)
+        ddr_cas_n_r <= two_t_enable_r[1];
+      else
+        ddr_cas_n_r <= 1'b1;
+      two_t_enable_r[1] <= 1'b1;
+    end
+  end
+
+  always @(posedge clk) begin
+    if ((state_r == CTRL_BURST_WRITE) ||
+        (state_r == CTRL_PRECHARGE)) begin
+      ddr_we_n_r <= 1'b0;
+      two_t_enable_r[2] <= 1'b0;
+    end else begin
+      if(TWO_T_TIME_EN)
+        ddr_we_n_r <= two_t_enable_r[2];
+      else
+        ddr_we_n_r <= 1'b1;
+      two_t_enable_r[2] <= 1'b1;
+    end
+  end
+
+  // turn off auto-precharge when issuing commands (A10 = 0)
+  // mapping the col add for linear addressing.
+  generate
+    if (TWO_T_TIME_EN) begin: gen_addr_col_two_t
+      if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
+        assign ddr_addr_col = {af_addr_r3[COL_WIDTH-1:10], 1'b0,
+                               af_addr_r3[9:0]};
+      end else begin
+        if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
+          assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
+                                 af_addr_r3[COL_WIDTH-1:10], 1'b0,
+                                 af_addr_r3[9:0]};
+        end else begin: gen_ddr_addr_col_2
+          assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
+                               af_addr_r3[COL_WIDTH-1:0]};
+        end
+      end
+    end else begin: gen_addr_col_one_t
+      if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0_1
+        assign ddr_addr_col = {af_addr_r2[COL_WIDTH-1:10], 1'b0,
+                               af_addr_r2[9:0]};
+      end else begin
+        if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1_1
+          assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
+                                 af_addr_r2[COL_WIDTH-1:10], 1'b0,
+                                 af_addr_r2[9:0]};
+        end else begin: gen_ddr_addr_col_2_1
+          assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
+                                 af_addr_r2[COL_WIDTH-1:0]};
+        end
+      end
+    end
+  endgenerate
+
+  // Assign address during row activate
+  generate
+    if (TWO_T_TIME_EN)
+      assign ddr_addr_row = af_addr_r3[ROW_RANGE_END:ROW_RANGE_START];
+    else
+      assign ddr_addr_row = af_addr_r2[ROW_RANGE_END:ROW_RANGE_START];
+  endgenerate
+
+
+  always @(posedge clk)begin
+    if ((state_r == CTRL_ACTIVE) ||
+        ((state_r1 == CTRL_ACTIVE) && TWO_T_TIME_EN))
+      ddr_addr_r <= ddr_addr_row;
+    else if ((state_r == CTRL_BURST_WRITE) ||
+             (state_r == CTRL_BURST_READ)  ||
+             (((state_r1 == CTRL_BURST_WRITE) ||
+               (state_r1 == CTRL_BURST_READ)) &&
+              TWO_T_TIME_EN))
+      ddr_addr_r <= ddr_addr_col;
+    else if (((state_r == CTRL_PRECHARGE)  ||
+              ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
+             && auto_ref_r) begin
+      // if we're precharging as a result of AUTO-REFRESH, precharge all banks
+      ddr_addr_r <= {ROW_WIDTH{1'b0}};
+      ddr_addr_r[10] <= 1'b1;
+    end else if ((state_r == CTRL_PRECHARGE) ||
+                 ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
+      // if we're precharging to close a specific bank/row, set A10=0
+      ddr_addr_r <= {ROW_WIDTH{1'b0}};
+    else
+      ddr_addr_r <= {ROW_WIDTH{1'bx}};
+  end
+
+  always @(posedge clk)begin
+    // whenever we're precharging, we're either: (1) precharging all banks (in
+    // which case banks bits are don't care, (2) precharging the LRU bank,
+    // b/c we've exceeded the limit of # of banks open (need to close the LRU
+    // bank to make room for a new one), (3) we haven't exceed the maximum #
+    // of banks open, but we trying to open a different row in a bank that's
+    // already open
+    if (((state_r == CTRL_PRECHARGE)  ||
+         ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN)) &&
+        bank_conflict_r && MULTI_BANK_EN)
+      // When LRU bank needs to be closed
+      ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
+                                  (3*CMP_WIDTH)+CMP_BANK_RANGE_START];
+    else begin
+      // Either precharge due to refresh or bank hit case
+      if (TWO_T_TIME_EN)
+        ddr_ba_r <= af_addr_r3[BANK_RANGE_END:BANK_RANGE_START];
+      else
+        ddr_ba_r <= af_addr_r2[BANK_RANGE_END:BANK_RANGE_START];
+    end
+  end
+
+  // chip enable generation logic
+  generate
+    // if only one chip select, always assert it after reset
+    if (CS_BITS == 0) begin: gen_ddr_cs_0
+      always @(posedge clk)
+        if (rst_r1)
+          ddr_cs_n_r[0] <= 1'b1;
+        else
+          ddr_cs_n_r[0] <= 1'b0;
+    // otherwise if we have multiple chip selects
+      end else begin: gen_ddr_cs_1
+      if(TWO_T_TIME_EN) begin: gen_2t_cs
+         always @(posedge clk)
+           if (rst_r1)
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+           else if ((state_r1 == CTRL_AUTO_REFRESH)) begin
+             // if auto-refreshing, only auto-refresh one CS at any time (avoid
+             // beating on the ground plane by refreshing all CS's at same time)
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+             ddr_cs_n_r[auto_cnt_r] <= 1'b0;
+           end else if (auto_ref_r && (state_r1 == CTRL_PRECHARGE)) begin
+             ddr_cs_n_r <= {CS_NUM{1'b0}};
+           end else if ((state_r1 == CTRL_PRECHARGE) && ( bank_conflict_r
+                    && MULTI_BANK_EN))begin
+                  // precharging the LRU bank
+                  ddr_cs_n_r <= {CS_NUM{1'b1}};
+                  ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
+                  (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
+           end else begin
+          // otherwise, check the upper address bits to see which CS to assert
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+             ddr_cs_n_r[af_addr_r3[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
+           end // else: !if(((state_r == CTRL_PRECHARGE)  ||...
+        end else begin: gen_1t_cs // block: gen_2t_cs
+         always @(posedge clk)
+           if (rst_r1)
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+           else if ((state_r == CTRL_AUTO_REFRESH) ) begin
+             // if auto-refreshing, only auto-refresh one CS at any time (avoid
+             // beating on the ground plane by refreshing all CS's at same time)
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+             ddr_cs_n_r[auto_cnt_r] <= 1'b0;
+           end else if (auto_ref_r && (state_r == CTRL_PRECHARGE) ) begin
+             ddr_cs_n_r <= {CS_NUM{1'b0}};
+           end else if ((state_r == CTRL_PRECHARGE)  &&
+                 (bank_conflict_r && MULTI_BANK_EN))begin
+                  // precharging the LRU bank
+                  ddr_cs_n_r <= {CS_NUM{1'b1}};
+                  ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
+                  (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
+           end else begin
+          // otherwise, check the upper address bits to see which CS to assert
+             ddr_cs_n_r <= {CS_NUM{1'b1}};
+             ddr_cs_n_r[af_addr_r2[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
+           end // else: !if(((state_r == CTRL_PRECHARGE)  ||...
+        end // block: gen_1t_cs
+    end
+  endgenerate
+
+  // registring the two_t timing enable signal.
+  // This signal will be asserted (low) when the
+  // chip select has to be asserted.
+  always @(posedge clk)begin
+     if(&two_t_enable_r)
+        two_t_enable_r1 <= {CS_NUM{1'b1}};
+     else
+        two_t_enable_r1 <= {CS_NUM{1'b0}};
+  end
+
+  assign ctrl_addr  = ddr_addr_r;
+  assign ctrl_ba    = ddr_ba_r;
+  assign ctrl_ras_n = ddr_ras_n_r;
+  assign ctrl_cas_n = ddr_cas_n_r;
+  assign ctrl_we_n  = ddr_we_n_r;
+  assign ctrl_cs_n  = (TWO_T_TIME_EN) ?
+                      (ddr_cs_n_r | two_t_enable_r1) :
+                      ddr_cs_n_r;
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_idelay_ctrl.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_idelay_ctrl.v
new file mode 100644 (file)
index 0000000..5742feb
--- /dev/null
@@ -0,0 +1,97 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_idelay_ctrl.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/08 15:20:47 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module instantiates the IDELAYCTRL primitive of the Virtex-5 device
+//   which continuously calibrates the IDELAY elements in the region in case of
+//   varying operating conditions. It takes a 200MHz clock as an input
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_idelay_ctrl #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter IDELAYCTRL_NUM  = 4
+   )
+
+  (
+   input  clk200,
+   input  rst200,
+   output idelay_ctrl_rdy
+   );
+
+wire [IDELAYCTRL_NUM-1 : 0] idelay_ctrl_rdy_i;
+
+genvar bnk_i;
+generate
+for(bnk_i=0; bnk_i<IDELAYCTRL_NUM; bnk_i=bnk_i+1)begin : IDELAYCTRL_INST
+IDELAYCTRL u_idelayctrl
+  (
+   .RDY(idelay_ctrl_rdy_i[bnk_i]),
+   .REFCLK(clk200),
+   .RST(rst200)
+   );
+end
+endgenerate
+
+assign idelay_ctrl_rdy = &idelay_ctrl_rdy_i;
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_infrastructure.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_infrastructure.v
new file mode 100644 (file)
index 0000000..50117ac
--- /dev/null
@@ -0,0 +1,156 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_infrastructure.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/08 15:20:47 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   Clock distribution and reset synchronization
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_infrastructure #
+  (
+   parameter RST_ACT_LOW  = 1
+   )
+  (
+   input clk0,
+   input clk90,
+   input clk200,
+   input clkdiv0,
+   input dcm_lock,
+   input  sys_rst_n,
+   input  idelay_ctrl_rdy,
+   output rst0,
+   output rst90,
+   output rst200,
+   output rstdiv0
+   );
+
+  // # of clock cycles to delay deassertion of reset. Needs to be a fairly
+  // high number not so much for metastability protection, but to give time
+  // for reset (i.e. stable clock cycles) to propagate through all state
+  // machines and to all control signals (i.e. not all control signals have
+  // resets, instead they rely on base state logic being reset, and the effect
+  // of that reset propagating through the logic). Need this because we may not
+  // be getting stable clock cycles while reset asserted (i.e. since reset
+  // depends on DCM lock status)
+  localparam RST_SYNC_NUM = 25;
+
+  reg [RST_SYNC_NUM-1:0]     rst0_sync_r    /* synthesis syn_maxfan = 10 */;
+  reg [RST_SYNC_NUM-1:0]     rst200_sync_r  /* synthesis syn_maxfan = 10 */;
+  reg [RST_SYNC_NUM-1:0]     rst90_sync_r   /* synthesis syn_maxfan = 10 */;
+  reg [(RST_SYNC_NUM/2)-1:0] rstdiv0_sync_r /* synthesis syn_maxfan = 10 */;
+  wire                       rst_tmp;
+  wire                       sys_clk_ibufg;
+  wire                       sys_rst;
+
+  assign sys_rst = RST_ACT_LOW ? ~sys_rst_n: sys_rst_n;
+
+
+
+  //***************************************************************************
+  // Reset synchronization
+  // NOTES:
+  //   1. shut down the whole operation if the DCM hasn't yet locked (and by
+  //      inference, this means that external SYS_RST_IN has been asserted -
+  //      DCM deasserts DCM_LOCK as soon as SYS_RST_IN asserted)
+  //   2. In the case of all resets except rst200, also assert reset if the
+  //      IDELAY master controller is not yet ready
+  //   3. asynchronously assert reset. This was we can assert reset even if
+  //      there is no clock (needed for things like 3-stating output buffers).
+  //      reset deassertion is synchronous.
+  //***************************************************************************
+
+  assign rst_tmp = sys_rst | ~dcm_lock | ~idelay_ctrl_rdy;
+
+  // synthesis attribute max_fanout of rst0_sync_r is 10
+  always @(posedge clk0 or posedge rst_tmp)
+    if (rst_tmp)
+      rst0_sync_r <= {RST_SYNC_NUM{1'b1}};
+    else
+      // logical left shift by one (pads with 0)
+      rst0_sync_r <= rst0_sync_r << 1;
+
+  // synthesis attribute max_fanout of rstdiv0_sync_r is 10
+  always @(posedge clkdiv0 or posedge rst_tmp)
+    if (rst_tmp)
+      rstdiv0_sync_r <= {(RST_SYNC_NUM/2){1'b1}};
+    else
+      // logical left shift by one (pads with 0)
+      rstdiv0_sync_r <= rstdiv0_sync_r << 1;
+
+  // synthesis attribute max_fanout of rst90_sync_r is 10
+  always @(posedge clk90 or posedge rst_tmp)
+    if (rst_tmp)
+      rst90_sync_r <= {RST_SYNC_NUM{1'b1}};
+    else
+      rst90_sync_r <= rst90_sync_r << 1;
+
+  // make sure CLK200 doesn't depend on IDELAY_CTRL_RDY, else chicken n' egg
+   // synthesis attribute max_fanout of rst200_sync_r is 10
+  always @(posedge clk200 or negedge dcm_lock)
+    if (!dcm_lock)
+      rst200_sync_r <= {RST_SYNC_NUM{1'b1}};
+    else
+      rst200_sync_r <= rst200_sync_r << 1;
+
+
+  assign rst0    = rst0_sync_r[RST_SYNC_NUM-1];
+  assign rst90   = rst90_sync_r[RST_SYNC_NUM-1];
+  assign rst200  = rst200_sync_r[RST_SYNC_NUM-1];
+  assign rstdiv0 = rstdiv0_sync_r[(RST_SYNC_NUM/2)-1];
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_mem_if_top.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_mem_if_top.v
new file mode 100644 (file)
index 0000000..ad30553
--- /dev/null
@@ -0,0 +1,379 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_mem_if_top.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/22 15:41:06 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+//   Top-level for parameterizable (DDR or DDR2) memory interface
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_mem_if_top #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH            = 2,
+   parameter CKE_WIDTH             = 1,
+   parameter CLK_WIDTH             = 1,
+   parameter COL_WIDTH             = 10,
+   parameter CS_BITS               = 0,
+   parameter CS_NUM                = 1,
+   parameter CS_WIDTH              = 1,
+   parameter USE_DM_PORT           = 1,
+   parameter DM_WIDTH              = 9,
+   parameter DQ_WIDTH              = 72,
+   parameter DQ_BITS               = 7,
+   parameter DQ_PER_DQS            = 8,
+   parameter DQS_BITS              = 4,
+   parameter DQS_WIDTH             = 9,
+   parameter HIGH_PERFORMANCE_MODE = "TRUE",
+   parameter ODT_WIDTH             = 1,
+   parameter ROW_WIDTH             = 14,
+   parameter APPDATA_WIDTH         = 144,
+   parameter ADDITIVE_LAT          = 0,
+   parameter BURST_LEN             = 4,
+   parameter BURST_TYPE            = 0,
+   parameter CAS_LAT               = 5,
+   parameter ECC_ENABLE            = 0,
+   parameter MULTI_BANK_EN         = 1,
+   parameter TWO_T_TIME_EN         = 0,
+   parameter ODT_TYPE              = 1,
+   parameter DDR_TYPE              = 1,
+   parameter REDUCE_DRV            = 0,
+   parameter REG_ENABLE            = 1,
+   parameter TREFI_NS              = 7800,
+   parameter TRAS                  = 40000,
+   parameter TRCD                  = 15000,
+   parameter TRFC                  = 105000,
+   parameter TRP                   = 15000,
+   parameter TRTP                  = 7500,
+   parameter TWR                   = 15000,
+   parameter TWTR                  = 10000,
+   parameter CLK_PERIOD            = 3000,
+   parameter SIM_ONLY              = 0,
+   parameter DEBUG_EN              = 0,
+   parameter DQS_IO_COL            = 0,
+   parameter DQ_IO_MS              = 0
+   )
+  (
+   input                                    clk0,
+   input                                    clk90,
+   input                                    clkdiv0,
+   input                                    rst0,
+   input                                    rst90,
+   input                                    rstdiv0,
+   input [2:0]                              app_af_cmd,
+   input [30:0]                             app_af_addr,
+   input                                    app_af_wren,
+   input                                    app_wdf_wren,
+   input [APPDATA_WIDTH-1:0]                app_wdf_data,
+   input [(APPDATA_WIDTH/8)-1:0]            app_wdf_mask_data,
+   output [1:0]                             rd_ecc_error,
+   output                                   app_af_afull,
+   output                                   app_wdf_afull,
+   output                                   rd_data_valid,
+   output [APPDATA_WIDTH-1:0]               rd_data_fifo_out,
+   output                                   phy_init_done,
+   output [CLK_WIDTH-1:0]                   ddr_ck,
+   output [CLK_WIDTH-1:0]                   ddr_ck_n,
+   output [ROW_WIDTH-1:0]                   ddr_addr,
+   output [BANK_WIDTH-1:0]                  ddr_ba,
+   output                                   ddr_ras_n,
+   output                                   ddr_cas_n,
+   output                                   ddr_we_n,
+   output [CS_WIDTH-1:0]                    ddr_cs_n,
+   output [CKE_WIDTH-1:0]                   ddr_cke,
+   output [ODT_WIDTH-1:0]                   ddr_odt,
+   output [DM_WIDTH-1:0]                    ddr_dm,
+   inout [DQS_WIDTH-1:0]                    ddr_dqs,
+   inout [DQS_WIDTH-1:0]                    ddr_dqs_n,
+   inout [DQ_WIDTH-1:0]                     ddr_dq,
+   // Debug signals (optional use)
+   input                                    dbg_idel_up_all,
+   input                                    dbg_idel_down_all,
+   input                                    dbg_idel_up_dq,
+   input                                    dbg_idel_down_dq,
+   input                                    dbg_idel_up_dqs,
+   input                                    dbg_idel_down_dqs,
+   input                                    dbg_idel_up_gate,
+   input                                    dbg_idel_down_gate,
+   input [DQ_BITS-1:0]                      dbg_sel_idel_dq,
+   input                                    dbg_sel_all_idel_dq,
+   input [DQS_BITS:0]                       dbg_sel_idel_dqs,
+   input                                    dbg_sel_all_idel_dqs,
+   input [DQS_BITS:0]                       dbg_sel_idel_gate,
+   input                                    dbg_sel_all_idel_gate,
+   output [3:0]                             dbg_calib_done,
+   output [3:0]                             dbg_calib_err,
+   output [(6*DQ_WIDTH)-1:0]                dbg_calib_dq_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]               dbg_calib_dqs_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]               dbg_calib_gate_tap_cnt,
+   output [DQS_WIDTH-1:0]                   dbg_calib_rd_data_sel,
+   output [(5*DQS_WIDTH)-1:0]               dbg_calib_rden_dly,
+   output [(5*DQS_WIDTH)-1:0]               dbg_calib_gate_dly
+   );
+
+  wire [30:0]                       af_addr;
+  wire [2:0]                        af_cmd;
+  wire                              af_empty;
+  wire [ROW_WIDTH-1:0]              ctrl_addr;
+  wire                              ctrl_af_rden;
+  wire [BANK_WIDTH-1:0]             ctrl_ba;
+  wire                              ctrl_cas_n;
+  wire [CS_NUM-1:0]                 ctrl_cs_n;
+  wire                              ctrl_ras_n;
+  wire                              ctrl_rden;
+  wire                              ctrl_ref_flag;
+  wire                              ctrl_we_n;
+  wire                              ctrl_wren;
+  wire [DQS_WIDTH-1:0]              phy_calib_rden;
+  wire [DQS_WIDTH-1:0]              phy_calib_rden_sel;
+  wire [DQ_WIDTH-1:0]               rd_data_fall;
+  wire [DQ_WIDTH-1:0]               rd_data_rise;
+  wire [(2*DQ_WIDTH)-1:0]           wdf_data;
+  wire [((2*DQ_WIDTH)/8)-1:0]       wdf_mask_data;
+  wire                              wdf_rden;
+
+  //***************************************************************************
+
+  ddr2_phy_top #
+    (
+     .BANK_WIDTH            (BANK_WIDTH),
+     .CKE_WIDTH             (CKE_WIDTH),
+     .CLK_WIDTH             (CLK_WIDTH),
+     .COL_WIDTH             (COL_WIDTH),
+     .CS_NUM                (CS_NUM),
+     .CS_WIDTH              (CS_WIDTH),
+     .USE_DM_PORT           (USE_DM_PORT),
+     .DM_WIDTH              (DM_WIDTH),
+     .DQ_WIDTH              (DQ_WIDTH),
+     .DQ_BITS               (DQ_BITS),
+     .DQ_PER_DQS            (DQ_PER_DQS),
+     .DQS_BITS              (DQS_BITS),
+     .DQS_WIDTH             (DQS_WIDTH),
+     .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+     .ODT_WIDTH             (ODT_WIDTH),
+     .ROW_WIDTH             (ROW_WIDTH),
+     .TWO_T_TIME_EN         (TWO_T_TIME_EN),
+     .ADDITIVE_LAT          (ADDITIVE_LAT),
+     .BURST_LEN             (BURST_LEN),
+     .BURST_TYPE            (BURST_TYPE),
+     .CAS_LAT               (CAS_LAT),
+     .ECC_ENABLE            (ECC_ENABLE),
+     .ODT_TYPE              (ODT_TYPE),
+     .DDR_TYPE              (DDR_TYPE),
+     .REDUCE_DRV            (REDUCE_DRV),
+     .REG_ENABLE            (REG_ENABLE),
+     .TWR                   (TWR),
+     .CLK_PERIOD            (CLK_PERIOD),
+     .SIM_ONLY              (SIM_ONLY),
+     .DEBUG_EN              (DEBUG_EN),
+     .DQS_IO_COL            (DQS_IO_COL),
+     .DQ_IO_MS              (DQ_IO_MS)
+     )
+    u_phy_top
+      (
+       .clk0                   (clk0),
+       .clk90                  (clk90),
+       .clkdiv0                (clkdiv0),
+       .rst0                   (rst0),
+       .rst90                  (rst90),
+       .rstdiv0                (rstdiv0),
+       .ctrl_wren              (ctrl_wren),
+       .ctrl_addr              (ctrl_addr),
+       .ctrl_ba                (ctrl_ba),
+       .ctrl_ras_n             (ctrl_ras_n),
+       .ctrl_cas_n             (ctrl_cas_n),
+       .ctrl_we_n              (ctrl_we_n),
+       .ctrl_cs_n              (ctrl_cs_n),
+       .ctrl_rden              (ctrl_rden),
+       .ctrl_ref_flag          (ctrl_ref_flag),
+       .wdf_data               (wdf_data),
+       .wdf_mask_data          (wdf_mask_data),
+       .wdf_rden               (wdf_rden),
+       .phy_init_done          (phy_init_done),
+       .phy_calib_rden         (phy_calib_rden),
+       .phy_calib_rden_sel     (phy_calib_rden_sel),
+       .rd_data_rise           (rd_data_rise),
+       .rd_data_fall           (rd_data_fall),
+       .ddr_ck                 (ddr_ck),
+       .ddr_ck_n               (ddr_ck_n),
+       .ddr_addr               (ddr_addr),
+       .ddr_ba                 (ddr_ba),
+       .ddr_ras_n              (ddr_ras_n),
+       .ddr_cas_n              (ddr_cas_n),
+       .ddr_we_n               (ddr_we_n),
+       .ddr_cs_n               (ddr_cs_n),
+       .ddr_cke                (ddr_cke),
+       .ddr_odt                (ddr_odt),
+       .ddr_dm                 (ddr_dm),
+       .ddr_dqs                (ddr_dqs),
+       .ddr_dqs_n              (ddr_dqs_n),
+       .ddr_dq                 (ddr_dq),
+       .dbg_idel_up_all        (dbg_idel_up_all),
+       .dbg_idel_down_all      (dbg_idel_down_all),
+       .dbg_idel_up_dq         (dbg_idel_up_dq),
+       .dbg_idel_down_dq       (dbg_idel_down_dq),
+       .dbg_idel_up_dqs        (dbg_idel_up_dqs),
+       .dbg_idel_down_dqs      (dbg_idel_down_dqs),
+       .dbg_idel_up_gate       (dbg_idel_up_gate),
+       .dbg_idel_down_gate     (dbg_idel_down_gate),
+       .dbg_sel_idel_dq        (dbg_sel_idel_dq),
+       .dbg_sel_all_idel_dq    (dbg_sel_all_idel_dq),
+       .dbg_sel_idel_dqs       (dbg_sel_idel_dqs),
+       .dbg_sel_all_idel_dqs   (dbg_sel_all_idel_dqs),
+       .dbg_sel_idel_gate      (dbg_sel_idel_gate),
+       .dbg_sel_all_idel_gate  (dbg_sel_all_idel_gate),
+       .dbg_calib_done         (dbg_calib_done),
+       .dbg_calib_err          (dbg_calib_err),
+       .dbg_calib_dq_tap_cnt   (dbg_calib_dq_tap_cnt),
+       .dbg_calib_dqs_tap_cnt  (dbg_calib_dqs_tap_cnt),
+       .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+       .dbg_calib_rd_data_sel  (dbg_calib_rd_data_sel),
+       .dbg_calib_rden_dly     (dbg_calib_rden_dly),
+       .dbg_calib_gate_dly     (dbg_calib_gate_dly)
+       );
+
+  ddr2_usr_top #
+    (
+     .BANK_WIDTH    (BANK_WIDTH),
+     .COL_WIDTH     (COL_WIDTH),
+     .CS_BITS       (CS_BITS),
+     .DQ_WIDTH      (DQ_WIDTH),
+     .DQ_PER_DQS    (DQ_PER_DQS),
+     .DQS_WIDTH     (DQS_WIDTH),
+     .APPDATA_WIDTH (APPDATA_WIDTH),
+     .ECC_ENABLE    (ECC_ENABLE),
+     .ROW_WIDTH     (ROW_WIDTH)
+     )
+    u_usr_top
+      (
+       .clk0              (clk0),
+       .clk90             (clk90),
+       .rst0              (rst0),
+       .rd_data_in_rise   (rd_data_rise),
+       .rd_data_in_fall   (rd_data_fall),
+       .phy_calib_rden    (phy_calib_rden),
+       .phy_calib_rden_sel(phy_calib_rden_sel),
+       .rd_data_valid     (rd_data_valid),
+       .rd_ecc_error      (rd_ecc_error),
+       .rd_data_fifo_out  (rd_data_fifo_out),
+       .app_af_cmd        (app_af_cmd),
+       .app_af_addr       (app_af_addr),
+       .app_af_wren       (app_af_wren),
+       .ctrl_af_rden      (ctrl_af_rden),
+       .af_cmd            (af_cmd),
+       .af_addr           (af_addr),
+       .af_empty          (af_empty),
+       .app_af_afull      (app_af_afull),
+       .app_wdf_wren      (app_wdf_wren),
+       .app_wdf_data      (app_wdf_data),
+       .app_wdf_mask_data (app_wdf_mask_data),
+       .wdf_rden          (wdf_rden),
+       .app_wdf_afull     (app_wdf_afull),
+       .wdf_data          (wdf_data),
+       .wdf_mask_data     (wdf_mask_data)
+       );
+
+
+  ddr2_ctrl #
+    (
+     .BANK_WIDTH    (BANK_WIDTH),
+     .COL_WIDTH     (COL_WIDTH),
+     .CS_BITS       (CS_BITS),
+     .CS_NUM        (CS_NUM),
+     .ROW_WIDTH     (ROW_WIDTH),
+     .ADDITIVE_LAT  (ADDITIVE_LAT),
+     .BURST_LEN     (BURST_LEN),
+     .CAS_LAT       (CAS_LAT),
+     .ECC_ENABLE    (ECC_ENABLE),
+     .REG_ENABLE    (REG_ENABLE),
+     .MULTI_BANK_EN (MULTI_BANK_EN),
+     .TWO_T_TIME_EN (TWO_T_TIME_EN),
+     .TREFI_NS      (TREFI_NS),
+     .TRAS          (TRAS),
+     .TRCD          (TRCD),
+     .TRFC          (TRFC),
+     .TRP           (TRP),
+     .TRTP          (TRTP),
+     .TWR           (TWR),
+     .TWTR          (TWTR),
+     .CLK_PERIOD    (CLK_PERIOD),
+     .DDR_TYPE      (DDR_TYPE)
+     )
+    u_ctrl
+      (
+       .clk           (clk0),
+       .rst           (rst0),
+       .af_cmd        (af_cmd),
+       .af_addr       (af_addr),
+       .af_empty      (af_empty),
+       .phy_init_done (phy_init_done),
+       .ctrl_ref_flag (ctrl_ref_flag),
+       .ctrl_af_rden  (ctrl_af_rden),
+       .ctrl_wren     (ctrl_wren),
+       .ctrl_rden     (ctrl_rden),
+       .ctrl_addr     (ctrl_addr),
+       .ctrl_ba       (ctrl_ba),
+       .ctrl_ras_n    (ctrl_ras_n),
+       .ctrl_cas_n    (ctrl_cas_n),
+       .ctrl_we_n     (ctrl_we_n),
+       .ctrl_cs_n     (ctrl_cs_n)
+       );
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_calib.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_calib.v
new file mode 100644 (file)
index 0000000..76a0751
--- /dev/null
@@ -0,0 +1,2353 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_calib.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/02 14:03:08 $
+// \   \  /  \    Date Created: Thu Aug 10 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module handles calibration after memory initialization.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_calib #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter DQ_WIDTH      = 72,
+   parameter DQ_BITS       = 7,
+   parameter DQ_PER_DQS    = 8,
+   parameter DQS_BITS      = 4,
+   parameter DQS_WIDTH     = 9,
+   parameter ADDITIVE_LAT  = 0,
+   parameter CAS_LAT       = 5,
+   parameter REG_ENABLE    = 1,
+   parameter CLK_PERIOD    = 3000,
+   parameter SIM_ONLY      = 0,
+   parameter DEBUG_EN      = 0
+   )
+  (
+   input                                   clk,
+   input                                   clkdiv,
+   input                                   rstdiv,
+   input [3:0]                             calib_start,
+   input                                   ctrl_rden,
+   input                                   phy_init_rden,
+   input [DQ_WIDTH-1:0]                    rd_data_rise,
+   input [DQ_WIDTH-1:0]                    rd_data_fall,
+   input                                   calib_ref_done,
+   output reg [3:0]                        calib_done,
+   output reg                              calib_ref_req,
+   output [DQS_WIDTH-1:0]                  calib_rden,
+   output reg [DQS_WIDTH-1:0]              calib_rden_sel,
+   output reg                              dlyrst_dq,
+   output reg [DQ_WIDTH-1:0]               dlyce_dq,
+   output reg [DQ_WIDTH-1:0]               dlyinc_dq,
+   output reg                              dlyrst_dqs,
+   output reg [DQS_WIDTH-1:0]              dlyce_dqs,
+   output reg [DQS_WIDTH-1:0]              dlyinc_dqs,
+   output reg [DQS_WIDTH-1:0]              dlyrst_gate,
+   output reg [DQS_WIDTH-1:0]              dlyce_gate,
+   output reg [DQS_WIDTH-1:0]              dlyinc_gate,
+   output [DQS_WIDTH-1:0]                  en_dqs,
+   output [DQS_WIDTH-1:0]                  rd_data_sel,
+   // Debug signals (optional use)
+   input                                   dbg_idel_up_all,
+   input                                   dbg_idel_down_all,
+   input                                   dbg_idel_up_dq,
+   input                                   dbg_idel_down_dq,
+   input                                   dbg_idel_up_dqs,
+   input                                   dbg_idel_down_dqs,
+   input                                   dbg_idel_up_gate,
+   input                                   dbg_idel_down_gate,
+   input [DQ_BITS-1:0]                     dbg_sel_idel_dq,
+   input                                   dbg_sel_all_idel_dq,
+   input [DQS_BITS:0]                      dbg_sel_idel_dqs,
+   input                                   dbg_sel_all_idel_dqs,
+   input [DQS_BITS:0]                      dbg_sel_idel_gate,
+   input                                   dbg_sel_all_idel_gate,
+   output [3:0]                            dbg_calib_done,
+   output [3:0]                            dbg_calib_err,
+   output [(6*DQ_WIDTH)-1:0]               dbg_calib_dq_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]              dbg_calib_dqs_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]              dbg_calib_gate_tap_cnt,
+   output [DQS_WIDTH-1:0]                  dbg_calib_rd_data_sel,
+   output [(5*DQS_WIDTH)-1:0]              dbg_calib_rden_dly,
+   output [(5*DQS_WIDTH)-1:0]              dbg_calib_gate_dly
+   );
+
+  // minimum time (in IDELAY taps) for which capture data must be stable for
+  // algorithm to consider
+  localparam MIN_WIN_SIZE = 5;
+  // IDEL_SET_VAL = (# of cycles - 1) to wait after changing IDELAY value
+  // we only have to wait enough for input with new IDELAY value to
+  // propagate through pipeline stages.
+  localparam IDEL_SET_VAL = 3'b111;
+  // # of clock cycles to delay read enable to determine if read data pattern
+  // is correct for stage 3/4 (RDEN, DQS gate) calibration
+  localparam CALIB_RDEN_PIPE_LEN = 31;
+  // translate CAS latency into number of clock cycles for read valid delay
+  // determination. Really only needed for CL = 2.5 (set to 2)
+  localparam CAS_LAT_RDEN = (CAS_LAT == 25) ? 2 : CAS_LAT;
+  // an SRL32 is used to delay CTRL_RDEN to generate read valid signal. This
+  // is min possible value delay through SRL32 can be
+  localparam RDEN_BASE_DELAY = CAS_LAT_RDEN + ADDITIVE_LAT + REG_ENABLE;
+  // an SRL32 is used to delay the CTRL_RDEN from the read postamble DQS
+  // gate. This is min possible value the SRL32 delay can be:
+  //  - Delay from end of deassertion of CTRL_RDEN to last falling edge of
+  //    read burst = 3.5 (CTRL_RDEN -> CAS delay) + 3 (min CAS latency) = 6.5
+  //  - Minimum time for DQS gate circuit to be generated:
+  //      * 1 cyc to register CTRL_RDEN from controller
+  //      * 1 cyc after RDEN_CTRL falling edge
+  //      * 1 cyc min through SRL32
+  //      * 1 cyc through SRL32 output flop
+  //      * 0 (<1) cyc of synchronization to DQS domain via IDELAY
+  //      * 1 cyc of delay through IDDR to generate CE to DQ IDDR's
+  //    Total = 5 cyc < 6.5 cycles
+  //    The total should be less than 5.5 cycles to account prop delays
+  //    adding one cycle to the synchronization time via the IDELAY.
+  //    NOTE: Value differs because of optional pipeline register added
+  //      for case of RDEN_BASE_DELAY > 3 to improve timing
+  localparam GATE_BASE_DELAY = RDEN_BASE_DELAY - 3;
+  localparam GATE_BASE_INIT = (GATE_BASE_DELAY <= 1) ? 0 : GATE_BASE_DELAY;
+  // used for RDEN calibration: difference between shift value used during
+  // calibration, and shift value for actual RDEN SRL. Only applies when
+  // RDEN edge is immediately captured by CLKDIV0. If not (depends on phase
+  // of CLK0 and CLKDIV0 when RDEN is asserted), then add 1 to this value.
+  localparam CAL3_RDEN_SRL_DLY_DELTA = 6;
+  // fix minimum value of DQS to be 1 to handle the case where's there's only
+  // one DQS group. We could also enforce that user always inputs minimum
+  // value of 1 for DQS_BITS (even when DQS_WIDTH=1). Leave this as safeguard
+  // Assume we don't have to do this for DQ, DQ_WIDTH always > 1
+  localparam DQS_BITS_FIX = (DQS_BITS == 0) ? 1 : DQS_BITS;
+  // how many taps to "pre-delay" DQ before stg 1 calibration - not needed for
+  // current calibration, but leave for debug
+  localparam DQ_IDEL_INIT = 6'b000000;
+  // # IDELAY taps per bit time (i.e. half cycle). Limit to 63.
+  localparam integer BIT_TIME_TAPS = (CLK_PERIOD/150 < 64) ?
+             CLK_PERIOD/150 : 63;
+
+  // used in various places during stage 4 cal: (1) determines maximum taps
+  // to increment when finding right edge, (2) amount to decrement after
+  // finding left edge, (3) amount to increment after finding right edge
+  localparam CAL4_IDEL_BIT_VAL = (BIT_TIME_TAPS >= 6'b100000) ?
+             6'b100000 : BIT_TIME_TAPS;
+
+  localparam CAL1_IDLE                   = 4'h0;
+  localparam CAL1_INIT                   = 4'h1;
+  localparam CAL1_INC_IDEL               = 4'h2;
+  localparam CAL1_FIND_FIRST_EDGE        = 4'h3;
+  localparam CAL1_FIRST_EDGE_IDEL_WAIT   = 4'h4;
+  localparam CAL1_FOUND_FIRST_EDGE_WAIT  = 4'h5;
+  localparam CAL1_FIND_SECOND_EDGE       = 4'h6;
+  localparam CAL1_SECOND_EDGE_IDEL_WAIT  = 4'h7;
+  localparam CAL1_CALC_IDEL              = 4'h8;
+  localparam CAL1_DEC_IDEL               = 4'h9;
+  localparam CAL1_DONE                   = 4'hA;
+
+  localparam CAL2_IDLE                    = 4'h0;
+  localparam CAL2_INIT                    = 4'h1;
+  localparam CAL2_INIT_IDEL_WAIT          = 4'h2;
+  localparam CAL2_FIND_EDGE_POS           = 4'h3;
+  localparam CAL2_FIND_EDGE_IDEL_WAIT_POS = 4'h4;
+  localparam CAL2_FIND_EDGE_NEG           = 4'h5;
+  localparam CAL2_FIND_EDGE_IDEL_WAIT_NEG = 4'h6;
+  localparam CAL2_DEC_IDEL                = 4'h7;
+  localparam CAL2_DONE                    = 4'h8;
+
+  localparam CAL3_IDLE                    = 3'h0;
+  localparam CAL3_INIT                    = 3'h1;
+  localparam CAL3_DETECT                  = 3'h2;
+  localparam CAL3_RDEN_PIPE_CLR_WAIT      = 3'h3;
+  localparam CAL3_DONE                    = 3'h4;
+
+  localparam CAL4_IDLE                    = 3'h0;
+  localparam CAL4_INIT                    = 3'h1;
+  localparam CAL4_FIND_WINDOW             = 3'h2;
+  localparam CAL4_FIND_EDGE               = 3'h3;
+  localparam CAL4_IDEL_WAIT               = 3'h4;
+  localparam CAL4_RDEN_PIPE_CLR_WAIT      = 3'h5;
+  localparam CAL4_ADJ_IDEL                = 3'h6;
+  localparam CAL4_DONE                    = 3'h7;
+
+  integer                        i, j;
+
+  reg [5:0]                      cal1_bit_time_tap_cnt;
+  reg [1:0]                      cal1_data_chk_last;
+  reg                            cal1_data_chk_last_valid;
+  reg [1:0]                      cal1_data_chk_r;
+  reg                            cal1_dlyce_dq;
+  reg                            cal1_dlyinc_dq;
+  reg                            cal1_dqs_dq_init_phase;
+  reg                            cal1_detect_edge;
+  reg                            cal1_detect_stable;
+  reg                            cal1_found_second_edge;
+  reg                            cal1_found_rising;
+  reg                            cal1_found_window;
+  reg                            cal1_first_edge_done;
+  reg [5:0]                      cal1_first_edge_tap_cnt;
+  reg [6:0]                      cal1_idel_dec_cnt;
+  reg [5:0]                      cal1_idel_inc_cnt;
+  reg [5:0]                      cal1_idel_max_tap;
+  reg                            cal1_idel_max_tap_we;
+  reg [5:0]                      cal1_idel_tap_cnt;
+  reg                            cal1_idel_tap_limit_hit;
+  reg [6:0]                      cal1_low_freq_idel_dec;
+  reg                            cal1_ref_req;
+  wire                           cal1_refresh;
+  reg [3:0]                      cal1_state;
+  reg [3:0]                      cal1_window_cnt;
+  reg                            cal2_curr_sel;
+  wire                           cal2_detect_edge;
+  reg                            cal2_dlyce_dqs;
+  reg                            cal2_dlyinc_dqs;
+  reg [5:0]                      cal2_idel_dec_cnt;
+  reg [5:0]                      cal2_idel_tap_cnt;
+  reg [5:0]                      cal2_idel_tap_limit;
+  reg                            cal2_idel_tap_limit_hit;
+  reg                            cal2_rd_data_fall_last_neg;
+  reg                            cal2_rd_data_fall_last_pos;
+  reg                            cal2_rd_data_last_valid_neg;
+  reg                            cal2_rd_data_last_valid_pos;
+  reg                            cal2_rd_data_rise_last_neg;
+  reg                            cal2_rd_data_rise_last_pos;
+  reg [DQS_WIDTH-1:0]            cal2_rd_data_sel;
+  wire                           cal2_rd_data_sel_edge;
+  reg [DQS_WIDTH-1:0]            cal2_rd_data_sel_r;
+  reg                            cal2_ref_req;
+  reg [3:0]                      cal2_state;
+  reg                            cal3_data_match;
+  reg                            cal3_data_match_stgd;
+  wire                           cal3_data_valid;
+  wire                           cal3_match_found;
+  wire [4:0]                     cal3_rden_dly;
+  reg [4:0]                      cal3_rden_srl_a;
+  reg [2:0]                      cal3_state;
+  wire                           cal4_data_good;
+  reg                            cal4_data_match;
+  reg                            cal4_data_match_stgd;
+  wire                           cal4_data_valid;
+  reg                            cal4_dlyce_gate;
+  reg                            cal4_dlyinc_gate;
+  reg                            cal4_dlyrst_gate;
+  reg [4:0]                      cal4_gate_srl_a;
+  reg [5:0]                      cal4_idel_adj_cnt;
+  reg                            cal4_idel_adj_inc;
+  reg                            cal4_idel_bit_tap;
+  reg [5:0]                      cal4_idel_tap_cnt;
+  reg                            cal4_idel_max_tap;
+  reg [4:0]                      cal4_rden_srl_a;
+  reg                            cal4_ref_req;
+  reg                            cal4_seek_left;
+  reg                            cal4_stable_window;
+  reg [2:0]                      cal4_state;
+  reg [3:0]                      cal4_window_cnt;
+  reg [3:0]                      calib_done_tmp;         // only for stg1/2/4
+  reg                            calib_ctrl_gate_pulse_r;
+  reg                            calib_ctrl_rden;
+  reg                            calib_ctrl_rden_r;
+  wire                           calib_ctrl_rden_negedge;
+  reg                            calib_ctrl_rden_negedge_r;
+  reg [3:0]                      calib_done_r;
+  reg [3:0]                      calib_err;
+  reg [1:0]                      calib_err_2;
+  wire                           calib_init_gate_pulse;
+  reg                            calib_init_gate_pulse_r;
+  reg                            calib_init_gate_pulse_r1;
+  reg                            calib_init_rden;
+  reg                            calib_init_rden_r;
+  reg [4:0]                      calib_rden_srl_a;
+  wire [4:0]                     calib_rden_srl_a_r;
+  reg [(5*DQS_WIDTH)-1:0]        calib_rden_dly;
+  reg                            calib_rden_edge_r;
+  reg [4:0]                      calib_rden_pipe_cnt;
+  wire                           calib_rden_srl_out;
+  wire                           calib_rden_srl_out_r;
+  reg                            calib_rden_srl_out_r1;
+  reg                            calib_rden_valid;
+  reg                            calib_rden_valid_stgd;
+  reg [DQ_BITS-1:0]              count_dq;
+  reg [DQS_BITS_FIX-1:0]         count_dqs;
+  reg [DQS_BITS_FIX-1:0]         count_gate;
+  reg [DQS_BITS_FIX-1:0]         count_rden;
+  reg                            ctrl_rden_r;
+  wire                           dlyce_or;
+  reg [(5*DQS_WIDTH)-1:0]        gate_dly;
+  wire [(5*DQS_WIDTH)-1:0]       gate_dly_r;
+  wire                           gate_srl_in;
+  wire [DQS_WIDTH-1:0]           gate_srl_out;
+  wire [DQS_WIDTH-1:0]           gate_srl_out_r;
+  reg [2:0]                      idel_set_cnt;
+  wire                           idel_set_wait;
+  reg [DQ_BITS-1:0]              next_count_dq;
+  reg [DQS_BITS_FIX-1:0]         next_count_dqs;
+  reg [DQS_BITS_FIX-1:0]         next_count_gate;
+  reg                            phy_init_rden_r;
+  reg                            phy_init_rden_r1;
+  reg [DQ_WIDTH-1:0]             rd_data_fall_1x_r;
+  reg [DQS_WIDTH-1:0]            rd_data_fall_1x_r1;
+  reg [DQS_WIDTH-1:0]            rd_data_fall_2x_r;
+  wire [DQS_WIDTH-1:0]           rd_data_fall_chk_q1;
+  wire [DQS_WIDTH-1:0]           rd_data_fall_chk_q2;
+  reg [DQ_WIDTH-1:0]             rd_data_rise_1x_r;
+  reg [DQS_WIDTH-1:0]            rd_data_rise_1x_r1;
+  reg [DQS_WIDTH-1:0]            rd_data_rise_2x_r;
+  wire [DQS_WIDTH-1:0]           rd_data_rise_chk_q1;
+  wire [DQS_WIDTH-1:0]           rd_data_rise_chk_q2;
+  reg                            rdd_fall_q1;
+  reg                            rdd_fall_q1_r;
+  reg                            rdd_fall_q1_r1;
+  reg                            rdd_fall_q2;
+  reg                            rdd_fall_q2_r;
+  reg                            rdd_rise_q1;
+  reg                            rdd_rise_q1_r;
+  reg                            rdd_rise_q1_r1;
+  reg                            rdd_rise_q2;
+  reg                            rdd_rise_q2_r;
+  reg [DQS_BITS_FIX-1:0]         rdd_mux_sel;
+  reg                            rden_dec;
+  reg [(5*DQS_WIDTH)-1:0]        rden_dly;
+  wire [(5*DQS_WIDTH)-1:0]       rden_dly_r;
+  reg [4:0]                      rden_dly_0;
+  reg                            rden_inc;
+  reg [DQS_WIDTH-1:0]            rden_mux;
+  wire [DQS_WIDTH-1:0]           rden_srl_out;
+
+  // Debug
+  integer                        x;
+  reg [5:0]                      dbg_dq_tap_cnt [DQ_WIDTH-1:0];
+  reg [5:0]                      dbg_dqs_tap_cnt [DQS_WIDTH-1:0];
+  reg [5:0]                      dbg_gate_tap_cnt [DQS_WIDTH-1:0];
+
+  //***************************************************************************
+  // Debug output ("dbg_phy_calib_*")
+  // NOTES:
+  //  1. All debug outputs coming out of PHY_CALIB are clocked off CLKDIV0,
+  //     although they are also static after calibration is complete. This
+  //     means the user can either connect them to a Chipscope ILA, or to
+  //     either a sync/async VIO input block. Using an async VIO has the
+  //     advantage of not requiring these paths to meet cycle-to-cycle timing.
+  //  2. The widths of most of these debug buses are dependent on the # of
+  //     DQS/DQ bits (e.g. dq_tap_cnt width = 6 * (# of DQ bits)
+  // SIGNAL DESCRIPTION:
+  //  1. calib_done:   4 bits - each one asserted as each phase of calibration
+  //                   is completed.
+  //  2. calib_err:    4 bits - each one asserted when a calibration error
+  //                   encountered for that stage. Some of these bits may not
+  //                   be used (not all cal stages report an error).
+  //  3. dq_tap_cnt:   final IDELAY tap counts for all DQ IDELAYs
+  //  4. dqs_tap_cnt:  final IDELAY tap counts for all DQS IDELAYs
+  //  5. gate_tap_cnt: final IDELAY tap counts for all DQS gate
+  //                   synchronization IDELAYs
+  //  6. rd_data_sel:  final read capture MUX (either "positive" or "negative"
+  //                   edge capture) settings for all DQS groups
+  //  7. rden_dly:     related to # of cycles after issuing a read until when
+  //                   read data is valid - for all DQS groups
+  //  8. gate_dly:     related to # of cycles after issuing a read until when
+  //                   clock enable for all DQ's is deasserted to prevent
+  //                   effect of DQS postamble glitch - for all DQS groups
+  //***************************************************************************
+
+  //*****************************************************************
+  // Record IDELAY tap values by "snooping" IDELAY control signals
+  //*****************************************************************
+
+  // record DQ IDELAY tap values
+  genvar dbg_dq_tc_i;
+  generate
+    for (dbg_dq_tc_i = 0; dbg_dq_tc_i < DQ_WIDTH;
+         dbg_dq_tc_i = dbg_dq_tc_i + 1) begin: gen_dbg_dq_tap_cnt
+      assign dbg_calib_dq_tap_cnt[(6*dbg_dq_tc_i)+5:(6*dbg_dq_tc_i)]
+               = dbg_dq_tap_cnt[dbg_dq_tc_i];
+      always @(posedge clkdiv)
+        if (rstdiv | dlyrst_dq)
+          dbg_dq_tap_cnt[dbg_dq_tc_i] <= 6'b000000;
+        else
+          if (dlyce_dq[dbg_dq_tc_i])
+            if (dlyinc_dq[dbg_dq_tc_i])
+              dbg_dq_tap_cnt[dbg_dq_tc_i]
+                <= dbg_dq_tap_cnt[dbg_dq_tc_i] + 1;
+            else
+              dbg_dq_tap_cnt[dbg_dq_tc_i]
+                <= dbg_dq_tap_cnt[dbg_dq_tc_i] - 1;
+    end
+  endgenerate
+
+  // record DQS IDELAY tap values
+  genvar dbg_dqs_tc_i;
+  generate
+    for (dbg_dqs_tc_i = 0; dbg_dqs_tc_i < DQS_WIDTH;
+         dbg_dqs_tc_i = dbg_dqs_tc_i + 1) begin: gen_dbg_dqs_tap_cnt
+      assign dbg_calib_dqs_tap_cnt[(6*dbg_dqs_tc_i)+5:(6*dbg_dqs_tc_i)]
+               = dbg_dqs_tap_cnt[dbg_dqs_tc_i];
+      always @(posedge clkdiv)
+        if (rstdiv | dlyrst_dqs)
+          dbg_dqs_tap_cnt[dbg_dqs_tc_i] <= 6'b000000;
+        else
+          if (dlyce_dqs[dbg_dqs_tc_i])
+            if (dlyinc_dqs[dbg_dqs_tc_i])
+              dbg_dqs_tap_cnt[dbg_dqs_tc_i]
+                <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] + 1;
+            else
+              dbg_dqs_tap_cnt[dbg_dqs_tc_i]
+                <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] - 1;
+    end
+  endgenerate
+
+  // record DQS gate IDELAY tap values
+  genvar dbg_gate_tc_i;
+  generate
+    for (dbg_gate_tc_i = 0; dbg_gate_tc_i < DQS_WIDTH;
+         dbg_gate_tc_i = dbg_gate_tc_i + 1) begin: gen_dbg_gate_tap_cnt
+      assign dbg_calib_gate_tap_cnt[(6*dbg_gate_tc_i)+5:(6*dbg_gate_tc_i)]
+               = dbg_gate_tap_cnt[dbg_gate_tc_i];
+      always @(posedge clkdiv)
+        if (rstdiv | dlyrst_gate[dbg_gate_tc_i])
+          dbg_gate_tap_cnt[dbg_gate_tc_i] <= 6'b000000;
+        else
+          if (dlyce_gate[dbg_gate_tc_i])
+            if (dlyinc_gate[dbg_gate_tc_i])
+              dbg_gate_tap_cnt[dbg_gate_tc_i]
+                <= dbg_gate_tap_cnt[dbg_gate_tc_i] + 1;
+            else
+              dbg_gate_tap_cnt[dbg_gate_tc_i]
+                <= dbg_gate_tap_cnt[dbg_gate_tc_i] - 1;
+    end
+  endgenerate
+
+  assign dbg_calib_done        = calib_done;
+  assign dbg_calib_err         = calib_err;
+  assign dbg_calib_rd_data_sel = cal2_rd_data_sel;
+  assign dbg_calib_rden_dly    = rden_dly;
+  assign dbg_calib_gate_dly    = gate_dly;
+
+  //***************************************************************************
+  // Read data pipelining, and read data "ISERDES" data width expansion
+  //***************************************************************************
+
+  // For all data bits, register incoming capture data to slow clock to improve
+  // timing. Adding single pipeline stage does not affect functionality (as
+  // long as we make sure to wait extra clock cycle after changing DQ IDELAY)
+  // Also note in this case that we're "missing" every other clock cycle's
+  // worth of data capture since we're sync'ing to the slow clock. This is
+  // fine for stage 1 and stage 2 cal, but not for stage 3 and 4 (see below
+  // for different circuit to handle those stages)
+  always @(posedge clkdiv) begin
+    rd_data_rise_1x_r <= rd_data_rise;
+    rd_data_fall_1x_r <= rd_data_fall;
+  end
+
+  // For every DQ_PER_DQS bit, generate what is essentially a ISERDES-type
+  // data width expander. Will need this for stage 3 and 4 cal, where we need
+  // to compare data over consecutive clock cycles. We can also use this for
+  // stage 2 as well (stage 2 doesn't require every bit to be looked at, only
+  // one bit per DQS group)
+  genvar rdd_i;
+  generate
+    for (rdd_i = 0; rdd_i < DQS_WIDTH; rdd_i = rdd_i + 1) begin: gen_rdd
+      // first stage: keep data in fast clk domain. Store data over two
+      // consecutive clock cycles for rise/fall data for proper transfer
+      // to slow clock domain
+      always @(posedge clk) begin
+        rd_data_rise_2x_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)];
+        rd_data_fall_2x_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)];
+      end
+      // second stage, register first stage to slow clock domain, 2nd stage
+      // consists of both these flops, and the rd_data_rise_1x_r flops
+      always @(posedge clkdiv) begin
+        rd_data_rise_1x_r1[rdd_i] <= rd_data_rise_2x_r[rdd_i];
+        rd_data_fall_1x_r1[rdd_i] <= rd_data_fall_2x_r[rdd_i];
+      end
+      // now we have four outputs - representing rise/fall outputs over last
+      // 2 fast clock cycles. However, the ordering these represent can either
+      // be: (1) Q2 = data @ time = n, Q1 = data @ time = n+1, or (2)
+      // Q2 = data @ time = n - 1, Q1 = data @ time = n (and data at [Q1,Q2]
+      // is "staggered") - leave it up to the stage of calibration using this
+      // to figure out which is which, if they care at all (e.g. stage 2 cal
+      // doesn't care about the ordering)
+      assign rd_data_rise_chk_q1[rdd_i]
+               = rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)];
+      assign rd_data_rise_chk_q2[rdd_i]
+               = rd_data_rise_1x_r1[rdd_i];
+      assign rd_data_fall_chk_q1[rdd_i]
+               = rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)];
+      assign rd_data_fall_chk_q2[rdd_i]
+               = rd_data_fall_1x_r1[rdd_i];
+    end
+  endgenerate
+
+  //*****************************************************************
+  // Outputs of these simplified ISERDES circuits then feed MUXes based on
+  // which DQ the current calibration algorithm needs to look at
+  //*****************************************************************
+
+  // generate MUX control; assume that adding an extra pipeline stage isn't
+  // an issue - whatever stage cal logic is using output of MUX will wait
+  // enough time after changing it
+  always @(posedge clkdiv) begin
+    (* full_case, parallel_case *) case (calib_done[2:0])
+      3'b001: rdd_mux_sel <= next_count_dqs;
+      3'b011: rdd_mux_sel <= count_rden;
+      3'b111: rdd_mux_sel <= next_count_gate;
+    endcase
+  end
+
+  always @(posedge clkdiv) begin
+    rdd_rise_q1 <= rd_data_rise_chk_q1[rdd_mux_sel];
+    rdd_rise_q2 <= rd_data_rise_chk_q2[rdd_mux_sel];
+    rdd_fall_q1 <= rd_data_fall_chk_q1[rdd_mux_sel];
+    rdd_fall_q2 <= rd_data_fall_chk_q2[rdd_mux_sel];
+  end
+
+  //***************************************************************************
+  // Demultiplexor to control (reset, increment, decrement) IDELAY tap values
+  //   For DQ:
+  //     STG1: for per-bit-deskew, only inc/dec the current DQ. For non-per
+  //       deskew, increment all bits in the current DQS set
+  //     STG2: inc/dec all DQ's in the current DQS set.
+  // NOTE: Nice to add some error checking logic here (or elsewhere in the
+  //       code) to check if logic attempts to overflow tap value
+  //***************************************************************************
+
+  // don't use DLYRST to reset value of IDELAY after reset. Need to change this
+  // if we want to allow user to recalibrate after initial reset
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      dlyrst_dq <= 1'b1;
+      dlyrst_dqs <= 1'b1;
+    end else begin
+      dlyrst_dq <= 1'b0;
+      dlyrst_dqs <= 1'b0;
+    end
+
+  always @(posedge clkdiv) begin
+    if (rstdiv) begin
+      dlyce_dq   <= 'b0;
+      dlyinc_dq  <= 'b0;
+      dlyce_dqs  <= 'b0;
+      dlyinc_dqs <= 'b0;
+    end else begin
+      dlyce_dq   <= 'b0;
+      dlyinc_dq  <= 'b0;
+      dlyce_dqs  <= 'b0;
+      dlyinc_dqs <= 'b0;
+
+      // stage 1 cal: change only specified DQ
+      if (cal1_dlyce_dq) begin
+        if (SIM_ONLY == 0) begin
+          dlyce_dq[count_dq] <= 1'b1;
+          dlyinc_dq[count_dq] <= cal1_dlyinc_dq;
+        end else begin
+          // if simulation, then calibrate only first DQ, apply results
+          // to all DQs (i.e. assume delay on all DQs is the same)
+          for (i = 0; i < DQ_WIDTH; i = i + 1) begin: loop_sim_dq_dly
+            dlyce_dq[i] <= 1'b1;
+            dlyinc_dq[i] <= cal1_dlyinc_dq;
+          end
+        end
+      end else if (cal2_dlyce_dqs) begin
+        // stage 2 cal: change DQS and all corresponding DQ's
+        if (SIM_ONLY == 0) begin
+          dlyce_dqs[count_dqs] <= 1'b1;
+          dlyinc_dqs[count_dqs] <= cal2_dlyinc_dqs;
+          for (i = 0; i < DQ_PER_DQS; i = i + 1) begin: loop_dqs_dly
+            dlyce_dq[(DQ_PER_DQS*count_dqs)+i] <= 1'b1;
+            dlyinc_dq[(DQ_PER_DQS*count_dqs)+i] <= cal2_dlyinc_dqs;
+          end
+        end else begin
+          for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_dqs_dly
+            // if simulation, then calibrate only first DQS
+            dlyce_dqs[i] <= 1'b1;
+            dlyinc_dqs[i] <= cal2_dlyinc_dqs;
+            for (j = 0; j < DQ_PER_DQS; j = j + 1) begin: loop_sim_dq_dqs_dly
+              dlyce_dq[(DQ_PER_DQS*i)+j] <= 1'b1;
+              dlyinc_dq[(DQ_PER_DQS*i)+j] <= cal2_dlyinc_dqs;
+            end
+          end
+        end
+      end else if (DEBUG_EN != 0) begin
+        // DEBUG: allow user to vary IDELAY tap settings
+        // For DQ IDELAY taps
+        if (dbg_idel_up_all || dbg_idel_down_all ||
+            dbg_sel_all_idel_dq) begin
+          for (x = 0; x < DQ_WIDTH; x = x + 1) begin: loop_dly_inc_dq
+            dlyce_dq[x] <= dbg_idel_up_all | dbg_idel_down_all |
+                           dbg_idel_up_dq  | dbg_idel_down_dq;
+            dlyinc_dq[x] <= dbg_idel_up_all | dbg_idel_up_dq;
+          end
+        end else begin
+          dlyce_dq <= 'b0;
+          dlyce_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq |
+                                       dbg_idel_down_dq;
+          dlyinc_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq;
+        end
+        // For DQS IDELAY taps
+        if (dbg_idel_up_all || dbg_idel_down_all ||
+            dbg_sel_all_idel_dqs) begin
+          for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_dqs
+            dlyce_dqs[x] <= dbg_idel_up_all | dbg_idel_down_all |
+                            dbg_idel_up_dqs | dbg_idel_down_dqs;
+            dlyinc_dqs[x] <= dbg_idel_up_all | dbg_idel_up_dqs;
+          end
+        end else begin
+          dlyce_dqs <= 'b0;
+          dlyce_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs |
+                                         dbg_idel_down_dqs;
+          dlyinc_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs;
+        end
+      end
+    end
+  end
+
+  // GATE synchronization is handled directly by Stage 4 calibration FSM
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      dlyrst_gate <= {DQS_WIDTH{1'b1}};
+      dlyce_gate  <= {DQS_WIDTH{1'b0}};
+      dlyinc_gate <= {DQS_WIDTH{1'b0}};
+    end else begin
+      dlyrst_gate <= {DQS_WIDTH{1'b0}};
+      dlyce_gate  <= {DQS_WIDTH{1'b0}};
+      dlyinc_gate <= {DQS_WIDTH{1'b0}};
+
+      if (cal4_dlyrst_gate) begin
+        if (SIM_ONLY == 0)
+          dlyrst_gate[count_gate] <= 1'b1;
+        else
+          for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly_rst
+            dlyrst_gate[i] <= 1'b1;
+          end
+      end
+
+      if (cal4_dlyce_gate) begin
+        if (SIM_ONLY == 0) begin
+          dlyce_gate[count_gate]  <= 1'b1;
+          dlyinc_gate[count_gate] <= cal4_dlyinc_gate;
+        end else begin
+          // if simulation, then calibrate only first gate
+          for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly
+            dlyce_gate[i]  <= 1'b1;
+            dlyinc_gate[i] <= cal4_dlyinc_gate;
+          end
+        end
+      end else if (DEBUG_EN != 0) begin
+        // DEBUG: allow user to vary IDELAY tap settings
+        if (dbg_idel_up_all || dbg_idel_down_all ||
+            dbg_sel_all_idel_gate) begin
+          for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_gate
+            dlyce_gate[x] <= dbg_idel_up_all | dbg_idel_down_all |
+                             dbg_idel_up_gate | dbg_idel_down_gate;
+            dlyinc_gate[x] <= dbg_idel_up_all | dbg_idel_up_gate;
+          end
+        end else begin
+          dlyce_gate <= {DQS_WIDTH{1'b0}};
+          dlyce_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate |
+                                           dbg_idel_down_gate;
+          dlyinc_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate;
+        end
+      end
+    end
+
+  //***************************************************************************
+  // signal to tell calibration state machines to wait and give IDELAY time to
+  // settle after it's value is changed (both time for IDELAY chain to settle,
+  // and for settled output to propagate through ISERDES). For general use: use
+  // for any calibration state machines that modify any IDELAY.
+  // Should give at least enough time for IDELAY output to settle (technically
+  // for V5, this should be "glitchless" when IDELAY taps are changed, so don't
+  // need any time here), and also time for new data to propagate through both
+  // ISERDES and the "RDD" MUX + associated pipelining
+  // For now, give very "generous" delay - doesn't really matter since only
+  // needed during calibration
+  //***************************************************************************
+
+  // determine if calibration polarity has changed
+  always @(posedge clkdiv)
+    cal2_rd_data_sel_r   <= cal2_rd_data_sel;
+
+  assign cal2_rd_data_sel_edge = |(cal2_rd_data_sel ^ cal2_rd_data_sel_r);
+
+  // combine requests to modify any of the IDELAYs into one. Also when second
+  // stage capture "edge" polarity is changed (IDELAY isn't changed in this
+  // case, but use the same counter to stall cal logic)
+  assign dlyce_or = cal1_dlyce_dq |
+                    cal2_dlyce_dqs |
+                    cal2_rd_data_sel_edge |
+                    cal4_dlyce_gate |
+                    cal4_dlyrst_gate;
+
+  // SYN_NOTE: Can later recode to avoid combinational path
+  assign idel_set_wait = dlyce_or || (idel_set_cnt != IDEL_SET_VAL);
+
+  always @(posedge clkdiv)
+    if (rstdiv)
+      idel_set_cnt <= 4'b0000;
+    else if (dlyce_or)
+      idel_set_cnt <= 4'b0000;
+    else if (idel_set_cnt != IDEL_SET_VAL)
+      idel_set_cnt <= idel_set_cnt + 1;
+
+  // generate request to PHY_INIT logic to issue auto-refresh
+  // used by certain states to force prech/auto-refresh part way through
+  // calibration to avoid a tRAS violation (which will happen if that
+  // stage of calibration lasts long enough). This signal must meet the
+  // following requirements: (1) only transition from 0->1 when the refresh
+  // request is needed, (2) stay at 1 and only transition 1->0 when
+  // CALIB_REF_DONE is asserted
+  always @(posedge clkdiv)
+    if (rstdiv)
+      calib_ref_req <= 1'b0;
+    else
+      calib_ref_req <= cal1_ref_req | cal2_ref_req  | cal4_ref_req;
+
+  // stage 1 calibration requests auto-refresh every 4 bits
+  generate
+    if (DQ_BITS < 2) begin: gen_cal1_refresh_dq_lte4
+      assign cal1_refresh = 1'b0;
+    end else begin: gen_cal1_refresh_dq_gt4
+      assign cal1_refresh = (next_count_dq[1:0] == 2'b00);
+    end
+  endgenerate
+
+  //***************************************************************************
+  // First stage calibration: DQ-DQS
+  // Definitions:
+  //  edge: detected when varying IDELAY, and current capture data != prev
+  //    capture data
+  //  valid bit window: detected when current capture data == prev capture
+  //    data for more than half the bit time
+  //  starting conditions for DQS-DQ phase:
+  //    case 1: when DQS starts somewhere in rising edge bit window, or
+  //      on the right edge of the rising bit window.
+  //    case 2: when DQS starts somewhere in falling edge bit window, or
+  //      on the right edge of the falling bit window.
+  // Algorithm Description:
+  //  1. Increment DQ IDELAY until we find an edge.
+  //  2. While we're finding the first edge, note whether a valid bit window
+  //     has been detected before we found an edge. If so, then figure out if
+  //     this is the rising or falling bit window. If rising, then our starting
+  //     DQS-DQ phase is case 1. If falling, then it's case 2. If don't detect
+  //     a valid bit window, then we must have started on the edge of a window.
+  //     Need to wait until later on to decide which case we are.
+  //       - Store FIRST_EDGE IDELAY value
+  //  3. Now look for second edge.
+  //  4. While we're finding the second edge, note whether valid bit window
+  //     is detected. If so, then use to, along with results from (2) to figure
+  //     out what the starting case is. If in rising bit window, then we're in
+  //     case 2. If falling, then case 1.
+  //       - Store SECOND_EDGE IDELAY value
+  //     NOTES:
+  //       a. Finding two edges allows us to calculate the bit time (although
+  //          not the "same" bit time polarity - need to investigate this
+  //          more).
+  //       b. If we run out of taps looking for the second edge, then the bit
+  //       time must be too long (>= 2.5ns, and DQS-DQ starting phase must be
+  //       case 1).
+  //  5. Calculate absolute amount to delay DQ as:
+  //       If second edge found, and case 1:
+  //         - DQ_IDELAY = FIRST_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
+  //       If second edge found, and case 2:
+  //         - DQ_IDELAY = SECOND_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
+  //       If second edge not found, then need to make an approximation on
+  //       how much to shift by (should be okay, because we have more timing
+  //       margin):
+  //         - DQ_IDELAY = FIRST_EDGE - 0.5 * (bit_time)
+  //     NOTE: Does this account for either case 1 or case 2?????
+  //     NOTE: It's also possible even when we find the second edge, that
+  //           to instead just use half the bit time to subtract from either
+  //           FIRST or SECOND_EDGE. Finding the actual bit time (which is
+  //           what (SECOND_EDGE - FIRST_EDGE) is, is slightly more accurate,
+  //           since it takes into account duty cycle distortion.
+  //  6. Repeat for each DQ in current DQS set.
+  //***************************************************************************
+
+  //*****************************************************************
+  // for first stage calibration - used for checking if DQS is aligned to the
+  // particular DQ, such that we're in the data valid window. Basically, this
+  // is one giant MUX.
+  //  = [falling data, rising data]
+  //  = [0, 1] = rising DQS aligned in proper (rising edge) bit window
+  //  = [1, 0] = rising DQS aligned in wrong (falling edge) bit window
+  //  = [0, 0], or [1,1] = in uncertain region between windows
+  //*****************************************************************
+
+  // SYN_NOTE: May have to split this up into multiple levels - MUX can get
+  //  very wide - as wide as the data bus width
+  always @(posedge clkdiv)
+    cal1_data_chk_r <= {rd_data_fall_1x_r[next_count_dq],
+                       rd_data_rise_1x_r[next_count_dq]};
+
+  //*****************************************************************
+  // determine when an edge has occurred - when either the current value
+  // is different from the previous latched value or when the DATA_CHK
+  // outputs are the same (rare, but indicates that we're at an edge)
+  // This is only valid when the IDELAY output and propagation of the
+  // data through the capture flops has had a chance to settle out.
+  //*****************************************************************
+
+  // write CAL1_DETECT_EDGE and CAL1_DETECT_STABLE in such a way that
+  // if X's are captured on the bus during functional simulation, that
+  // the logic will register this as an edge detected. Do this to allow
+  // use of this HDL with Denali memory models (Denali models drive DQ
+  // to X's on both edges of the data valid window to simulate jitter)
+  // This is only done for functional simulation purposes. **Should not**
+  // make the final synthesized logic more complicated, but it does make
+  // the HDL harder to understand b/c we have to "phrase" the logic
+  // slightly differently than when not worrying about X's
+  always @(*) begin
+    // no edge found if: (1) we have recorded prev edge, and rise
+    // data == fall data, (2) we haven't yet recorded prev edge, but
+    // rise/fall data is equal to either [0,1] or [1,0] (i.e. rise/fall
+    // data isn't either X's, or [0,0] or [1,1], which indicates we're
+    // in the middle of an edge, since normally rise != fall data for stg1)
+    if ((cal1_data_chk_last_valid &&
+         (cal1_data_chk_r == cal1_data_chk_last)) ||
+        (!cal1_data_chk_last_valid &&
+         ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10))))
+      cal1_detect_edge = 1'b0;
+    else
+      cal1_detect_edge = 1'b1;
+  end
+
+  always @(*) begin
+    // assert if we've found a region where data valid window is stable
+    // over consecutive IDELAY taps, and either rise/fall = [1,0], or [0,1]
+    if ((cal1_data_chk_last_valid &&
+         (cal1_data_chk_r == cal1_data_chk_last)) &&
+        ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10)))
+      cal1_detect_stable <= 1'b1;
+    else
+      cal1_detect_stable <= 1'b0;
+  end
+
+  //*****************************************************************
+  // Find valid window: keep track of how long we've been in the same data
+  // window. If it's been long enough, then declare that we've found a valid
+  // window. Also returns whether we found a rising or falling window (only
+  // valid when found_window is asserted)
+  //*****************************************************************
+
+  always @(posedge clkdiv) begin
+    if (cal1_state == CAL1_INIT) begin
+      cal1_window_cnt   <= 4'b0000;
+      cal1_found_window <= 1'b0;
+      cal1_found_rising <= 1'bx;
+    end else if (!cal1_data_chk_last_valid) begin
+      // if we haven't stored a previous value of CAL1_DATA_CHK (or it got
+      // invalidated because we detected an edge, and are now looking for the
+      // second edge), then make sure FOUND_WINDOW deasserted on following
+      // clock edge (to avoid finding a false window immediately after finding
+      // an edge). Note that because of jitter, it's possible to not find an
+      // edge at the end of the IDELAY increment settling time, but to find an
+      // edge on the next clock cycle (e.g. during CAL1_FIND_FIRST_EDGE)
+      cal1_window_cnt   <= 4'b0000;
+      cal1_found_window <= 1'b0;
+      cal1_found_rising <= 1'bx;
+    end else if (((cal1_state == CAL1_FIRST_EDGE_IDEL_WAIT) ||
+                  (cal1_state == CAL1_SECOND_EDGE_IDEL_WAIT)) &&
+                 !idel_set_wait) begin
+      // while finding the first and second edges, see if we can detect a
+      // stable bit window (occurs over MIN_WIN_SIZE number of taps). If
+      // so, then we're away from an edge, and can conclusively determine the
+      // starting DQS-DQ phase.
+      if (cal1_detect_stable) begin
+        cal1_window_cnt <= cal1_window_cnt + 1;
+        if (cal1_window_cnt == MIN_WIN_SIZE-1) begin
+          cal1_found_window <= 1'b1;
+          if (cal1_data_chk_r == 2'b01)
+            cal1_found_rising <= 1'b1;
+          else
+            cal1_found_rising <= 1'b0;
+        end
+      end else begin
+        // otherwise, we're not in a data valid window, reset the window
+        // counter, and indicate we're not currently in window. This should
+        // happen by design at least once after finding the first edge.
+        cal1_window_cnt <= 4'b0000;
+        cal1_found_window <= 1'b0;
+        cal1_found_rising <= 1'bx;
+      end
+    end
+  end
+
+  //*****************************************************************
+  // keep track of edge tap counts found, and whether we've
+  // incremented to the maximum number of taps allowed
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (cal1_state == CAL1_INIT) begin
+      cal1_idel_tap_limit_hit   <= 1'b0;
+      cal1_idel_tap_cnt   <= 6'b000000;
+    end else if (cal1_dlyce_dq) begin
+      if (cal1_dlyinc_dq) begin
+        cal1_idel_tap_cnt <= cal1_idel_tap_cnt + 1;
+        cal1_idel_tap_limit_hit <= (cal1_idel_tap_cnt == 6'b111110);
+      end else begin
+        cal1_idel_tap_cnt <= cal1_idel_tap_cnt - 1;
+        cal1_idel_tap_limit_hit <= 1'b0;
+      end
+    end
+
+  //*****************************************************************
+  // Pipeline for better timing - amount to decrement by if second
+  // edge not found
+  //*****************************************************************
+  // if only one edge found (possible for low frequencies), then:
+  //  1. Assume starting DQS-DQ phase has DQS in DQ window (aka "case 1")
+  //  2. We have to decrement by (63 - first_edge_tap_cnt) + (BIT_TIME_TAPS/2)
+  //     (i.e. decrement by 63-first_edge_tap_cnt to get to right edge of
+  //     DQ window. Then decrement again by (BIT_TIME_TAPS/2) to get to center
+  //     of DQ window.
+  //  3. Clamp the above value at 63 to ensure we don't underflow IDELAY
+  //     (note: clamping happens in the CAL1 state machine)
+  always @(posedge clkdiv)
+    cal1_low_freq_idel_dec
+      <= (7'b0111111 - {1'b0, cal1_first_edge_tap_cnt}) +
+         (BIT_TIME_TAPS/2);
+
+  //*****************************************************************
+  // Keep track of max taps used during stage 1, use this to limit
+  // the number of taps that can be used in stage 2
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      cal1_idel_max_tap    <= 6'b000000;
+      cal1_idel_max_tap_we <= 1'b0;
+    end else begin
+      // pipeline latch enable for CAL1_IDEL_MAX_TAP - we have plenty
+      // of time, tap count gets updated, then dead cycles waiting for
+      // IDELAY output to settle
+      cal1_idel_max_tap_we <= (cal1_idel_max_tap < cal1_idel_tap_cnt);
+      // record maximum # of taps used for stg 1 cal
+      if ((cal1_state == CAL1_DONE) && cal1_idel_max_tap_we)
+        cal1_idel_max_tap <= cal1_idel_tap_cnt;
+    end
+
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      calib_done[0]            <= 1'b0;
+      calib_done_tmp[0]        <= 1'bx;
+      calib_err[0]             <= 1'b0;
+      count_dq                 <= {DQ_BITS{1'b0}};
+      next_count_dq            <= {DQ_BITS{1'b0}};
+      cal1_bit_time_tap_cnt    <= 6'bxxxxxx;
+      cal1_data_chk_last       <= 2'bxx;
+      cal1_data_chk_last_valid <= 1'bx;
+      cal1_dlyce_dq            <= 1'b0;
+      cal1_dlyinc_dq           <= 1'b0;
+      cal1_dqs_dq_init_phase   <= 1'bx;
+      cal1_first_edge_done     <= 1'bx;
+      cal1_found_second_edge   <= 1'bx;
+      cal1_first_edge_tap_cnt  <= 6'bxxxxxx;
+      cal1_idel_dec_cnt        <= 7'bxxxxxxx;
+      cal1_idel_inc_cnt        <= 6'bxxxxxx;
+      cal1_ref_req             <= 1'b0;
+      cal1_state               <= CAL1_IDLE;
+    end else begin
+      // default values for all "pulse" outputs
+      cal1_ref_req        <= 1'b0;
+      cal1_dlyce_dq       <= 1'b0;
+      cal1_dlyinc_dq      <= 1'b0;
+
+      case (cal1_state)
+        CAL1_IDLE: begin
+          count_dq      <= {DQ_BITS{1'b0}};
+          next_count_dq <= {DQ_BITS{1'b0}};
+          if (calib_start[0]) begin
+            calib_done[0] <= 1'b0;
+            calib_done_tmp[0] <= 1'b0;
+            cal1_state    <= CAL1_INIT;
+          end
+        end
+
+        CAL1_INIT: begin
+          cal1_data_chk_last_valid <= 1'b0;
+          cal1_found_second_edge <= 1'b0;
+          cal1_dqs_dq_init_phase <= 1'b0;
+          cal1_idel_inc_cnt      <= 6'b000000;
+          cal1_state <= CAL1_INC_IDEL;
+        end
+
+        // increment DQ IDELAY so that either: (1) DQS starts somewhere in
+        // first rising DQ window, or (2) DQS starts in first falling DQ
+        // window. The amount to shift is frequency dependent (and is either
+        // precalculated by MIG or possibly adjusted by the user)
+        CAL1_INC_IDEL:
+          if ((cal1_idel_inc_cnt == DQ_IDEL_INIT) && !idel_set_wait) begin
+            cal1_state <= CAL1_FIND_FIRST_EDGE;
+          end else if (cal1_idel_inc_cnt != DQ_IDEL_INIT) begin
+            cal1_idel_inc_cnt <= cal1_idel_inc_cnt + 1;
+            cal1_dlyce_dq <= 1'b1;
+            cal1_dlyinc_dq <= 1'b1;
+          end
+
+        // look for first edge
+        CAL1_FIND_FIRST_EDGE: begin
+          // Determine DQS-DQ phase if we can detect enough of a valid window
+          if (cal1_found_window)
+            cal1_dqs_dq_init_phase <= ~cal1_found_rising;
+          // find first edge - if found then record position
+          if (cal1_detect_edge) begin
+            cal1_state <= CAL1_FOUND_FIRST_EDGE_WAIT;
+            cal1_first_edge_done   <= 1'b0;
+            cal1_first_edge_tap_cnt <= cal1_idel_tap_cnt;
+            cal1_data_chk_last_valid <= 1'b0;
+          end else begin
+            // otherwise, store the current value of DATA_CHK, increment
+            // DQ IDELAY, and compare again
+            cal1_state <= CAL1_FIRST_EDGE_IDEL_WAIT;
+            cal1_data_chk_last <= cal1_data_chk_r;
+            // avoid comparing against DATA_CHK_LAST for previous iteration
+            cal1_data_chk_last_valid <= 1'b1;
+            cal1_dlyce_dq <= 1'b1;
+            cal1_dlyinc_dq <= 1'b1;
+          end
+        end
+
+        // wait for DQ IDELAY to settle
+        CAL1_FIRST_EDGE_IDEL_WAIT:
+          if (!idel_set_wait)
+            cal1_state <= CAL1_FIND_FIRST_EDGE;
+
+        // delay state between finding first edge and looking for second
+        // edge. Necessary in order to invalidate CAL1_FOUND_WINDOW before
+        // starting to look for second edge
+        CAL1_FOUND_FIRST_EDGE_WAIT:
+          cal1_state <= CAL1_FIND_SECOND_EDGE;
+
+        // Try and find second edge
+        CAL1_FIND_SECOND_EDGE: begin
+          // When looking for 2nd edge, first make sure data stabilized (by
+          // detecting valid data window) - needed to avoid false edges
+          if (cal1_found_window) begin
+            cal1_first_edge_done <= 1'b1;
+            cal1_dqs_dq_init_phase <= cal1_found_rising;
+          end
+          // exit if run out of taps to increment
+          if (cal1_idel_tap_limit_hit)
+            cal1_state <= CAL1_CALC_IDEL;
+          else begin
+            // found second edge, record the current edge count
+            if (cal1_first_edge_done && cal1_detect_edge) begin
+              cal1_state <= CAL1_CALC_IDEL;
+              cal1_found_second_edge <= 1'b1;
+              cal1_bit_time_tap_cnt <= cal1_idel_tap_cnt -
+                                       cal1_first_edge_tap_cnt + 1;
+            end else begin
+              cal1_state <= CAL1_SECOND_EDGE_IDEL_WAIT;
+              cal1_data_chk_last <= cal1_data_chk_r;
+              cal1_data_chk_last_valid <= 1'b1;
+              cal1_dlyce_dq <= 1'b1;
+              cal1_dlyinc_dq <= 1'b1;
+            end
+          end
+        end
+
+        // wait for DQ IDELAY to settle, then store ISERDES output
+        CAL1_SECOND_EDGE_IDEL_WAIT:
+          if (!idel_set_wait)
+            cal1_state <= CAL1_FIND_SECOND_EDGE;
+
+        // pipeline delay state to calculate amount to decrement DQ IDELAY
+        // NOTE: We're calculating the amount to decrement by, not the
+        //  absolute setting for DQ IDELAY
+        CAL1_CALC_IDEL: begin
+          // if two edges found
+          if (cal1_found_second_edge)
+            // case 1: DQS was in DQ window to start with. First edge found
+            // corresponds to left edge of DQ rising window. Backup by 1.5*BT
+            // NOTE: In this particular case, it is possible to decrement
+            //  "below 0" in the case where DQS delay is less than 0.5*BT,
+            //  need to limit decrement to prevent IDELAY tap underflow
+            if (!cal1_dqs_dq_init_phase)
+              cal1_idel_dec_cnt <= {1'b0, cal1_bit_time_tap_cnt} +
+                                   {1'b0, (cal1_bit_time_tap_cnt >> 1)};
+            // case 2: DQS was in wrong DQ window (in DQ falling window).
+            // First edge found is right edge of DQ rising window. Second
+            // edge is left edge of DQ rising window. Backup by 0.5*BT
+            else
+              cal1_idel_dec_cnt <= {1'b0, (cal1_bit_time_tap_cnt >> 1)};
+          // if only one edge found - assume will always be case 1 - DQS in
+          // DQS window. Case 2 only possible if path delay on DQS > 5ns
+          else
+            cal1_idel_dec_cnt <= cal1_low_freq_idel_dec;
+          cal1_state <= CAL1_DEC_IDEL;
+        end
+
+        // decrement DQ IDELAY for final adjustment
+        CAL1_DEC_IDEL:
+          // once adjustment is complete, we're done with calibration for
+          // this DQ, now return to IDLE state and repeat for next DQ
+          // Add underflow protection for case of 2 edges found and DQS
+          // starting in DQ window (see comments for above state) - note we
+          // have to take into account delayed value of CAL1_IDEL_TAP_CNT -
+          // gets updated one clock cycle after CAL1_DLYCE/INC_DQ
+          if ((cal1_idel_dec_cnt == 7'b0000000) ||
+              (cal1_dlyce_dq && (cal1_idel_tap_cnt == 6'b000001))) begin
+            cal1_state <= CAL1_DONE;
+            // stop when all DQ's calibrated, or DQ[0] cal'ed (for sim)
+            if ((count_dq == DQ_WIDTH-1) || (SIM_ONLY != 0))
+              calib_done_tmp[0] <= 1'b1;
+            else
+              // need for VHDL simulation to prevent out-of-index error
+              next_count_dq <= count_dq + 1;
+          end else begin
+            // keep decrementing until final tap count reached
+            cal1_idel_dec_cnt <= cal1_idel_dec_cnt - 1;
+            cal1_dlyce_dq <= 1'b1;
+            cal1_dlyinc_dq <= 1'b0;
+          end
+
+        // delay state to allow count_dq and DATA_CHK to point to the next
+        // DQ bit (allows us to potentially begin checking for an edge on
+        // next DQ right away).
+        CAL1_DONE:
+          if (!idel_set_wait) begin
+            count_dq <= next_count_dq;
+            if (calib_done_tmp[0]) begin
+              calib_done[0] <= 1'b1;
+              cal1_state <= CAL1_IDLE;
+            end else begin
+              // request auto-refresh after every 8-bits calibrated to
+              // avoid tRAS violation
+              if (cal1_refresh) begin
+                cal1_ref_req <= 1'b1;
+                if (calib_ref_done)
+                  cal1_state <= CAL1_INIT;
+              end else
+                // if no need this time for refresh, proceed to next bit
+                cal1_state <= CAL1_INIT;
+            end
+          end
+      endcase
+    end
+
+  //***************************************************************************
+  // Second stage calibration: DQS-FPGA Clock
+  // Algorithm Description:
+  //  1. Assumes a training pattern that will produce a pattern oscillating at
+  //     half the core clock frequency each on rise and fall outputs, and such
+  //     that rise and fall outputs are 180 degrees out of phase from each
+  //     other. Note that since the calibration logic runs at half the speed
+  //     of the interface, expect that data sampled with the slow clock always
+  //     to be constant (either always = 1, or = 0, and rise data != fall data)
+  //     unless we cross the edge of the data valid window
+  //  2. Start by setting RD_DATA_SEL = 0. This selects the rising capture data
+  //     sync'ed to rising edge of core clock, and falling edge data sync'ed
+  //     to falling edge of core clock
+  //  3. Start looking for an edge. An edge is defined as either: (1) a
+  //     change in capture value or (2) an invalid capture value (e.g. rising
+  //     data != falling data for that same clock cycle).
+  //  4. If an edge is found, go to step (6). If edge hasn't been found, then
+  //     set RD_DATA_SEL = 1, and try again.
+  //  5. If no edge is found, then increment IDELAY and return to step (3)
+  //  6. If an edge if found, then invert RD_DATA_SEL - this shifts the
+  //     capture point 180 degrees from the edge of the window (minus duty
+  //     cycle distortion, delay skew between rising/falling edge capture
+  //     paths, etc.)
+  //  7. If no edge is found by CAL2_IDEL_TAP_LIMIT (= 63 - # taps used for
+  //     stage 1 calibration), then decrement IDELAY (without reinverting
+  //     RD_DATA_SEL) by CAL2_IDEL_TAP_LIMIT/2. This guarantees we at least
+  //     have CAL2_IDEL_TAP_LIMIT/2 of slack both before and after the
+  //     capture point (not optimal, but best we can do not having found an
+  //     of the window). This happens only for very low frequencies.
+  //  8. Repeat for each DQS group.
+  //  NOTE: Step 6 is not optimal. A better (and perhaps more complicated)
+  //   algorithm might be to find both edges of the data valid window (using
+  //   the same polarity of RD_DATA_SEL), and then decrement to the midpoint.
+  //***************************************************************************
+
+  // RD_DATA_SEL should be tagged with FROM-TO (multi-cycle) constraint in
+  // UCF file to relax timing. This net is "pseudo-static" (after value is
+  // changed, FSM waits number of cycles before using the output).
+  // Note that we are adding one clock cycle of delay (to isolate it from
+  // the other logic CAL2_RD_DATA_SEL feeds), make sure FSM waits long
+  // enough to compensate (by default it does, it waits a few cycles more
+  // than minimum # of clock cycles)
+  genvar rd_i;
+  generate
+    for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rd_data_sel
+      FDRSE u_ff_rd_data_sel
+        (
+         .Q   (rd_data_sel[rd_i]),
+         .C   (clkdiv),
+         .CE  (1'b1),
+         .D   (cal2_rd_data_sel[rd_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */
+           /* synthesis syn_replicate = 0 */;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // Max number of taps used for stg2 cal dependent on number of taps
+  // used for stg1 (give priority to stg1 cal - let it use as many
+  // taps as it needs - the remainder of the IDELAY taps can be used
+  // by stg2)
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    cal2_idel_tap_limit <= 6'b111111 - cal1_idel_max_tap;
+
+  //*****************************************************************
+  // second stage calibration uses readback pattern of "1100" (i.e.
+  // 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
+  // only look at the first bit of each DQS group
+  //*****************************************************************
+
+  // deasserted when captured data has changed since IDELAY was
+  // incremented, or when we're right on the edge (i.e. rise data =
+  // fall data).
+  assign cal2_detect_edge =
+    ((((rdd_rise_q1 != cal2_rd_data_rise_last_pos) ||
+       (rdd_fall_q1 != cal2_rd_data_fall_last_pos)) &&
+      cal2_rd_data_last_valid_pos && (!cal2_curr_sel)) ||
+     (((rdd_rise_q1 != cal2_rd_data_rise_last_neg) ||
+       (rdd_fall_q1 != cal2_rd_data_fall_last_neg)) &&
+      cal2_rd_data_last_valid_neg && (cal2_curr_sel)) ||
+     (rdd_rise_q1 != rdd_fall_q1));
+
+  //*****************************************************************
+  // keep track of edge tap counts found, and whether we've
+  // incremented to the maximum number of taps allowed
+  // NOTE: Assume stage 2 cal always increments the tap count (never
+  //       decrements) when searching for edge of the data valid window
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (cal2_state == CAL2_INIT) begin
+      cal2_idel_tap_limit_hit <= 1'b0;
+      cal2_idel_tap_cnt <= 6'b000000;
+    end else if (cal2_dlyce_dqs) begin
+      cal2_idel_tap_cnt <= cal2_idel_tap_cnt + 1;
+      cal2_idel_tap_limit_hit <= (cal2_idel_tap_cnt ==
+                                  cal2_idel_tap_limit - 1);
+    end
+
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      calib_done[1]               <= 1'b0;
+      calib_done_tmp[1]           <= 1'bx;
+      calib_err[1]                <= 1'b0;
+      count_dqs                   <= 'b0;
+      next_count_dqs              <= 'b0;
+      cal2_dlyce_dqs              <= 1'b0;
+      cal2_dlyinc_dqs             <= 1'b0;
+      cal2_idel_dec_cnt           <= 6'bxxxxxx;
+      cal2_rd_data_last_valid_neg <= 1'bx;
+      cal2_rd_data_last_valid_pos <= 1'bx;
+      cal2_rd_data_sel            <= 'b0;
+      cal2_ref_req                <= 1'b0;
+      cal2_state                  <= CAL2_IDLE;
+    end else begin
+      cal2_ref_req      <= 1'b0;
+      cal2_dlyce_dqs    <= 1'b0;
+      cal2_dlyinc_dqs   <= 1'b0;
+
+      case (cal2_state)
+        CAL2_IDLE: begin
+          count_dqs      <= 'b0;
+          next_count_dqs <= 'b0;
+          if (calib_start[1]) begin
+            cal2_rd_data_sel  <= {DQS_WIDTH{1'b0}};
+            calib_done[1]     <= 1'b0;
+            calib_done_tmp[1] <= 1'b0;
+            cal2_state        <= CAL2_INIT;
+          end
+        end
+
+        // Pass through this state every time we calibrate a new DQS group
+        CAL2_INIT: begin
+          cal2_curr_sel <= 1'b0;
+          cal2_rd_data_last_valid_neg <= 1'b0;
+          cal2_rd_data_last_valid_pos <= 1'b0;
+          cal2_state <= CAL2_INIT_IDEL_WAIT;
+        end
+
+        // Stall state only used if calibration run more than once. Can take
+        // this state out if design never runs calibration more than once.
+        // We need this state to give time for MUX'ed data to settle after
+        // resetting RD_DATA_SEL
+        CAL2_INIT_IDEL_WAIT:
+          if (!idel_set_wait)
+            cal2_state <= CAL2_FIND_EDGE_POS;
+
+        // Look for an edge - first check "positive-edge" stage 2 capture
+        CAL2_FIND_EDGE_POS: begin
+          // if found an edge, then switch to the opposite edge stage 2
+          // capture and we're done - no need to decrement the tap count,
+          // since switching to the opposite edge will shift the capture
+          // point by 180 degrees
+          if (cal2_detect_edge) begin
+            cal2_curr_sel <= 1'b1;
+            cal2_state <= CAL2_DONE;
+            // set all DQS groups to be the same for simulation
+            if (SIM_ONLY != 0)
+              cal2_rd_data_sel <= {DQS_WIDTH{1'b1}};
+            else
+              cal2_rd_data_sel[count_dqs] <= 1'b1;
+            if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+              calib_done_tmp[1] <= 1'b1;
+           else
+              // MIG 2.1: Fix for simulation out-of-bounds error when
+              // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)  
+             next_count_dqs <= count_dqs + 1;
+          end else begin
+            // otherwise, invert polarity of stage 2 capture and look for
+            // an edge with opposite capture clock polarity
+            cal2_curr_sel <= 1'b1;
+            cal2_rd_data_sel[count_dqs] <= 1'b1;
+            cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_POS;
+            cal2_rd_data_rise_last_pos  <= rdd_rise_q1;
+            cal2_rd_data_fall_last_pos  <= rdd_fall_q1;
+            cal2_rd_data_last_valid_pos <= 1'b1;
+          end
+        end
+
+        // Give time to switch from positive-edge to negative-edge second
+        // stage capture (need time for data to filter though pipe stages)
+        CAL2_FIND_EDGE_IDEL_WAIT_POS:
+          if (!idel_set_wait)
+            cal2_state <= CAL2_FIND_EDGE_NEG;
+
+        // Look for an edge - check "negative-edge" stage 2 capture
+        CAL2_FIND_EDGE_NEG:
+          if (cal2_detect_edge) begin
+            cal2_curr_sel <= 1'b0;
+            cal2_state <= CAL2_DONE;
+            // set all DQS groups to be the same for simulation
+            if (SIM_ONLY != 0)
+              cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
+            else
+              cal2_rd_data_sel[count_dqs] <= 1'b0;
+            if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+              calib_done_tmp[1] <= 1'b1;
+           else
+              // MIG 2.1: Fix for simulation out-of-bounds error when
+              // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
+             next_count_dqs <= count_dqs + 1;
+          end else if (cal2_idel_tap_limit_hit) begin
+            // otherwise, if we've run out of taps, then immediately
+            // backoff by half # of taps used - that's our best estimate
+            // for optimal calibration point. Doesn't matter whether which
+            // polarity we're using for capture (we don't know which one is
+            // best to use)
+            cal2_idel_dec_cnt <= {1'b0, cal2_idel_tap_limit[5:1]};
+            cal2_state <= CAL2_DEC_IDEL;
+            if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+              calib_done_tmp[1] <= 1'b1;
+           else
+              // MIG 2.1: Fix for simulation out-of-bounds error when
+              // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
+             next_count_dqs <= count_dqs + 1;
+          end else begin
+            // otherwise, increment IDELAY, and start looking for edge again
+            cal2_curr_sel <= 1'b0;
+            cal2_rd_data_sel[count_dqs] <= 1'b0;
+            cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_NEG;
+            cal2_rd_data_rise_last_neg  <= rdd_rise_q1;
+            cal2_rd_data_fall_last_neg  <= rdd_fall_q1;
+            cal2_rd_data_last_valid_neg <= 1'b1;
+            cal2_dlyce_dqs  <= 1'b1;
+            cal2_dlyinc_dqs <= 1'b1;
+          end
+
+        CAL2_FIND_EDGE_IDEL_WAIT_NEG:
+          if (!idel_set_wait)
+            cal2_state <= CAL2_FIND_EDGE_POS;
+
+        // if no edge found, then decrement by half # of taps used
+        CAL2_DEC_IDEL: begin
+          if (cal2_idel_dec_cnt == 6'b000000)
+            cal2_state <= CAL2_DONE;
+          else begin
+            cal2_idel_dec_cnt <= cal2_idel_dec_cnt - 1;
+            cal2_dlyce_dqs  <= 1'b1;
+            cal2_dlyinc_dqs <= 1'b0;
+          end
+        end
+
+        // delay state to allow count_dqs and ISERDES data to point to next
+        // DQ bit (DQS group) before going to INIT
+        CAL2_DONE:
+          if (!idel_set_wait) begin
+            count_dqs <= next_count_dqs;
+            if (calib_done_tmp[1]) begin
+              calib_done[1] <= 1'b1;
+              cal2_state <= CAL2_IDLE;
+            end else begin
+              // request auto-refresh after every DQS group calibrated to
+              // avoid tRAS violation
+              cal2_ref_req <= 1'b1;
+              if (calib_ref_done)
+                cal2_state <= CAL2_INIT;
+            end
+          end
+      endcase
+    end
+
+  //***************************************************************************
+  // Stage 3 calibration: Read Enable
+  // Description:
+  // read enable calibration determines the "round-trip" time (in # of CLK0
+  // cycles) between when a read command is issued by the controller, and
+  // when the corresponding read data is synchronized by into the CLK0 domain
+  // this is a long delay chain to delay read enable signal from controller/
+  // initialization logic (i.e. this is used for both initialization and
+  // during normal controller operation). Stage 3 calibration logic decides
+  // which delayed version is appropriate to use (which is affected by the
+  // round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
+  // when the captured data output from ISERDES is valid.
+  //***************************************************************************
+
+  //*****************************************************************
+  // Delay chains: Use shift registers
+  // Two sets of delay chains are used:
+  //  1. One to delay RDEN from PHY_INIT module for calibration
+  //     purposes (delay required for RDEN for calibration is different
+  //     than during normal operation)
+  //  2. One per DQS group to delay RDEN from controller for normal
+  //     operation - the value to delay for each DQS group can be different
+  //     as is determined during calibration
+  //*****************************************************************
+
+  //*****************************************************************
+  // First delay chain, use only for calibration
+  // input = asserted on rising edge of RDEN from PHY_INIT module
+  //*****************************************************************
+
+  always @(posedge clk) begin
+    ctrl_rden_r       <= ctrl_rden;
+    phy_init_rden_r   <= phy_init_rden;
+    phy_init_rden_r1  <= phy_init_rden_r;
+    calib_rden_edge_r <= phy_init_rden_r & ~phy_init_rden_r1;
+  end
+
+  // Calibration shift register used for both Stage 3 and Stage 4 cal
+  // (not strictly necessary for stage 4, but use as an additional check
+  // to make sure we're checking for correct data on the right clock cycle)
+  always @(posedge clkdiv)
+    if (!calib_done[2])
+      calib_rden_srl_a <= cal3_rden_srl_a;
+    else
+      calib_rden_srl_a <= cal4_rden_srl_a;
+
+  // Flops for targetting of multi-cycle path in UCF
+  genvar cal_rden_ff_i;
+  generate
+    for (cal_rden_ff_i = 0; cal_rden_ff_i < 5;
+         cal_rden_ff_i = cal_rden_ff_i+1) begin: gen_cal_rden_dly
+      FDRSE u_ff_cal_rden_dly
+        (
+         .Q   (calib_rden_srl_a_r[cal_rden_ff_i]),
+         .C   (clkdiv),
+         .CE  (1'b1),
+         .D   (calib_rden_srl_a[cal_rden_ff_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */
+           /* synthesis syn_replicate = 0 */;
+    end
+  endgenerate
+
+  SRLC32E u_calib_rden_srl
+    (
+     .Q   (calib_rden_srl_out),
+     .Q31 (),
+     .A   (calib_rden_srl_a_r),
+     .CE  (1'b1),
+     .CLK (clk),
+     .D   (calib_rden_edge_r)
+     );
+
+  FDRSE u_calib_rden_srl_out_r
+    (
+         .Q   (calib_rden_srl_out_r),
+         .C   (clk),
+         .CE  (1'b1),
+         .D   (calib_rden_srl_out),
+         .R   (1'b0),
+         .S   (1'b0)
+     ) /* synthesis syn_preserve = 1 */;
+
+  // convert to CLKDIV domain. Two version are generated because we need
+  // to be able to tell exactly which fast (clk) clock cycle the read
+  // enable was asserted in. Only one of CALIB_DATA_VALID or
+  // CALIB_DATA_VALID_STGD will be asserted for any given shift value
+  always @(posedge clk)
+    calib_rden_srl_out_r1 <= calib_rden_srl_out_r;
+
+  always @(posedge clkdiv) begin
+    calib_rden_valid      <= calib_rden_srl_out_r;
+    calib_rden_valid_stgd <= calib_rden_srl_out_r1;
+  end
+
+  //*****************************************************************
+  // Second set of delays chain, use for normal reads
+  // input = RDEN from controller
+  //*****************************************************************
+
+  // Flops for targetting of multi-cycle path in UCF
+  genvar rden_ff_i;
+  generate
+    for (rden_ff_i = 0; rden_ff_i < 5*DQS_WIDTH;
+         rden_ff_i = rden_ff_i+1) begin: gen_rden_dly
+      FDRSE u_ff_rden_dly
+        (
+         .Q   (rden_dly_r[rden_ff_i]),
+         .C   (clkdiv),
+         .CE  (1'b1),
+         .D   (rden_dly[rden_ff_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */
+           /* synthesis syn_replicate = 0 */;
+    end
+  endgenerate
+
+  // NOTE: Comment this section explaining purpose of SRL's
+  genvar rden_i;
+  generate
+    for (rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
+      SRLC32E u_rden_srl
+        (
+         .Q   (rden_srl_out[rden_i]),
+         .Q31 (),
+         .A   ({rden_dly_r[(rden_i*5)+4],
+                rden_dly_r[(rden_i*5)+3],
+                rden_dly_r[(rden_i*5)+2],
+                rden_dly_r[(rden_i*5)+1],
+                rden_dly_r[(rden_i*5)]}),
+         .CE  (1'b1),
+         .CLK (clk),
+         .D   (ctrl_rden_r)
+         );
+      FDRSE u_calib_rden_r
+        (
+         .Q   (calib_rden[rden_i]),
+         .C   (clk),
+         .CE  (1'b1),
+         .D   (rden_srl_out[rden_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // indicates that current received data is the correct pattern. Check both
+  // rising and falling data for first DQ in each DQS group. Note that
+  // we're checking using a pipelined version of read data, so need to take
+  // this inherent delay into account in determining final read valid delay
+  // Data is written to the memory in the following order (first -> last):
+  //   0x1, 0xE, 0xE, 0x1, 0x1, 0xE, 0xE, 0x1
+  // Looking just at LSb, expect data in sequence (in binary):
+  //   1, 0, 0, 1, 1, 0, 0, 1
+  // Check for the presence of the first 7 words, and compensate read valid
+  // delay accordingly. Don't check last falling edge data, it may be
+  // corrupted by the DQS tri-state glitch at end of read postamble
+  // (glitch protection not yet active until stage 4 cal)
+  //*****************************************************************
+
+  always @(posedge clkdiv) begin
+    rdd_rise_q1_r  <= rdd_rise_q1;
+    rdd_fall_q1_r  <= rdd_fall_q1;
+    rdd_rise_q2_r  <= rdd_rise_q2;
+    rdd_fall_q2_r  <= rdd_fall_q2;
+    rdd_rise_q1_r1 <= rdd_rise_q1_r;
+    rdd_fall_q1_r1 <= rdd_fall_q1_r;
+  end
+
+  always @(posedge clkdiv) begin
+    // For the following sequence from memory:
+    //   rise[0], fall[0], rise[1], fall[1]
+    // if data is aligned out of fabric ISERDES:
+    //   RDD_RISE_Q2 = rise[0]
+    //   RDD_FALL_Q2 = fall[0]
+    //   RDD_RISE_Q1 = rise[1]
+    //   RDD_FALL_Q1 = fall[1]
+    cal3_data_match <= ((rdd_rise_q2_r == 1) &&
+                        (rdd_fall_q2_r == 0) &&
+                        (rdd_rise_q1_r == 0) &&
+                        (rdd_fall_q1_r == 1) &&
+                        (rdd_rise_q2   == 1) &&
+                        (rdd_fall_q2   == 0) &&
+                        (rdd_rise_q1   == 0));
+
+    // if data is staggered out of fabric ISERDES:
+    //   RDD_RISE_Q1_R = rise[0]
+    //   RDD_FALL_Q1_R = fall[0]
+    //   RDD_RISE_Q2   = rise[1]
+    //   RDD_FALL_Q2   = fall[1]
+    cal3_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
+                             (rdd_fall_q1_r1 == 0) &&
+                             (rdd_rise_q2_r  == 0) &&
+                             (rdd_fall_q2_r  == 1) &&
+                             (rdd_rise_q1_r  == 1) &&
+                             (rdd_fall_q1_r  == 0) &&
+                             (rdd_rise_q2    == 0));
+  end
+
+  assign cal3_rden_dly = cal3_rden_srl_a - CAL3_RDEN_SRL_DLY_DELTA;
+  assign cal3_data_valid = (calib_rden_valid | calib_rden_valid_stgd);
+  assign cal3_match_found
+    = ((calib_rden_valid && cal3_data_match) ||
+       (calib_rden_valid_stgd && cal3_data_match_stgd));
+
+  // when calibrating, check to see which clock cycle (after the read is
+  // issued) does the expected data pattern arrive. Record this result
+  // NOTE: Can add error checking here in case valid data not found on any
+  //  of the available pipeline stages
+  always @(posedge clkdiv) begin
+    if (rstdiv) begin
+      cal3_rden_srl_a <= 5'bxxxxx;
+      cal3_state      <= CAL3_IDLE;
+      calib_done[2]   <= 1'b0;
+      calib_err_2[0]  <= 1'b0;
+      count_rden      <= {DQS_WIDTH{1'b0}};
+      rden_dly        <= {5*DQS_WIDTH{1'b0}};
+    end else begin
+
+      case (cal3_state)
+        CAL3_IDLE: begin
+          count_rden <= {DQS_WIDTH{1'b0}};
+          if (calib_start[2]) begin
+            calib_done[2] <= 1'b0;
+            cal3_state    <= CAL3_INIT;
+          end
+        end
+
+        CAL3_INIT: begin
+          cal3_rden_srl_a <= RDEN_BASE_DELAY;
+          // let SRL pipe clear after loading initial shift value
+          cal3_state      <= CAL3_RDEN_PIPE_CLR_WAIT;
+        end
+
+        CAL3_DETECT:
+          if (cal3_data_valid)
+            // if match found at the correct clock cycle
+            if (cal3_match_found) begin
+
+              // For simulation, load SRL addresses for all DQS with same value
+              if (SIM_ONLY != 0) begin
+                for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_rden_dly
+                  rden_dly[(i*5)]   <= cal3_rden_dly[0];
+                  rden_dly[(i*5)+1] <= cal3_rden_dly[1];
+                  rden_dly[(i*5)+2] <= cal3_rden_dly[2];
+                  rden_dly[(i*5)+3] <= cal3_rden_dly[3];
+                  rden_dly[(i*5)+4] <= cal3_rden_dly[4];
+                end
+              end else begin
+                rden_dly[(count_rden*5)]   <= cal3_rden_dly[0];
+                rden_dly[(count_rden*5)+1] <= cal3_rden_dly[1];
+                rden_dly[(count_rden*5)+2] <= cal3_rden_dly[2];
+                rden_dly[(count_rden*5)+3] <= cal3_rden_dly[3];
+                rden_dly[(count_rden*5)+4] <= cal3_rden_dly[4];
+              end
+
+              // Use for stage 4 calibration
+              calib_rden_dly[(count_rden*5)]   <= cal3_rden_srl_a[0];
+              calib_rden_dly[(count_rden*5)+1] <= cal3_rden_srl_a[1];
+              calib_rden_dly[(count_rden*5)+2] <= cal3_rden_srl_a[2];
+              calib_rden_dly[(count_rden*5)+3] <= cal3_rden_srl_a[3];
+              calib_rden_dly[(count_rden*5)+4] <= cal3_rden_srl_a[4];
+              cal3_state <= CAL3_DONE;
+            end else begin
+              // If we run out of stages to shift, without finding correct
+              // result, the stop and assert error
+              if (cal3_rden_srl_a == 5'b11111) begin
+                calib_err_2[0] <= 1'b1;
+                cal3_state   <= CAL3_IDLE;
+              end else begin
+                // otherwise, increase the shift value and try again
+                cal3_rden_srl_a <= cal3_rden_srl_a + 1;
+                cal3_state      <= CAL3_RDEN_PIPE_CLR_WAIT;
+              end
+            end
+
+        // give additional time for RDEN_R pipe to clear from effects of
+        // previous pipeline or IDELAY tap change
+        CAL3_RDEN_PIPE_CLR_WAIT:
+          if (calib_rden_pipe_cnt == 5'b00000)
+              cal3_state <= CAL3_DETECT;
+
+        CAL3_DONE: begin
+          if ((count_rden == DQS_WIDTH-1) || (SIM_ONLY != 0)) begin
+            calib_done[2] <= 1'b1;
+            cal3_state    <= CAL3_IDLE;
+          end else begin
+            count_rden    <= count_rden + 1;
+            cal3_state    <= CAL3_INIT;
+          end
+        end
+      endcase
+    end
+  end
+
+  //*****************************************************************
+  // Last part of stage 3 calibration - compensate for differences
+  // in delay between different DQS groups. Assume that in the worst
+  // case, DQS groups can only differ by one clock cycle. Data for
+  // certain DQS groups must be delayed by one clock cycle.
+  // NOTE: May need to increase allowable variation to greater than
+  //  one clock cycle in certain customer designs.
+  // Algorithm is:
+  //   1. Record shift delay value for DQS[0]
+  //   2. Compare each DQS[x] delay value to that of DQS[0]:
+  //     - If different, than record this fact (RDEN_MUX)
+  //     - If greater than DQS[0], set RDEN_INC. Assume greater by
+  //       one clock cycle only - this is a key assumption, assume no
+  //       more than a one clock cycle variation.
+  //     - If less than DQS[0], set RDEN_DEC
+  //   3. After calibration is complete, set control for DQS group
+  //      delay (CALIB_RDEN_SEL):
+  //     - If RDEN_DEC = 1, then assume that DQS[0] is the lowest
+  //       delay (and at least one other DQS group has a higher
+  //       delay).
+  //     - If RDEN_INC = 1, then assume that DQS[0] is the highest
+  //       delay (and that all other DQS groups have the same or
+  //       lower delay).
+  //     - If both RDEN_INC and RDEN_DEC = 1, then flag error
+  //       (variation is too high for this algorithm to handle)
+  //*****************************************************************
+
+  always @(posedge clkdiv) begin
+    if (rstdiv) begin
+      calib_err_2[1] <= 1'b0;
+      calib_rden_sel <= {DQS_WIDTH{1'bx}};
+      rden_dec       <= 1'b0;
+      rden_dly_0     <= 5'bxxxxx;
+      rden_inc       <= 1'b0;
+      rden_mux       <= {DQS_WIDTH{1'b0}};
+    end else begin
+      // if a match if found, then store the value of rden_dly
+      if (!calib_done[2]) begin
+        if ((cal3_state == CAL3_DETECT) && cal3_match_found) begin
+          // store the value for DQS[0] as a reference
+          if (count_rden == 0) begin
+            // for simulation, RDEN calibration only happens for DQS[0]
+            // set RDEN_MUX for all DQS groups to be the same as DQS[0]
+            if (SIM_ONLY != 0)
+              rden_mux <= {DQS_WIDTH{1'b0}};
+            else begin
+              // otherwise, load values for DQS[0]
+              rden_dly_0  <= cal3_rden_srl_a;
+              rden_mux[0] <= 1'b0;
+            end
+          end else if (SIM_ONLY == 0) begin
+            // for all other DQS groups, compare RDEN_DLY delay value with
+            // that of DQS[0]
+            if (rden_dly_0 != cal3_rden_srl_a) begin
+              // record that current DQS group has a different delay
+              // than DQS[0] (the "reference" DQS group)
+              rden_mux[count_rden] <= 1'b1;
+              if (rden_dly_0 > cal3_rden_srl_a)
+                rden_inc <= 1'b1;
+              else if (rden_dly_0 < cal3_rden_srl_a)
+                rden_dec <= 1'b1;
+              // otherwise, if current DQS group has same delay as DQS[0],
+              // then rden_mux[count_rden] remains at 0 (since rden_mux
+              // array contents initialized to 0)
+            end
+          end
+        end
+      end else begin
+        // Otherwise - if we're done w/ stage 2 calibration:
+        // set final value for RDEN data delay
+        // flag error if there's more than one cycle variation from DQS[0]
+        calib_err_2[1] <= (rden_inc && rden_dec);
+        if (rden_inc)
+          // if DQS[0] delay represents max delay
+          calib_rden_sel <= ~rden_mux;
+        else
+          // if DQS[0] delay represents min delay (or all the delays are
+          // the same between DQS groups)
+          calib_rden_sel <= rden_mux;
+      end
+    end
+  end
+
+  // flag error for stage 3 if appropriate
+  always @(posedge clkdiv)
+    calib_err[2] <= calib_err_2[0] | calib_err_2[1];
+
+  //***************************************************************************
+  // Stage 4 calibration: DQS gate
+  //***************************************************************************
+
+  //*****************************************************************
+  // indicates that current received data is the correct pattern. Same as
+  // for READ VALID calibration, except that the expected data sequence is
+  // different since DQS gate is asserted after the 6th word.
+  // Data sequence:
+  //  Arrives from memory (at FPGA input) (R, F): 1 0 0 1 1 0 0 1
+  //  After gating the sequence looks like: 1 0 0 1 1 0 1 0 (7th word =
+  //   5th word, 8th word = 6th word)
+  // What is the gate timing is off? Need to make sure we can distinquish
+  // between the results of correct vs. incorrect gate timing. We also use
+  // the "read_valid" signal from stage 3 calibration to help us determine
+  // when to check for a valid sequence for stage 4 calibration (i.e. use
+  // CAL4_DATA_VALID in addition to CAL4_DATA_MATCH/CAL4_DATA_MATCH_STGD)
+  // Note that since the gate signal from the CLK0 domain is synchronized
+  // to the falling edge of DQS, that the effect of the gate will only be
+  // seen starting with a rising edge data (although it is possible
+  // the GATE IDDR output could go metastable and cause a unexpected result
+  // on the first rising and falling edges after the gate is enabled). 
+  // Also note that the actual DQS glitch can come more than 0.5*tCK after 
+  // the last falling edge of DQS and the constraint for this path is can 
+  // be > 0.5*tCK; however, this means when calibrating, the output of the 
+  // GATE IDDR may miss the setup time requirement of the rising edge flop 
+  // and only meet it for the falling edge flop. Therefore the rising
+  // edge data immediately following the assertion of the gate can either
+  // be a 1 or 0 (can rely on either)
+  // As the timing on the gate is varied, we expect to see (sequence of
+  // captured read data shown below):
+  //       - 1 0 0 1 1 0 0 1 (gate is really early, starts and ends before
+  //                          read burst even starts)
+  //       - x 0 0 1 1 0 0 1 (gate pulse starts before the burst, and ends
+  //       - x y 0 1 1 0 0 1  sometime during the burst; x,y = 0, or 1, but 
+  //       - x y x 1 1 0 0 1  all bits that show an x are the same value, 
+  //       - x y x y 1 0 0 1  and y are the same value)
+  //       - x y x y x 0 0 1
+  //       - x y x y x y 0 1 (gate starts just before start of burst)
+  //       - 1 0 x 0 x 0 x 0 (gate starts after 1st falling word. The "x"
+  //                          represents possiblity that gate may not disable
+  //                          clock for 2nd rising word in time)
+  //       - 1 0 0 1 x 1 x 1 (gate starts after 2nd falling word)
+  //       - 1 0 0 1 1 0 x 0 (gate starts after 3rd falling word - GOOD!!)
+  //       - 1 0 0 1 1 0 0 1 (gate starts after burst is already done)
+  //*****************************************************************
+
+  assign cal4_data_valid = calib_rden_valid | calib_rden_valid_stgd;
+  assign cal4_data_good  = (calib_rden_valid &
+                            cal4_data_match) |
+                           (calib_rden_valid_stgd &
+                            cal4_data_match_stgd);
+
+  always @(posedge clkdiv) begin
+    // if data is aligned out of fabric ISERDES:
+    cal4_data_match <= ((rdd_rise_q2_r == 1) &&
+                        (rdd_fall_q2_r == 0) &&
+                        (rdd_rise_q1_r == 0) &&
+                        (rdd_fall_q1_r == 1) &&
+                        (rdd_rise_q2   == 1) &&
+                        (rdd_fall_q2   == 0) &&
+                       // MIG 2.1: Last rising edge data value not
+                       // guaranteed to be certain value at higher
+                       // frequencies
+                       // (rdd_rise_q1   == 0) &&
+                        (rdd_fall_q1   == 0));
+    // if data is staggered out of fabric ISERDES:
+    cal4_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
+                             (rdd_fall_q1_r1 == 0) &&
+                             (rdd_rise_q2_r  == 0) &&
+                             (rdd_fall_q2_r  == 1) &&
+                             (rdd_rise_q1_r  == 1) &&
+                             (rdd_fall_q1_r  == 0) &&
+                            // MIG 2.1: Last rising edge data value not
+                            // guaranteed to be certain value at higher
+                            // frequencies
+                            // (rdd_rise_q2    == 0) &&
+                             (rdd_fall_q2    == 0));
+  end
+
+  //*****************************************************************
+  // DQS gate enable generation:
+  // This signal gets synchronized to DQS domain, and drives IDDR
+  // register that in turn asserts/deasserts CE to all 4 or 8 DQ
+  // IDDR's in that DQS group.
+  //   1. During normal (post-cal) operation, this is only for 2 clock
+  //      cycles following the end of a burst. Check for falling edge
+  //      of RDEN. But must also make sure NOT assert for a read-idle-
+  //      read (two non-consecutive reads, separated by exactly one
+  //      idle cycle) - in this case, don't assert the gate because:
+  //      (1) we don't have enough time to deassert the gate before the
+  //          first rising edge of DQS for second burst (b/c of fact
+  //          that DQS gate is generated in the fabric only off rising
+  //          edge of CLK0 - if we somehow had an ODDR in fabric, we
+  //          could pull this off, (2) assumption is that the DQS glitch
+  //          will not rise enough to cause a glitch because the
+  //          post-amble of the first burst is followed immediately by
+  //          the pre-amble of the next burst
+  //   2. During stage 4 calibration, assert for 3 clock cycles
+  //      (assert gate enable one clock cycle early), since we gate out
+  //      the last two words (in addition to the crap on the DQ bus after
+  //      the DQS read postamble).
+  // NOTE: PHY_INIT_RDEN and CTRL_RDEN have slightly different timing w/r
+  //  to when they are asserted w/r to the start of the read burst
+  //  (PHY_INIT_RDEN is one cycle earlier than CTRL_RDEN).
+  //*****************************************************************
+
+  // register for timing purposes for fast clock path - currently only
+  // calib_done_r[2] used
+  always @(posedge clk)
+    calib_done_r <= calib_done;
+
+  always @(*) begin
+    calib_ctrl_rden = ctrl_rden;
+    calib_init_rden = calib_done_r[2] & phy_init_rden;
+  end
+
+  assign calib_ctrl_rden_negedge = ~calib_ctrl_rden & calib_ctrl_rden_r;
+  // check for read-idle-read before asserting DQS pulse at end of read
+  assign calib_ctrl_gate_pulse   = calib_ctrl_rden_negedge_r &
+                                   ~calib_ctrl_rden;
+  always @(posedge clk) begin
+    calib_ctrl_rden_r         <= calib_ctrl_rden;
+    calib_ctrl_rden_negedge_r <= calib_ctrl_rden_negedge;
+    calib_ctrl_gate_pulse_r   <= calib_ctrl_gate_pulse;
+  end
+
+  assign calib_init_gate_pulse = ~calib_init_rden & calib_init_rden_r;
+  always @(posedge clk) begin
+    calib_init_rden_r        <= calib_init_rden;
+    calib_init_gate_pulse_r  <= calib_init_gate_pulse;
+    calib_init_gate_pulse_r1 <= calib_init_gate_pulse_r;
+  end
+
+  // Gate is asserted: (1) during cal, for 3 cycles, starting 1 cycle
+  // after falling edge of CTRL_RDEN, (2) during normal ops, for 2
+  // cycles, starting 2 cycles after falling edge of CTRL_RDEN
+  assign gate_srl_in = ~((calib_ctrl_gate_pulse |
+                          calib_ctrl_gate_pulse_r) |
+                         (calib_init_gate_pulse   |
+                          calib_init_gate_pulse_r |
+                          calib_init_gate_pulse_r1));
+
+  //*****************************************************************
+  // generate DQS enable signal for each DQS group
+  // There are differences between DQS gate signal for calibration vs. during
+  // normal operation:
+  //  * calibration gates the second to last clock cycle of the burst,
+  //    rather than after the last word (e.g. for a 8-word, 4-cycle burst,
+  //    cycle 4 is gated for calibration; during normal operation, cycle
+  //    5 (i.e. cycle after the last word) is gated)
+  // enable for DQS is deasserted for two clock cycles, except when
+  // we have the preamble for the next read immediately following
+  // the postamble of the current read - assume DQS does not glitch
+  // during this time, that it stays low. Also if we did have to gate
+  // the DQS for this case, then we don't have enough time to deassert
+  // the gate in time for the first rising edge of DQS for the second
+  // read
+  //*****************************************************************
+
+  // Flops for targetting of multi-cycle path in UCF
+  genvar gate_ff_i;
+  generate
+    for (gate_ff_i = 0; gate_ff_i < 5*DQS_WIDTH;
+         gate_ff_i = gate_ff_i+1) begin: gen_gate_dly
+      FDRSE u_ff_gate_dly
+        (
+         .Q   (gate_dly_r[gate_ff_i]),
+         .C   (clkdiv),
+         .CE  (1'b1),
+         .D   (gate_dly[gate_ff_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */
+           /* synthesis syn_replicate = 0 */;
+    end
+  endgenerate
+
+  genvar gate_i;
+  generate
+    for (gate_i = 0; gate_i < DQS_WIDTH; gate_i = gate_i + 1) begin: gen_gate
+      SRLC32E u_gate_srl
+        (
+         .Q   (gate_srl_out[gate_i]),
+         .Q31 (),
+         .A   ({gate_dly_r[(gate_i*5)+4],
+                gate_dly_r[(gate_i*5)+3],
+                gate_dly_r[(gate_i*5)+2],
+                gate_dly_r[(gate_i*5)+1],
+                gate_dly_r[(gate_i*5)]}),
+         .CE  (1'b1),
+         .CLK (clk),
+         .D   (gate_srl_in)
+         );
+
+      // For GATE_BASE_DELAY > 0, have one extra cycle to register outputs
+      // from controller before generating DQS gate pulse. In PAR, the
+      // location of the controller logic can be far from the DQS gate
+      // logic (DQS gate logic located near the DQS I/O's), contributing
+      // to large net delays. Registering the controller outputs for
+      // CL >= 4 (above 200MHz) adds a stage of pipelining to reduce net
+      // delays
+      if (GATE_BASE_DELAY > 0) begin: gen_gate_base_dly_gt3
+        // add flop between SRL32 and EN_DQS flop (which is located near the
+        // DDR2 IOB's)
+        FDRSE u_gate_srl_ff
+          (
+         .Q   (gate_srl_out_r[gate_i]),
+         .C   (clk),
+         .CE  (1'b1),
+         .D   (gate_srl_out[gate_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+           ) /* synthesis syn_preserve = 1 */;
+      end else begin: gen_gate_base_dly_le3
+        assign gate_srl_out_r[gate_i] = gate_srl_out[gate_i];
+      end
+
+      FDRSE u_en_dqs_ff
+        (
+         .Q   (en_dqs[gate_i]),
+         .C   (clk),
+         .CE  (1'b1),
+         .D   (gate_srl_out_r[gate_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve = 1 */
+           /* synthesis syn_replicate = 0 */;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // Find valid window: keep track of how long we've been in the same data
+  // window. If it's been long enough, then declare that we've found a stable
+  // valid window - in particular, that we're past any region of instability
+  // associated with the edge of the window. Use only when finding left edge
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    // reset before we start to look for window
+    if (cal4_state == CAL4_INIT) begin
+      cal4_window_cnt    <= 4'b0000;
+      cal4_stable_window <= 1'b0;
+    end else if ((cal4_state == CAL4_FIND_EDGE) && cal4_seek_left) begin
+      // if we're looking for left edge, and incrementing IDELAY, count
+      // consecutive taps over which we're in the window
+      if (cal4_data_valid) begin
+        if (cal4_data_good)
+          cal4_window_cnt <= cal4_window_cnt + 1;
+        else
+          cal4_window_cnt <= 4'b0000;
+      end
+
+      if (cal4_window_cnt == MIN_WIN_SIZE-1)
+        cal4_stable_window <= 1'b1;
+    end
+
+  //*****************************************************************
+  // keep track of edge tap counts found, and whether we've
+  // incremented to the maximum number of taps allowed
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if ((cal4_state == CAL4_INIT) || cal4_dlyrst_gate) begin
+      cal4_idel_max_tap <= 1'b0;
+      cal4_idel_bit_tap <= 1'b0;
+      cal4_idel_tap_cnt <= 6'b000000;
+    end else if (cal4_dlyce_gate) begin
+      if (cal4_dlyinc_gate) begin
+        cal4_idel_tap_cnt <= cal4_idel_tap_cnt + 1;
+        cal4_idel_bit_tap <= (cal4_idel_tap_cnt == CAL4_IDEL_BIT_VAL-2);
+        cal4_idel_max_tap <= (cal4_idel_tap_cnt == 6'b111110);
+      end else begin
+        cal4_idel_tap_cnt <= cal4_idel_tap_cnt - 1;
+        cal4_idel_bit_tap <= 1'b0;
+        cal4_idel_max_tap <= 1'b0;
+      end
+    end
+
+  always @(posedge clkdiv)
+    if ((cal4_state != CAL4_RDEN_PIPE_CLR_WAIT) &&
+        (cal3_state != CAL3_RDEN_PIPE_CLR_WAIT))
+      calib_rden_pipe_cnt <= CALIB_RDEN_PIPE_LEN-1;
+    else
+      calib_rden_pipe_cnt <= calib_rden_pipe_cnt - 1;
+
+  //*****************************************************************
+  // Stage 4 cal state machine
+  //*****************************************************************
+
+  always @(posedge clkdiv)
+    if (rstdiv) begin
+      calib_done[3]      <= 1'b0;
+      calib_done_tmp[3]  <= 1'b0;
+      calib_err[3]       <= 1'b0;
+      count_gate         <= 'b0;
+      gate_dly           <= 'b0;
+      next_count_gate    <= 'b0;
+      cal4_idel_adj_cnt  <= 6'bxxxxxx;
+      cal4_dlyce_gate    <= 1'b0;
+      cal4_dlyinc_gate   <= 1'b0;
+      cal4_dlyrst_gate   <= 1'b0;    // reset handled elsewhere in code
+      cal4_gate_srl_a    <= 5'bxxxxx;
+      cal4_rden_srl_a    <= 5'bxxxxx;
+      cal4_ref_req       <= 1'b0;
+      cal4_seek_left     <= 1'bx;
+      cal4_state         <= CAL4_IDLE;
+    end else begin
+      cal4_ref_req     <= 1'b0;
+      cal4_dlyce_gate  <= 1'b0;
+      cal4_dlyinc_gate <= 1'b0;
+      cal4_dlyrst_gate <= 1'b0;
+
+      case (cal4_state)
+        CAL4_IDLE: begin
+          count_gate      <= 'b0;
+          next_count_gate <= 'b0;
+          if (calib_start[3]) begin
+            gate_dly      <= 'b0;
+            calib_done[3] <= 1'b0;
+            cal4_state    <= CAL4_INIT;
+          end
+        end
+
+        CAL4_INIT: begin
+          // load: (1) initial value of gate delay SRL, (2) appropriate
+          // value of RDEN SRL (so that we get correct "data valid" timing)
+          cal4_gate_srl_a <= GATE_BASE_INIT;
+          cal4_rden_srl_a <= {calib_rden_dly[(count_gate*5)+4],
+                              calib_rden_dly[(count_gate*5)+3],
+                              calib_rden_dly[(count_gate*5)+2],
+                              calib_rden_dly[(count_gate*5)+1],
+                              calib_rden_dly[(count_gate*5)]};
+          // let SRL pipe clear after loading initial shift value
+          cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
+        end
+
+        // sort of an initial state - start checking to see whether we're
+        // already in the window or not
+        CAL4_FIND_WINDOW:
+          // decide right away if we start in the proper window - this
+          // determines if we are then looking for the left (trailing) or
+          // right (leading) edge of the data valid window
+          if (cal4_data_valid) begin
+            // if we find a match - then we're already in window, now look
+            // for left edge. Otherwise, look for right edge of window
+            cal4_seek_left  <= cal4_data_good;
+            cal4_state      <= CAL4_FIND_EDGE;
+          end
+
+        CAL4_FIND_EDGE:
+          // don't do anything until the exact clock cycle when to check that
+          // readback data is valid or not
+          if (cal4_data_valid) begin
+            // we're currently in the window, look for left edge of window
+            if (cal4_seek_left) begin
+              // make sure we've passed the right edge before trying to detect
+              // the left edge (i.e. avoid any edge "instability") - else, we
+              // may detect an "false" edge too soon. By design, if we start in
+              // the data valid window, always expect at least
+              // MIN(BIT_TIME_TAPS,32) (-/+ jitter, see below) taps of valid
+              // window before we hit the left edge (this is because when stage
+              // 4 calibration first begins (i.e., gate_dly = 00, and IDELAY =
+              // 00), we're guaranteed to NOT be in the window, and we always
+              // start searching for MIN(BIT_TIME_TAPS,32) for the right edge
+              // of window. If we don't find it, increment gate_dly, and if we
+              // now start in the window, we have at least approximately
+              // CLK_PERIOD-MIN(BIT_TIME_TAPS,32) = MIN(BIT_TIME_TAPS,32) taps.
+              // It's approximately because jitter, noise, etc. can bring this
+              // value down slightly. Because of this (although VERY UNLIKELY),
+              // we have to protect against not decrementing IDELAY below 0
+              // during adjustment phase).
+              if (cal4_stable_window && !cal4_data_good) begin
+                // found left edge of window, dec by MIN(BIT_TIME_TAPS,32)
+                cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
+                cal4_idel_adj_inc <= 1'b0;
+                cal4_state        <= CAL4_ADJ_IDEL;
+              end else begin
+                // Otherwise, keep looking for left edge:
+                if (cal4_idel_max_tap) begin
+                  // ran out of taps looking for left edge (max=63) - happens
+                  // for low frequency case, decrement by 32
+                  cal4_idel_adj_cnt <= 6'b100000;
+                  cal4_idel_adj_inc <= 1'b0;
+                  cal4_state        <= CAL4_ADJ_IDEL;
+                end else begin
+                  cal4_dlyce_gate  <= 1'b1;
+                  cal4_dlyinc_gate <= 1'b1;
+                  cal4_state       <= CAL4_IDEL_WAIT;
+                end
+              end
+            end else begin
+              // looking for right edge of window:
+              // look for the first match - this means we've found the right
+              // (leading) edge of the data valid window, increment by
+              // MIN(BIT_TIME_TAPS,32)
+              if (cal4_data_good) begin
+                cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
+                cal4_idel_adj_inc <= 1'b1;
+                cal4_state        <= CAL4_ADJ_IDEL;
+              end else begin
+                // Otherwise, keep looking:
+                // only look for MIN(BIT_TIME_TAPS,32) taps for right edge,
+                // if we haven't found it, then inc gate delay, try again
+                if (cal4_idel_bit_tap) begin
+                  // if we're already maxed out on gate delay, then error out
+                  // (simulation only - calib_err isn't currently connected)
+                  if (cal4_gate_srl_a == 5'b11111) begin
+                    calib_err[3] <= 1'b1;
+                    cal4_state   <= CAL4_IDLE;
+                  end else begin
+                    // otherwise, increment gate delay count, and start
+                    // over again
+                    cal4_gate_srl_a <= cal4_gate_srl_a + 1;
+                    cal4_dlyrst_gate <= 1'b1;
+                    cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
+                  end
+                end else begin
+                  // keep looking for right edge
+                  cal4_dlyce_gate  <= 1'b1;
+                  cal4_dlyinc_gate <= 1'b1;
+                  cal4_state       <= CAL4_IDEL_WAIT;
+                end
+              end
+            end
+          end
+
+        // wait for GATE IDELAY to settle, after reset or increment
+        CAL4_IDEL_WAIT: begin
+          // For simulation, load SRL addresses for all DQS with same value
+          if (SIM_ONLY != 0) begin
+            for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly
+              gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
+              gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
+              gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
+              gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
+              gate_dly[(i*5)]   <= cal4_gate_srl_a[0];
+            end
+          end else begin
+            gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
+            gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
+            gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
+            gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
+            gate_dly[(count_gate*5)]   <= cal4_gate_srl_a[0];
+          end
+          // check to see if we've found edge of window
+          if (!idel_set_wait)
+            cal4_state <= CAL4_FIND_EDGE;
+        end
+
+        // give additional time for RDEN_R pipe to clear from effects of
+        // previous pipeline (and IDELAY reset)
+        CAL4_RDEN_PIPE_CLR_WAIT: begin
+          // MIG 2.2: Bug fix - make sure to update GATE_DLY count, since
+          // possible for FIND_EDGE->RDEN_PIPE_CLR_WAIT->FIND_WINDOW
+          // transition (i.e. need to make sure the gate count updated in
+          // FIND_EDGE gets reflected in GATE_DLY by the time we reach
+          // state FIND_WINDOW) - previously GATE_DLY only being updated
+          // during state CAL4_IDEL_WAIT
+          if (SIM_ONLY != 0) begin
+            for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly_pipe
+              gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
+              gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
+              gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
+              gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
+              gate_dly[(i*5)]   <= cal4_gate_srl_a[0];
+            end
+          end else begin
+            gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
+            gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
+            gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
+            gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
+            gate_dly[(count_gate*5)]   <= cal4_gate_srl_a[0];
+          end    
+          // look for new window
+          if (calib_rden_pipe_cnt == 5'b00000)
+            cal4_state <= CAL4_FIND_WINDOW;
+       end
+
+        // increment/decrement DQS/DQ IDELAY for final adjustment
+        CAL4_ADJ_IDEL:
+          // add underflow protection for corner case when left edge found
+          // using fewer than MIN(BIT_TIME_TAPS,32) taps
+          if ((cal4_idel_adj_cnt == 6'b000000) ||
+              (cal4_dlyce_gate && !cal4_dlyinc_gate &&
+               (cal4_idel_tap_cnt == 6'b000001))) begin
+            cal4_state <= CAL4_DONE;
+            // stop when all gates calibrated, or gate[0] cal'ed (for sim)
+            if ((count_gate == DQS_WIDTH-1) || (SIM_ONLY != 0))
+              calib_done_tmp[3] <= 1'b1;
+            else
+              // need for VHDL simulation to prevent out-of-index error
+              next_count_gate <= count_gate + 1;
+          end else begin
+            cal4_idel_adj_cnt <= cal4_idel_adj_cnt - 1;
+            cal4_dlyce_gate  <= 1'b1;
+            // whether inc or dec depends on whether left or right edge found
+            cal4_dlyinc_gate <= cal4_idel_adj_inc;
+          end
+
+        // wait for IDELAY output to settle after decrement. Check current
+        // COUNT_GATE value and decide if we're done
+        CAL4_DONE:
+          if (!idel_set_wait) begin
+            count_gate <= next_count_gate;
+            if (calib_done_tmp[3]) begin
+              calib_done[3] <= 1'b1;
+              cal4_state <= CAL4_IDLE;
+            end else begin
+              // request auto-refresh after every DQS group calibrated to
+              // avoid tRAS violation
+              cal4_ref_req <= 1'b1;
+              if (calib_ref_done)
+                cal4_state <= CAL4_INIT;
+            end
+          end
+      endcase
+    end
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_ctl_io.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_ctl_io.v
new file mode 100644 (file)
index 0000000..625a5dc
--- /dev/null
@@ -0,0 +1,306 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_ctl_io.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/29 15:24:03 $
+// \   \  /  \    Date Created: Thu Aug 24 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module puts the memory control signals like address, bank address,
+//   row address strobe, column address strobe, write enable and clock enable
+//   in the IOBs.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_ctl_io #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH    = 2,
+   parameter CKE_WIDTH     = 1,
+   parameter COL_WIDTH     = 10,
+   parameter CS_NUM        = 1,
+   parameter TWO_T_TIME_EN = 0,
+   parameter CS_WIDTH      = 1,
+   parameter ODT_WIDTH     = 1,
+   parameter ROW_WIDTH     = 14,
+   parameter DDR_TYPE      = 1
+   )
+  (
+   input                   clk0,
+   input                   clk90,
+   input                   rst0,
+   input                   rst90,
+   input [ROW_WIDTH-1:0]   ctrl_addr,
+   input [BANK_WIDTH-1:0]  ctrl_ba,
+   input                   ctrl_ras_n,
+   input                   ctrl_cas_n,
+   input                   ctrl_we_n,
+   input [CS_NUM-1:0]      ctrl_cs_n,
+   input [ROW_WIDTH-1:0]   phy_init_addr,
+   input [BANK_WIDTH-1:0]  phy_init_ba,
+   input                   phy_init_ras_n,
+   input                   phy_init_cas_n,
+   input                   phy_init_we_n,
+   input [CS_NUM-1:0]      phy_init_cs_n,
+   input [CKE_WIDTH-1:0]   phy_init_cke,
+   input                   phy_init_data_sel,
+   input [CS_NUM-1:0]      odt,
+   output [ROW_WIDTH-1:0]  ddr_addr,
+   output [BANK_WIDTH-1:0] ddr_ba,
+   output                  ddr_ras_n,
+   output                  ddr_cas_n,
+   output                  ddr_we_n,
+   output [CKE_WIDTH-1:0]  ddr_cke,
+   output [CS_WIDTH-1:0]   ddr_cs_n,
+   output [ODT_WIDTH-1:0]  ddr_odt
+   );
+
+  reg [ROW_WIDTH-1:0]     addr_mux;
+  reg [BANK_WIDTH-1:0]    ba_mux;
+  reg                     cas_n_mux;
+  reg [CS_NUM-1:0]        cs_n_mux;
+  reg                     ras_n_mux;
+  reg                     we_n_mux;
+
+
+
+  //***************************************************************************
+
+
+
+
+  // MUX to choose from either PHY or controller for SDRAM control
+
+  generate // in 2t timing mode the extra register stage cannot be used.
+    if(TWO_T_TIME_EN) begin // the control signals are asserted for two cycles
+      always @(*)begin
+        if (phy_init_data_sel) begin
+          addr_mux  = ctrl_addr;
+          ba_mux    = ctrl_ba;
+          cas_n_mux = ctrl_cas_n;
+          cs_n_mux  = ctrl_cs_n;
+          ras_n_mux = ctrl_ras_n;
+          we_n_mux  = ctrl_we_n;
+        end else begin
+          addr_mux  = phy_init_addr;
+          ba_mux    = phy_init_ba;
+          cas_n_mux = phy_init_cas_n;
+          cs_n_mux  = phy_init_cs_n;
+          ras_n_mux = phy_init_ras_n;
+          we_n_mux  = phy_init_we_n;
+        end
+      end
+    end else begin
+      always @(posedge clk0)begin // register the signals in non 2t mode
+        if (phy_init_data_sel) begin
+          addr_mux <= ctrl_addr;
+          ba_mux <= ctrl_ba;
+          cas_n_mux <= ctrl_cas_n;
+          cs_n_mux <= ctrl_cs_n;
+          ras_n_mux <= ctrl_ras_n;
+          we_n_mux <= ctrl_we_n;
+        end else begin
+          addr_mux <= phy_init_addr;
+          ba_mux <= phy_init_ba;
+          cas_n_mux <= phy_init_cas_n;
+          cs_n_mux <= phy_init_cs_n;
+          ras_n_mux <= phy_init_ras_n;
+          we_n_mux <= phy_init_we_n;
+        end
+      end
+    end
+  endgenerate
+
+  //***************************************************************************
+  // Output flop instantiation
+  // NOTE: Make sure all control/address flops are placed in IOBs
+  //***************************************************************************
+
+  // RAS: = 1 at reset
+  (* IOB = "TRUE" *) FDCPE u_ff_ras_n
+    (
+     .Q   (ddr_ras_n),
+     .C   (clk0),
+     .CE  (1'b1),
+     .CLR (1'b0),
+     .D   (ras_n_mux),
+     .PRE (rst0)
+     ) /* synthesis syn_useioff = 1 */;
+
+  // CAS: = 1 at reset
+  (* IOB = "TRUE" *) FDCPE u_ff_cas_n
+    (
+     .Q   (ddr_cas_n),
+     .C   (clk0),
+     .CE  (1'b1),
+     .CLR (1'b0),
+     .D   (cas_n_mux),
+     .PRE (rst0)
+     ) /* synthesis syn_useioff = 1 */;
+
+  // WE: = 1 at reset
+  (* IOB = "TRUE" *) FDCPE u_ff_we_n
+    (
+     .Q   (ddr_we_n),
+     .C   (clk0),
+     .CE  (1'b1),
+     .CLR (1'b0),
+     .D   (we_n_mux),
+     .PRE (rst0)
+     ) /* synthesis syn_useioff = 1 */;
+
+  // CKE: = 0 at reset
+  genvar cke_i;
+  generate
+    for (cke_i = 0; cke_i < CKE_WIDTH; cke_i = cke_i + 1) begin: gen_cke
+      (* IOB = "TRUE" *) FDCPE u_ff_cke
+        (
+         .Q   (ddr_cke[cke_i]),
+         .C   (clk0),
+         .CE  (1'b1),
+         .CLR (rst0),
+         .D   (phy_init_cke[cke_i]),
+         .PRE (1'b0)
+         ) /* synthesis syn_useioff = 1 */;
+    end
+  endgenerate
+
+  // chip select: = 1 at reset
+  // For unbuffered dimms the loading will be high. The chip select
+  // can be asserted early if the loading is very high. The
+  // code as is uses clock 0. If needed clock 270 can be used to
+  // toggle chip select 1/4 clock cycle early. The code has
+  // the clock 90 input for the early assertion of chip select.
+
+  genvar cs_i;
+  generate
+    for(cs_i = 0; cs_i < CS_WIDTH; cs_i = cs_i + 1) begin: gen_cs_n
+      if(TWO_T_TIME_EN) begin
+         (* IOB = "TRUE" *) FDCPE u_ff_cs_n
+           (
+            .Q   (ddr_cs_n[cs_i]),
+            .C   (clk0),
+            .CE  (1'b1),
+            .CLR (1'b0),
+            .D   (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
+            .PRE (rst0)
+            ) /* synthesis syn_useioff = 1 */;
+      end else begin // if (TWO_T_TIME_EN)
+         (* IOB = "TRUE" *) FDCPE u_ff_cs_n
+           (
+            .Q   (ddr_cs_n[cs_i]),
+            .C   (clk0),
+            .CE  (1'b1),
+            .CLR (1'b0),
+            .D   (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
+            .PRE (rst0)
+            ) /* synthesis syn_useioff = 1 */;
+      end // else: !if(TWO_T_TIME_EN)
+    end
+  endgenerate
+
+  // address: = X at reset
+  genvar addr_i;
+  generate
+    for (addr_i = 0; addr_i < ROW_WIDTH; addr_i = addr_i + 1) begin: gen_addr
+      (* IOB = "TRUE" *) FDCPE u_ff_addr
+        (
+         .Q   (ddr_addr[addr_i]),
+         .C   (clk0),
+         .CE  (1'b1),
+         .CLR (1'b0),
+         .D   (addr_mux[addr_i]),
+         .PRE (1'b0)
+         ) /* synthesis syn_useioff = 1 */;
+    end
+  endgenerate
+
+  // bank address = X at reset
+  genvar ba_i;
+  generate
+    for (ba_i = 0; ba_i < BANK_WIDTH; ba_i = ba_i + 1) begin: gen_ba
+      (* IOB = "TRUE" *) FDCPE u_ff_ba
+        (
+         .Q   (ddr_ba[ba_i]),
+         .C   (clk0),
+         .CE  (1'b1),
+         .CLR (1'b0),
+         .D   (ba_mux[ba_i]),
+         .PRE (1'b0)
+         ) /* synthesis syn_useioff = 1 */;
+    end
+  endgenerate
+
+  // ODT control = 0 at reset
+  genvar odt_i;
+  generate
+    if (DDR_TYPE > 0) begin: gen_odt_ddr2
+      for (odt_i = 0; odt_i < ODT_WIDTH; odt_i = odt_i + 1) begin: gen_odt
+        (* IOB = "TRUE" *) FDCPE u_ff_odt
+          (
+           .Q   (ddr_odt[odt_i]),
+           .C   (clk0),
+           .CE  (1'b1),
+           .CLR (rst0),
+          .D   (odt[(odt_i*CS_NUM)/ODT_WIDTH]),
+           .PRE (1'b0)
+           ) /* synthesis syn_useioff = 1 */;
+      end
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dm_iob.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dm_iob.v
new file mode 100644 (file)
index 0000000..fc6b5c2
--- /dev/null
@@ -0,0 +1,108 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_dm_iob.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/21 14:53:09 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module places the data mask signals into the IOBs.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dm_iob
+  (
+   input  clk90,
+   input  dm_ce,
+   input  mask_data_rise,
+   input  mask_data_fall,
+   output ddr_dm
+   );
+
+  wire    dm_out;
+  wire    dm_ce_r;
+
+  FDRSE_1 u_dm_ce
+    (
+     .Q    (dm_ce_r),
+     .C    (clk90),
+     .CE   (1'b1),
+     .D    (dm_ce),
+     .R   (1'b0),
+     .S   (1'b0)
+     );
+
+  ODDR #
+    (
+     .SRTYPE("SYNC"),
+     .DDR_CLK_EDGE("SAME_EDGE")
+     )
+    u_oddr_dm
+      (
+       .Q  (dm_out),
+       .C  (clk90),
+       .CE (dm_ce_r),
+       .D1 (mask_data_rise),
+       .D2 (mask_data_fall),
+       .R  (1'b0),
+       .S  (1'b0)
+       );
+
+  OBUF u_obuf_dm
+    (
+     .I (dm_out),
+     .O (ddr_dm)
+     );
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dq_iob.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dq_iob.v
new file mode 100644 (file)
index 0000000..854079a
--- /dev/null
@@ -0,0 +1,929 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_dq_iob.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/17 07:52:27 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module places the data in the IOBs.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dq_iob #
+  (
+   parameter DQ_COL                = 0,
+   parameter DQ_MS                 = 0,
+   parameter HIGH_PERFORMANCE_MODE = "TRUE"
+   )
+  (
+   input        clk0,
+   input        clk90,
+   input        clkdiv0,
+   input        rst90,
+   input        dlyinc,
+   input        dlyce,
+   input        dlyrst,
+   input  [1:0] dq_oe_n,
+   input        dqs,
+   input        ce,
+   input        rd_data_sel,
+   input        wr_data_rise,
+   input        wr_data_fall,
+   output       rd_data_rise,
+   output       rd_data_fall,
+   inout        ddr_dq
+   );
+
+  wire       dq_iddr_clk;
+  wire       dq_idelay;
+  wire       dq_in;
+  wire       dq_oe_n_r;
+  wire       dq_out;
+  wire       stg2a_out_fall;
+  wire       stg2a_out_rise;
+  wire       stg2b_out_fall;
+  wire       stg2b_out_rise;
+  wire       stg3a_out_fall;
+  wire       stg3a_out_rise;
+  wire       stg3b_out_fall;
+  wire       stg3b_out_rise;
+
+  //***************************************************************************
+  // Directed routing constraints for route between IDDR and stage 2 capture
+  // in fabric.
+  // Only 2 out of the 12 wire declarations will be used for any given
+  // instantiation of this module.
+  // Varies according:
+  //  (1) I/O column (left, center, right) used
+  //  (2) Which I/O in I/O pair (master, slave) used
+  // Nomenclature: _Xy, X = column (0 = left, 1 = center, 2 = right),
+  //  y = master or slave
+  //***************************************************************************
+
+  // master, left
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;93a1e3bb!-1;-78112;-4200;S!0;-143;-1248!1;-452;0!2;2747;1575!3;2461;81!4;2732;-960!4;2732;-984!5;404;8!6;404;8!7;683;-568;L!8;843;24;L!}" *)
+  wire stg1_out_rise_0m;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;907923a!-1;-78112;-4192;S!0;-143;-1192!0;-143;-1272!1;-452;0!2;-452;0!3;2723;-385!4;2731;-311!5;3823;-1983!6;5209;1271!7;1394;3072!8;0;-8!9;404;8!10;0;-144!11;683;-536;L!12;404;8!14;843;8;L!}" *)
+  wire stg1_out_fall_0m;
+  // slave, left
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;53bb9d6f!-1;-78112;-4600;S!0;-143;-712!1;-452;0!2;1008;-552!3;2780;1360!4;0;-8!5;0;-240!5;0;-264!6;404;8!7;404;8!8;683;-568;L!9;843;24;L!}" *)
+  wire stg1_out_rise_0s;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;46bf60d8!-1;-78112;-4592;S!0;-143;-800!1;-452;0!2;1040;1592!3;5875;-85!4;-3127;-843!4;-3127;-939!5;404;8!6;404;8!7;683;-696;L!8;843;-136;L!}" *)
+  wire stg1_out_fall_0s;
+  // master, center
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;9ee47800!-1;-6504;-50024;S!0;-175;-1136!1;-484;0!2;-3208;1552!3;-4160;-2092!4;-1428;1172!4;-1428;1076!5;404;8!6;404;8!7;843;-152;L!8;683;-728;L!}" *)
+  wire stg1_out_rise_1m;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;e7df31c2!-1;-6504;-50016;S!0;-175;-1192!1;-484;0!2;-5701;1523!3;-3095;-715!3;-4423;2421!4;0;-8!5;1328;-3288!6;0;-240!7;404;8!8;404;8!9;683;-696;L!10;843;-136;L!}" *)
+  wire stg1_out_fall_1m;
+  // slave, center
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;a8c11eb3!-1;-6504;-50424;S!0;-175;-856!1;-484;0!2;-5677;-337!3;1033;1217!3;-295;4353!4;0;-8!5;1328;-3288!6;0;-120!7;404;8!8;404;8!9;683;-696;L!10;843;-152;L!}" *)
+  wire stg1_out_rise_1s;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;ed30cce!-1;-6504;-50416;S!0;-175;-848!1;-484;0!2;-3192;-432!3;-1452;1368!3;-6645;85!4;0;-8!5;5193;1035!6;0;-264!7;404;8!8;404;8!9;683;-568;L!10;843;24;L!}" *)
+  wire stg1_out_fall_1s;
+  // master, right
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;4d035a44!-1;54728;-108896;S!0;-175;-1248!1;-484;0!2;-3192;-424!3;-4208;2092!4;-1396;-972!4;-1396;-996!5;404;8!6;404;8!7;683;-568;L!8;843;24;L!}" *)
+  wire stg1_out_rise_2m;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;92ae8739!-1;54728;-108888;S!0;-175;-1272!1;-484;0!2;-5677;-329!3;-1691;-83!4;-1428;1076!4;-1428;1052!5;404;8!6;404;8!7;683;-728;L!8;843;-136;L!}" *)
+  wire stg1_out_fall_2m;
+  // slave, right
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;9de34bf1!-1;54728;-109296;S!0;-175;-712!1;-484;0!2;-5685;-475!3;1041;1107!3;1041;1011!4;404;8!5;404;8!6;683;-536;L!7;843;24;L!}" *)
+  wire stg1_out_rise_2s;
+  (* syn_keep = "1", keep = "TRUE",
+     ROUTE = "{3;1;5vlx50tff1136;1df9e65d!-1;54728;-109288;S!0;-175;-800!1;-484;0!2;-3208;1608!3;-1436;-792!4;0;-8!5;0;-240!5;0;-144!6;404;8!7;404;8!8;843;-136;L!9;683;-696;L!}" *)
+  wire stg1_out_fall_2s;
+
+  //***************************************************************************
+  // Bidirectional I/O
+  //***************************************************************************
+
+  IOBUF u_iobuf_dq
+    (
+     .I  (dq_out),
+     .T  (dq_oe_n_r),
+     .IO (ddr_dq),
+     .O  (dq_in)
+     );
+
+  //***************************************************************************
+  // Write (output) path
+  //***************************************************************************
+
+  // on a write, rising edge of DQS corresponds to rising edge of CLK180
+  // (aka falling edge of CLK0 -> rising edge DQS). We also know:
+  //  1. data must be driven 1/4 clk cycle before corresponding DQS edge
+  //  2. first rising DQS edge driven on falling edge of CLK0
+  //  3. rising data must be driven 1/4 cycle before falling edge of CLK0
+  //  4. therefore, rising data driven on rising edge of CLK
+  ODDR #
+    (
+     .SRTYPE("SYNC"),
+     .DDR_CLK_EDGE("SAME_EDGE")
+     )
+    u_oddr_dq
+      (
+       .Q  (dq_out),
+       .C  (clk90),
+       .CE (1'b1),
+       .D1 (wr_data_rise),
+       .D2 (wr_data_fall),
+       .R  (1'b0),
+       .S  (1'b0)
+       );
+
+  // make sure output is tri-state during reset (DQ_OE_N_R = 1)
+  ODDR #
+    (
+     .SRTYPE("ASYNC"),
+     .DDR_CLK_EDGE("SAME_EDGE")
+     )
+    u_tri_state_dq
+      (
+       .Q  (dq_oe_n_r),
+       .C  (clk90),
+       .CE (1'b1),
+       .D1 (dq_oe_n[0]),
+       .D2 (dq_oe_n[1]),
+       .R  (1'b0),
+       .S  (rst90)
+       );
+
+  //***************************************************************************
+  // Read data capture scheme description:
+  // Data capture consists of 3 ranks of flops, and a MUX
+  //  1. Rank 1 ("Stage 1"): IDDR captures delayed DDR DQ from memory using
+  //     delayed DQS.
+  //     - Data is split into 2 SDR streams, one each for rise and fall data.
+  //     - BUFIO (DQS) input inverted to IDDR. IDDR configured in SAME_EDGE
+  //       mode. This means that: (1) Q1 = fall data, Q2 = rise data,
+  //       (2) Both rise and fall data are output on falling edge of DQS -
+  //       rather than rise output being output on one edge of DQS, and fall
+  //       data on the other edge if the IDDR were configured in OPPOSITE_EDGE
+  //       mode. This simplifies Stage 2 capture (only one core clock edge
+  //       used, removing effects of duty-cycle-distortion), and saves one
+  //       fabric flop in Rank 3.
+  //  2. Rank 2 ("Stage 2"): Fabric flops are used to capture output of first
+  //     rank into FPGA clock (CLK) domain. Each rising/falling SDR stream
+  //     from IDDR is feed into two flops, one clocked off rising and one off
+  //     falling edge of CLK. One of these flops is chosen, with the choice
+  //     being the one that reduces # of DQ/DQS taps necessary to align Stage
+  //     1 and Stage 2. Same edge is used to capture both rise and fall SDR
+  //     streams.
+  //  3. Rank 3 ("Stage 3"): Removes half-cycle paths in CLK domain from
+  //     output of Rank 2. This stage, like Stage 2, is clocked by CLK. Note
+  //     that Stage 3 can be expanded to also support SERDES functionality
+  //  4. Output MUX: Selects whether Stage 1 output is aligned to rising or
+  //     falling edge of CLK (i.e. specifically this selects whether IDDR
+  //     rise/fall output is transfered to rising or falling edge of CLK).
+  // Implementation:
+  //  1. Rank 1 is implemented using an IDDR primitive
+  //  2. Rank 2 is implemented using:
+  //     - An RPM to fix the location of the capture flops near the DQ I/O.
+  //       The exact RPM used depends on which I/O column (left, center,
+  //       right) the DQ I/O is placed at - this affects the optimal location
+  //       of the slice flops (or does it - can we always choose the two
+  //       columns to slices to the immediate right of the I/O to use, no
+  //       matter what the column?). The origin of the RPM must be set in the
+  //       UCF file using the RLOC_ORIGIN constraint (where the original is
+  //       based on the DQ I/O location).
+  //     - Directed Routing Constraints ("DIRT strings") to fix the routing
+  //       to the rank 2 fabric flops. This is done to minimize: (1) total
+  //       route delay (and therefore minimize voltage/temperature-related
+  //       variations), and (2) minimize skew both within each rising and
+  //       falling data net, as well as between the rising and falling nets.
+  //       The exact DIRT string used depends on: (1) which I/O column the
+  //       DQ I/O is placed, and (2) whether the DQ I/O is placed on the
+  //       "Master" or "Slave" I/O of a diff pair (DQ is not differential, but
+  //       the routing will be affected by which of each I/O pair is used)
+  // 3. Rank 3 is implemented using fabric flops. No LOC or DIRT contraints
+  //    are used, tools are expected to place these and meet PERIOD timing
+  //    without constraints (constraints may be necessary for "full" designs,
+  //    in this case, user may need to add LOC constraints - if this is the
+  //    case, there are no constraints - other than meeting PERIOD timing -
+  //    for rank 3 flops.
+  //***************************************************************************
+
+  //***************************************************************************
+  // MIG 2.2: Define AREA_GROUP = "DDR_CAPTURE_FFS" contain all RPM flops in
+  //          design. In UCF file, add constraint:
+  //             AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
+  //          This is done to prevent MAP from packing unrelated logic into
+  //          the slices used by the RPMs. Doing so may cause the DIRT strings
+  //          that define the IDDR -> fabric flop routing to later become
+  //          unroutable during PAR because the unrelated logic placed by MAP
+  //          may use routing resources required by the DIRT strings. MAP
+  //          does not currently take into account DIRT strings when placing
+  //          logic
+  //***************************************************************************
+
+  // IDELAY to delay incoming data for synchronization purposes
+  IODELAY #
+    (
+     .DELAY_SRC             ("I"),
+     .IDELAY_TYPE           ("VARIABLE"),
+     .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+     .IDELAY_VALUE          (0),
+     .ODELAY_VALUE          (0)
+     )
+    u_idelay_dq
+      (
+       .DATAOUT (dq_idelay),
+       .C       (clkdiv0),
+       .CE      (dlyce),
+       .DATAIN  (),
+       .IDATAIN (dq_in),
+       .INC     (dlyinc),
+       .ODATAIN (),
+       .RST     (dlyrst),
+       .T       ()
+       );
+
+  //***************************************************************************
+  // Rank 1 capture: Use IDDR to generate two SDR outputs
+  //***************************************************************************
+
+  // invert clock to IDDR in order to use SAME_EDGE mode (otherwise, we "run
+  // out of clocks" because DQS is not continuous
+  assign dq_iddr_clk = ~dqs;
+
+  //***************************************************************************
+  // Rank 2 capture: Use fabric flops to capture Rank 1 output. Use RPM and
+  // DIRT strings here.
+  // BEL ("Basic Element of Logic") and relative location constraints for
+  // second stage capture. C
+  // Varies according:
+  //  (1) I/O column (left, center, right) used
+  //  (2) Which I/O in I/O pair (master, slave) used
+  //***************************************************************************
+
+  // Six different cases for the different I/O column, master/slave
+  // combinations (can't seem to do this using a localparam, which
+  // would be easier, XST doesn't allow it)
+  generate
+    if ((DQ_MS == 1) && (DQ_COL == 0)) begin: gen_stg2_0m
+
+      //*****************************************************************
+      // master, left
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_0m),
+           .Q2 (stg1_out_rise_0m),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      //*********************************************************
+      // Slice #1 (posedge CLK): Used for:
+      //  1. IDDR transfer to CLK0 rising edge domain ("stg2a")
+      //  2. stg2 falling edge -> stg3 rising edge transfer
+      //*********************************************************
+
+      // Stage 2 capture
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_0m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_0m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      // Stage 3 falling -> rising edge translation
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      //*********************************************************
+      // Slice #2 (posedge CLK): Used for:
+      //  1. IDDR transfer to CLK0 falling edge domain ("stg2b")
+      //*********************************************************
+
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_0m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_0m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end else if ((DQ_MS == 0) && (DQ_COL == 0)) begin: gen_stg2_0s
+
+      //*****************************************************************
+      // slave, left
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_0s),
+           .Q2 (stg1_out_rise_0s),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_0s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_0s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "AFF",
+       AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_0s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "CFF",
+       AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_0s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end else if ((DQ_MS == 1) && (DQ_COL == 1))  begin: gen_stg2_1m
+
+      //*****************************************************************
+      // master, center
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_1m),
+           .Q2 (stg1_out_rise_1m),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_1m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_1m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_1m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_1m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end else if ((DQ_MS == 0) && (DQ_COL == 1)) begin: gen_stg2_1s
+
+      //*****************************************************************
+      // slave, center
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_1s),
+           .Q2 (stg1_out_rise_1s),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_1s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_1s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_1s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_1s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end else if ((DQ_MS == 1) && (DQ_COL == 2)) begin: gen_stg2_2m
+
+      //*****************************************************************
+      // master, right
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_2m),
+           .Q2 (stg1_out_rise_2m),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_2m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_2m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X0Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_2m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X1Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_2m),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end else if ((DQ_MS == 0) && (DQ_COL == 2)) begin: gen_stg2_2s
+
+      //*****************************************************************
+      // slave, right
+      //*****************************************************************
+
+      IDDR #
+        (
+         .DDR_CLK_EDGE ("SAME_EDGE")
+         )
+        u_iddr_dq
+          (
+           .Q1 (stg1_out_fall_2s),
+           .Q2 (stg1_out_rise_2s),
+           .C  (dq_iddr_clk),
+           .CE (ce),
+           .D  (dq_idelay),
+           .R  (1'b0),
+           .S  (1'b0)
+           );
+
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "BFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_fall
+        (
+         .Q   (stg2a_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_2s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "DFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg2a_rise
+        (
+         .Q   (stg2a_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_2s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_fall
+        (
+         .Q   (stg3b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_fall),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X2Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE u_ff_stg3b_rise
+        (
+         .Q   (stg3b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg2b_out_rise),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "AFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_fall
+        (
+         .Q   (stg2b_out_fall),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_fall_2s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+      (* HU_SET = "stg2_capture", RLOC = "X3Y0", BEL = "CFF",
+         AREA_GROUP = "DDR_CAPTURE_FFS" *)
+      FDRSE_1 u_ff_stg2b_rise
+        (
+         .Q   (stg2b_out_rise),
+         .C   (clk0),
+         .CE  (1'b1),
+     .D   (stg1_out_rise_2s),
+         .R   (1'b0),
+         .S   (1'b0)
+         )/* synthesis syn_preserve = 1 */
+          /* synthesis syn_replicate = 0 */;
+
+    end
+  endgenerate
+
+  //***************************************************************************
+  // Second stage flops clocked by posedge CLK0 don't need another layer of
+  // registering
+  //***************************************************************************
+
+  assign stg3a_out_rise = stg2a_out_rise;
+  assign stg3a_out_fall = stg2a_out_fall;
+
+  //*******************************************************************
+
+  assign rd_data_rise = (rd_data_sel) ? stg3a_out_rise : stg3b_out_rise;
+  assign rd_data_fall = (rd_data_sel) ? stg3a_out_fall : stg3b_out_fall;
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dqs_iob.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_dqs_iob.v
new file mode 100644 (file)
index 0000000..a626f72
--- /dev/null
@@ -0,0 +1,259 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_dqs_iob.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/22 15:41:06 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module places the data strobes in the IOBs.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dqs_iob #
+  (
+   parameter DDR_TYPE              = 1,
+   parameter HIGH_PERFORMANCE_MODE = "TRUE"
+   )
+  (
+   input        clk0,
+   input        clkdiv0,
+   input        rst0,
+   input        dlyinc_dqs,
+   input        dlyce_dqs,
+   input        dlyrst_dqs,
+   input        dlyinc_gate,
+   input        dlyce_gate,
+   input        dlyrst_gate,
+   input        dqs_oe_n,
+   input        dqs_rst_n,
+   input        en_dqs,
+   inout        ddr_dqs,
+   inout        ddr_dqs_n,
+   output       dq_ce,
+   output       delayed_dqs
+   );
+
+  wire                     clk180;
+  wire                     dqs_bufio;
+
+  wire                     dqs_ibuf;
+  wire                     dqs_idelay;
+  wire                     dqs_oe_n_delay;
+  wire                     dqs_oe_n_r;
+  wire                     dqs_rst_n_delay;
+  reg                      dqs_rst_n_r /* synthesis syn_preserve = 1*/;
+  wire                     dqs_out;
+  wire                     en_dqs_sync /* synthesis syn_keep = 1 */;
+
+  // for simulation only. Synthesis should ignore this delay
+  localparam    DQS_NET_DELAY = 0.8;
+
+  assign        clk180 = ~clk0;
+
+  // add delta delay to inputs clocked by clk180 to avoid delta-delay
+  // simulation issues
+  assign dqs_rst_n_delay = dqs_rst_n;
+  assign dqs_oe_n_delay  = dqs_oe_n;
+
+  //***************************************************************************
+  // DQS input-side resources:
+  //  - IODELAY (pad -> IDELAY)
+  //  - BUFIO (IDELAY -> BUFIO)
+  //***************************************************************************
+
+  // Route DQS from PAD to IDELAY
+  IODELAY #
+    (
+     .DELAY_SRC("I"),
+     .IDELAY_TYPE("VARIABLE"),
+     .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
+     .IDELAY_VALUE(0),
+     .ODELAY_VALUE(0)
+     )
+    u_idelay_dqs
+      (
+       .DATAOUT (dqs_idelay),
+       .C       (clkdiv0),
+       .CE      (dlyce_dqs),
+       .DATAIN  (),
+       .IDATAIN (dqs_ibuf),
+       .INC     (dlyinc_dqs),
+       .ODATAIN (),
+       .RST     (dlyrst_dqs),
+       .T       ()
+       );
+
+  // From IDELAY to BUFIO
+  BUFIO u_bufio_dqs
+    (
+     .I  (dqs_idelay),
+     .O  (dqs_bufio)
+     );
+
+  // To model additional delay of DQS BUFIO + gating network
+  // for behavioral simulation. Make sure to select a delay number smaller
+  // than half clock cycle (otherwise output will not track input changes
+  // because of inertial delay). Duplicate to avoid delta delay issues.
+  assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
+  assign #(DQS_NET_DELAY) delayed_dqs   = dqs_bufio;
+
+  //***************************************************************************
+  // DQS gate circuit (not supported for all controllers)
+  //***************************************************************************
+
+  // Gate routing:
+  //   en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
+  //   capture IDDR.CE
+
+  // Delay CE control so that it's in phase with delayed DQS
+  IODELAY #
+    (
+     .DELAY_SRC             ("DATAIN"),
+     .IDELAY_TYPE           ("VARIABLE"),
+     .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+     .IDELAY_VALUE          (0),
+     .ODELAY_VALUE          (0)
+     )
+    u_iodelay_dq_ce
+      (
+       .DATAOUT (en_dqs_sync),
+       .C       (clkdiv0),
+       .CE      (dlyce_gate),
+       .DATAIN  (en_dqs),
+       .IDATAIN (),
+       .INC     (dlyinc_gate),
+       .ODATAIN (),
+       .RST     (dlyrst_gate),
+       .T       ()
+       );
+
+  // Generate sync'ed CE to DQ IDDR's using an IDDR clocked by DQS
+  // We could also instantiate a negative-edge SDR flop here
+  IDDR #
+    (
+     .DDR_CLK_EDGE ("OPPOSITE_EDGE"),
+     .INIT_Q1      (1'b0),
+     .INIT_Q2      (1'b0),
+     .SRTYPE       ("ASYNC")
+     )
+    u_iddr_dq_ce
+      (
+       .Q1 (),
+       .Q2 (dq_ce),           // output on falling edge
+       .C  (i_delayed_dqs),
+       .CE (1'b1),
+       .D  (en_dqs_sync),
+       .R  (1'b0),
+       .S  (en_dqs_sync)
+       );
+
+  //***************************************************************************
+  // DQS output-side resources
+  //***************************************************************************
+
+  // synthesis attribute keep of dqs_rst_n_r is "true"
+  always @(posedge clk180)
+    dqs_rst_n_r <= dqs_rst_n_delay;
+
+  ODDR #
+    (
+     .SRTYPE("SYNC"),
+     .DDR_CLK_EDGE("OPPOSITE_EDGE")
+     )
+    u_oddr_dqs
+      (
+       .Q  (dqs_out),
+       .C  (clk180),
+       .CE (1'b1),
+       .D1 (dqs_rst_n_r),      // keep output deasserted for write preamble
+       .D2 (1'b0),
+       .R  (1'b0),
+       .S  (1'b0)
+       );
+
+  (* IOB = "TRUE" *) FDP u_tri_state_dqs
+    (
+     .D   (dqs_oe_n_delay),
+     .Q   (dqs_oe_n_r),
+     .C   (clk180),
+     .PRE (rst0)
+     ) /* synthesis syn_useioff = 1 */;
+
+  //***************************************************************************
+
+  // use either single-ended (for DDR1) or differential (for DDR2) DQS input
+
+  generate
+    if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
+      IOBUFDS u_iobuf_dqs
+        (
+         .O   (dqs_ibuf),
+         .IO  (ddr_dqs),
+         .IOB (ddr_dqs_n),
+         .I   (dqs_out),
+         .T   (dqs_oe_n_r)
+         );
+    end else begin: gen_dqs_iob_ddr1
+      IOBUF u_iobuf_dqs
+        (
+         .O   (dqs_ibuf),
+         .IO  (ddr_dqs),
+         .I   (dqs_out),
+         .T   (dqs_oe_n_r)
+         );
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_init.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_init.v
new file mode 100644 (file)
index 0000000..4282b63
--- /dev/null
@@ -0,0 +1,1150 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_init.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/22 15:41:06 $
+// \   \  /  \    Date Created: Thu Aug 24 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//Reference:
+//   This module is the intialization control logic of the memory interface.
+//   All commands are issued from here acoording to the burst, CAS Latency and
+//   the user commands.
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_init #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH    = 2,
+   parameter CKE_WIDTH     = 1,
+   parameter COL_WIDTH     = 10,
+   parameter CS_NUM        = 1,
+   parameter DQ_WIDTH      = 72,
+   parameter ODT_WIDTH     = 1,
+   parameter ROW_WIDTH     = 14,
+   parameter ADDITIVE_LAT  = 0,
+   parameter BURST_LEN     = 4,
+   parameter TWO_T_TIME_EN = 0,
+   parameter BURST_TYPE    = 0,
+   parameter CAS_LAT       = 5,
+   parameter ODT_TYPE      = 1,
+   parameter REDUCE_DRV    = 0,
+   parameter REG_ENABLE    = 1,
+   parameter TWR           = 15000,
+   parameter CLK_PERIOD    = 3000,
+   parameter DDR_TYPE      = 1,
+   parameter SIM_ONLY      = 0
+   )
+  (
+   input                                   clk0,
+   input                                   clkdiv0,
+   input                                   rst0,
+   input                                   rstdiv0,
+   input [3:0]                             calib_done,
+   input                                   ctrl_ref_flag,
+   input                                   calib_ref_req,
+   output reg [3:0]                        calib_start,
+   output reg                              calib_ref_done,
+   output reg                              phy_init_wren,
+   output reg                              phy_init_rden,
+   output [ROW_WIDTH-1:0]                  phy_init_addr,
+   output [BANK_WIDTH-1:0]                 phy_init_ba,
+   output                                  phy_init_ras_n,
+   output                                  phy_init_cas_n,
+   output                                  phy_init_we_n,
+   output [CS_NUM-1:0]                     phy_init_cs_n,
+   output [CKE_WIDTH-1:0]                  phy_init_cke,
+   output reg                              phy_init_done,
+   output                                  phy_init_data_sel
+   );
+
+  // time to wait between consecutive commands in PHY_INIT - this is a
+  // generic number, and must be large enough to account for worst case
+  // timing parameter (tRFC - refresh-to-active) across all memory speed
+  // grades and operating frequencies. Expressed in CLKDIV clock cycles.
+  localparam  CNTNEXT_CMD = 7'b1111111;
+  // time to wait between read and read or precharge for stage 3 & 4
+  // the larger CNTNEXT_CMD can also be used, use smaller number to
+  // speed up calibration - avoid tRAS violation, and speeds up simulation
+  localparam  CNTNEXT_RD  = 4'b1111;
+
+  // Write recovery (WR) time - is defined by 
+  // tWR (in nanoseconds) by tCK (in nanoseconds) and rounding up a 
+  // noninteger value to the next integer
+  localparam integer WR_RECOVERY =  ((TWR + CLK_PERIOD) - 1)/CLK_PERIOD;
+
+  localparam  INIT_CAL1_READ            = 5'h00;
+  localparam  INIT_CAL2_READ            = 5'h01;
+  localparam  INIT_CAL3_READ            = 5'h02;
+  localparam  INIT_CAL4_READ            = 5'h03;
+  localparam  INIT_CAL1_WRITE           = 5'h04;
+  localparam  INIT_CAL2_WRITE           = 5'h05;
+  localparam  INIT_CAL3_WRITE           = 5'h06;
+  localparam  INIT_DUMMY_ACTIVE_WAIT    = 5'h07;
+  localparam  INIT_PRECHARGE            = 5'h08;
+  localparam  INIT_LOAD_MODE            = 5'h09;
+  localparam  INIT_AUTO_REFRESH         = 5'h0A;
+  localparam  INIT_IDLE                 = 5'h0B;
+  localparam  INIT_CNT_200              = 5'h0C;
+  localparam  INIT_CNT_200_WAIT         = 5'h0D;
+  localparam  INIT_PRECHARGE_WAIT       = 5'h0E;
+  localparam  INIT_MODE_REGISTER_WAIT   = 5'h0F;
+  localparam  INIT_AUTO_REFRESH_WAIT    = 5'h10;
+  localparam  INIT_DEEP_MEMORY_ST       = 5'h11;
+  localparam  INIT_DUMMY_ACTIVE         = 5'h12;
+  localparam  INIT_CAL1_WRITE_READ      = 5'h13;
+  localparam  INIT_CAL1_READ_WAIT       = 5'h14;
+  localparam  INIT_CAL2_WRITE_READ      = 5'h15;
+  localparam  INIT_CAL2_READ_WAIT       = 5'h16;
+  localparam  INIT_CAL3_WRITE_READ      = 5'h17;
+  localparam  INIT_CAL3_READ_WAIT       = 5'h18;
+  localparam  INIT_CAL4_READ_WAIT       = 5'h19;
+  localparam  INIT_CALIB_REF            = 5'h1A;
+  localparam  INIT_ZQCL                 = 5'h1B;
+  localparam  INIT_WAIT_DLLK_ZQINIT     = 5'h1C;
+
+  localparam  INIT_CNTR_INIT            = 4'h0;
+  localparam  INIT_CNTR_PRECH_1         = 4'h1;
+  localparam  INIT_CNTR_EMR2_INIT       = 4'h2;
+  localparam  INIT_CNTR_EMR3_INIT       = 4'h3;
+  localparam  INIT_CNTR_EMR_EN_DLL      = 4'h4;
+  localparam  INIT_CNTR_MR_RST_DLL      = 4'h5;
+  localparam  INIT_CNTR_CNT_200_WAIT    = 4'h6;
+  localparam  INIT_CNTR_PRECH_2         = 4'h7;
+  localparam  INIT_CNTR_AR_1            = 4'h8;
+  localparam  INIT_CNTR_AR_2            = 4'h9;
+  localparam  INIT_CNTR_MR_ACT_DLL      = 4'hA;
+  localparam  INIT_CNTR_EMR_DEF_OCD     = 4'hB;
+  localparam  INIT_CNTR_EMR_EXIT_OCD    = 4'hC;
+  localparam  INIT_CNTR_DEEP_MEM        = 4'hD;
+  localparam  INIT_CNTR_PRECH_3         = 4'hE;
+  localparam  INIT_CNTR_DONE            = 4'hF;
+
+  localparam   DDR1                     = 0;
+  localparam   DDR2                     = 1;
+  localparam   DDR3                     = 2;
+
+
+  reg [1:0]             burst_addr_r;
+  reg [1:0]             burst_cnt_r;
+  wire [1:0]            burst_val;
+  wire                  cal_read;
+  wire                  cal_write;
+  wire                  cal_write_read;
+  reg                   cal1_started_r;
+  reg                   cal2_started_r;
+  reg                   cal4_started_r;
+  reg [3:0]             calib_done_r;
+  reg                   calib_ref_req_posedge;
+  reg                   calib_ref_req_r;
+  reg [15:0]            calib_start_shift0_r;
+  reg [15:0]            calib_start_shift1_r;
+  reg [15:0]            calib_start_shift2_r;
+  reg [15:0]            calib_start_shift3_r;
+  reg [1:0]             chip_cnt_r;
+  reg [4:0]             cke_200us_cnt_r;
+  reg                   cke_200us_cnt_en_r;
+  reg [7:0]             cnt_200_cycle_r;
+  reg                   cnt_200_cycle_done_r;
+  reg [6:0]             cnt_cmd_r;
+  reg                   cnt_cmd_ok_r;
+  reg [3:0]             cnt_rd_r;
+  reg                   cnt_rd_ok_r;
+  reg                   ctrl_ref_flag_r;
+  reg                   done_200us_r;
+  reg [ROW_WIDTH-1:0]   ddr_addr_r;
+  reg [ROW_WIDTH-1:0]   ddr_addr_r1;
+  reg [BANK_WIDTH-1:0]  ddr_ba_r;
+  reg [BANK_WIDTH-1:0]  ddr_ba_r1;
+  reg                   ddr_cas_n_r;
+  reg                   ddr_cas_n_r1;
+  reg [CKE_WIDTH-1:0]   ddr_cke_r;
+  reg [CS_NUM-1:0]      ddr_cs_n_r;
+  reg [CS_NUM-1:0]      ddr_cs_n_r1;
+  reg [CS_NUM-1:0]      ddr_cs_disable_r;
+  reg                   ddr_ras_n_r;
+  reg                   ddr_ras_n_r1;
+  reg                   ddr_we_n_r;
+  reg                   ddr_we_n_r1;
+  wire [15:0]           ext_mode_reg;
+  reg [3:0]             init_cnt_r;
+  reg                   init_done_r;
+  reg [4:0]             init_next_state;
+  reg [4:0]             init_state_r;
+  reg [4:0]             init_state_r1;
+  reg [4:0]             init_state_r2;
+  wire [15:0]           load_mode_reg;
+  wire [15:0]           load_mode_reg0;
+  wire [15:0]           load_mode_reg1;
+  wire [15:0]           load_mode_reg2;
+  wire [15:0]           load_mode_reg3;
+  reg                   phy_init_done_r;
+  reg                   phy_init_done_r1;
+  reg                   phy_init_done_r2;
+  reg                   phy_init_done_r3;
+  reg                   refresh_req;
+  wire [3:0]            start_cal;
+
+  //***************************************************************************
+
+  //*****************************************************************
+  // DDR1 and DDR2 Load mode register
+  // Mode Register (MR):
+  //   [15:14] - unused          - 00
+  //   [13]    - reserved        - 0
+  //   [12]    - Power-down mode - 0 (normal)
+  //   [11:9]  - write recovery  - for Auto Precharge (tWR/tCK)
+  //   [8]     - DLL reset       - 0 or 1
+  //   [7]     - Test Mode       - 0 (normal)
+  //   [6:4]   - CAS latency     - CAS_LAT
+  //   [3]     - Burst Type      - BURST_TYPE
+  //   [2:0]   - Burst Length    - BURST_LEN
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR2) begin: gen_load_mode_reg_ddr2
+      assign load_mode_reg[2:0]   = (BURST_LEN == 8) ? 3'b011 :
+                                    ((BURST_LEN == 4) ? 3'b010 : 3'b111);
+      assign load_mode_reg[3]     = BURST_TYPE;
+      assign load_mode_reg[6:4]   = (CAS_LAT == 3) ? 3'b011 :
+                                    ((CAS_LAT == 4) ? 3'b100 :
+                                     ((CAS_LAT == 5) ? 3'b101 : 3'b111));
+      assign load_mode_reg[7]     = 1'b0;
+      assign load_mode_reg[8]     = 1'b0;    // init value only (DLL not reset)
+      assign load_mode_reg[11:9]  = (WR_RECOVERY == 6) ? 3'b101 :
+                                    ((WR_RECOVERY == 5) ? 3'b100 :
+                                     ((WR_RECOVERY == 4) ? 3'b011 :
+                                      ((WR_RECOVERY == 3) ? 3'b010 :
+                                      3'b001)));
+      assign load_mode_reg[15:12] = 4'b000;
+    end else if (DDR_TYPE == DDR1)begin: gen_load_mode_reg_ddr1
+      assign load_mode_reg[2:0]   = (BURST_LEN == 8) ? 3'b011 :
+                                    ((BURST_LEN == 4) ? 3'b010 :
+                                     ((BURST_LEN == 2) ? 3'b001 : 3'b111));
+      assign load_mode_reg[3]     = BURST_TYPE;
+      assign load_mode_reg[6:4]   = (CAS_LAT == 2) ? 3'b010 :
+                                    ((CAS_LAT == 3) ? 3'b011 :
+                                     ((CAS_LAT == 25) ? 3'b110 : 3'b111));
+      assign load_mode_reg[12:7]  = 6'b000000; // init value only
+      assign load_mode_reg[15:13]  = 3'b000;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // DDR1 and DDR2 ext mode register
+  // Extended Mode Register (MR):
+  //   [15:14] - unused          - 00
+  //   [13]    - reserved        - 0
+  //   [12]    - output enable   - 0 (enabled)
+  //   [11]    - RDQS enable     - 0 (disabled)
+  //   [10]    - DQS# enable     - 0 (enabled)
+  //   [9:7]   - OCD Program     - 111 or 000 (first 111, then 000 during init)
+  //   [6]     - RTT[1]          - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
+  //   [5:3]   - Additive CAS    - ADDITIVE_CAS
+  //   [2]     - RTT[0]
+  //   [1]     - Output drive    - REDUCE_DRV (= 0(full), = 1 (reduced)
+  //   [0]     - DLL enable      - 0 (normal)
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR2) begin: gen_ext_mode_reg_ddr2
+      assign ext_mode_reg[0]     = 1'b0;
+      assign ext_mode_reg[1]     = REDUCE_DRV;
+      assign ext_mode_reg[2]     = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
+                                   1'b1 : 1'b0;
+      assign ext_mode_reg[5:3]   = (ADDITIVE_LAT == 0) ? 3'b000 :
+                                   ((ADDITIVE_LAT == 1) ? 3'b001 :
+                                    ((ADDITIVE_LAT == 2) ? 3'b010 :
+                                     ((ADDITIVE_LAT == 3) ? 3'b011 :
+                                      ((ADDITIVE_LAT == 4) ? 3'b100 :
+                                      3'b111))));
+      assign ext_mode_reg[6]     = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
+                                   1'b1 : 1'b0;
+      assign ext_mode_reg[9:7]   = 3'b000;
+      assign ext_mode_reg[10]    = 1'b0;
+      assign ext_mode_reg[15:10] = 6'b000000;
+    end else if (DDR_TYPE == DDR1)begin: gen_ext_mode_reg_ddr1
+      assign ext_mode_reg[0]     = 1'b0;
+      assign ext_mode_reg[1]     = REDUCE_DRV;
+      assign ext_mode_reg[12:2]  = 11'b00000000000;
+      assign ext_mode_reg[15:13] = 3'b000;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // DDR3 Load mode reg0
+  // Mode Register (MR0):
+  //   [15:13] - unused          - 000
+  //   [12]    - Precharge Power-down DLL usage - 0 (DLL frozen, slow-exit),
+  //             1 (DLL maintained)
+  //   [11:9]  - write recovery for Auto Precharge (tWR/tCK = 6)
+  //   [8]     - DLL reset       - 0 or 1
+  //   [7]     - Test Mode       - 0 (normal)
+  //   [6:4],[2]   - CAS latency     - CAS_LAT
+  //   [3]     - Burst Type      - BURST_TYPE
+  //   [1:0]   - Burst Length    - BURST_LEN
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR3) begin: gen_load_mode_reg0_ddr3
+      assign load_mode_reg0[1:0]   = (BURST_LEN == 8) ? 2'b00 :
+                                     ((BURST_LEN == 4) ? 2'b10 : 2'b11);
+      // Part of CAS latency. This bit is '0' for all CAS latencies
+      assign load_mode_reg0[2]     = 1'b0;
+      assign load_mode_reg0[3]     = BURST_TYPE;
+      assign load_mode_reg0[6:4]   = (CAS_LAT == 5) ? 3'b001 :
+                                     (CAS_LAT == 6) ? 3'b010 : 3'b111;
+      assign load_mode_reg0[7]     = 1'b0;
+      // init value only (DLL reset)
+      assign load_mode_reg0[8]     = 1'b1;
+      assign load_mode_reg0[11:9]  = 3'b010;
+      // Precharge Power-Down DLL 'slow-exit'
+      assign load_mode_reg0[12]    = 1'b0;
+      assign load_mode_reg0[15:13] = 3'b000;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // DDR3 Load mode reg1
+  // Mode Register (MR1):
+  //   [15:13] - unused          - 00
+  //   [12]    - output enable   - 0 (enabled for DQ, DQS, DQS#)
+  //   [11]    - TDQS enable     - 0 (TDQS disabled and DM enabled)
+  //   [10]    - reserved   - 0 (must be '0')
+  //   [9]     - RTT[2]     - 0
+  //   [8]     - reserved   - 0 (must be '0')
+  //   [7]     - write leveling - 0 (disabled), 1 (enabled)
+  //   [6]     - RTT[1]          - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
+  //   [5]     - Output driver impedance[1] - 0 (RZQ/6 and RZQ/7)
+  //   [4:3]   - Additive CAS    - ADDITIVE_CAS
+  //   [2]     - RTT[0]
+  //   [1]     - Output driver impedance[0] - 0(RZQ/6), or 1 (RZQ/7)
+  //   [0]     - DLL enable      - 0 (normal)
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg1_ddr3
+      // DLL enabled during Imitialization
+      assign load_mode_reg1[0]     = 1'b0;
+      // RZQ/6
+      assign load_mode_reg1[1]     = REDUCE_DRV;
+      assign load_mode_reg1[2]     = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
+                                     1'b1 : 1'b0;
+      assign load_mode_reg1[4:3]   = (ADDITIVE_LAT == 0) ? 2'b00 :
+                                     ((ADDITIVE_LAT == 1) ? 2'b01 :
+                                      ((ADDITIVE_LAT == 2) ? 2'b10 :
+                                       3'b111));
+      // RZQ/6
+      assign load_mode_reg1[5]     = 1'b0;
+      assign load_mode_reg1[6]     = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
+                                   1'b1 : 1'b0;
+      // Make zero WRITE_LEVEL
+      assign load_mode_reg1[7]   = 0;
+      assign load_mode_reg1[8]   = 1'b0;
+      assign load_mode_reg1[9]   = 1'b0;
+      assign load_mode_reg1[10]    = 1'b0;
+      assign load_mode_reg1[15:11] = 5'b00000;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // DDR3 Load mode reg2
+  // Mode Register (MR2):
+  //   [15:11] - unused     - 00
+  //   [10:9]  - RTT_WR     - 00 (Dynamic ODT off)
+  //   [8]     - reserved   - 0 (must be '0')
+  //   [7]     - self-refresh temperature range -
+  //               0 (normal), 1 (extended)
+  //   [6]     - Auto Self-Refresh - 0 (manual), 1(auto)
+  //   [5:3]   - CAS Write Latency (CWL) -
+  //               000 (5 for 400 MHz device),
+  //               001 (6 for 400 MHz to 533 MHz devices),
+  //               010 (7 for 533 MHz to 667 MHz devices),
+  //               011 (8 for 667 MHz to 800 MHz)
+  //   [2:0]   - Partial Array Self-Refresh (Optional)      -
+  //               000 (full array)
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3
+      assign load_mode_reg2[2:0]     = 3'b000;
+      assign load_mode_reg2[5:3]   = (CAS_LAT == 5) ? 3'b000 :
+                                     (CAS_LAT == 6) ? 3'b001 : 3'b111;
+      assign load_mode_reg2[6]     = 1'b0; // Manual Self-Refresh
+      assign load_mode_reg2[7]   = 1'b0;
+      assign load_mode_reg2[8]   = 1'b0;
+      assign load_mode_reg2[10:9]  = 2'b00;
+      assign load_mode_reg2[15:11] = 5'b00000;
+    end
+  endgenerate
+
+  //*****************************************************************
+  // DDR3 Load mode reg3
+  // Mode Register (MR3):
+  //   [15:3] - unused          - All zeros
+  //   [2]     - MPR Operation - 0(normal operation), 1(data flow from MPR)
+  //   [1:0]   - MPR location     - 00 (Predefined pattern)
+  //*****************************************************************
+
+  generate
+    if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3
+      assign load_mode_reg3[1:0]   = 2'b00;
+      assign load_mode_reg3[2]     = 1'b0;
+      assign load_mode_reg3[15:3] = 13'b0000000000000;
+    end
+  endgenerate
+
+  //***************************************************************************
+  // Logic for calibration start, and for auto-refresh during cal request
+  // CALIB_REF_REQ is used by calibration logic to request auto-refresh
+  // durign calibration (used to avoid tRAS violation is certain calibration
+  // stages take a long time). Once the auto-refresh is complete and cal can
+  // be resumed, CALIB_REF_DONE is asserted by PHY_INIT.
+  //***************************************************************************
+
+  // generate pulse for each of calibration start controls
+  assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
+                         (init_state_r2 != INIT_CAL1_READ));
+  assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
+                         (init_state_r2 != INIT_CAL2_READ));
+  assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
+                         (init_state_r2 == INIT_CAL3_WRITE_READ));
+  assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
+                         (init_state_r2 == INIT_DUMMY_ACTIVE_WAIT));
+
+  // Generate positive-edge triggered, latched signal to force initialization
+  // to pause calibration, and to issue auto-refresh. Clear flag as soon as
+  // refresh initiated
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      calib_ref_req_r       <= 1'b0;
+      calib_ref_req_posedge <= 1'b0;
+      refresh_req           <= 1'b0;
+    end else begin
+      calib_ref_req_r       <= calib_ref_req;
+      calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;
+      if (init_state_r1 == INIT_AUTO_REFRESH)
+        refresh_req <= 1'b0;
+      else if (calib_ref_req_posedge)
+        refresh_req <= 1'b1;
+    end
+
+  // flag to tell cal1 calibration was started.
+  // This flag is used for cal1 auto refreshes
+  // some of these bits may not be needed - only needed for those stages that
+  // need refreshes within the stage (i.e. very long stages)
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      cal1_started_r <= 1'b0;
+      cal2_started_r <= 1'b0;
+      cal4_started_r <= 1'b0;
+    end else begin
+      if (calib_start[0])
+        cal1_started_r <= 1'b1;
+      if (calib_start[1])
+        cal2_started_r <= 1'b1;
+      if (calib_start[3])
+        cal4_started_r <= 1'b1;
+    end
+
+  // Delay start of each calibration by 16 clock cycles to
+  // ensure that when calibration logic begins, that read data is already
+  // appearing on the bus. Don't really need it, it's more for simulation
+  // purposes. Each circuit should synthesize using an SRL16.
+  // In first stage of calibration  periodic auto refreshes
+  // will be issued to meet memory timing. calib_start_shift0_r[15] will be
+  // asserted more than once.calib_start[0] is anded with cal1_started_r so
+  // that it is asserted only once. cal1_refresh_done is anded with
+  // cal1_started_r so that it is asserted after the auto refreshes.
+  always @(posedge clkdiv0) begin
+    calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
+    calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
+    calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
+    calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
+    calib_start[0]       <= calib_start_shift0_r[15] & ~cal1_started_r;
+    calib_start[1]       <= calib_start_shift1_r[15] & ~cal2_started_r;
+    calib_start[2]       <= calib_start_shift2_r[15];
+    calib_start[3]       <= calib_start_shift3_r[15] & ~cal4_started_r;
+    calib_ref_done       <= calib_start_shift0_r[15] |
+                            calib_start_shift1_r[15] |
+                            calib_start_shift3_r[15];
+  end
+
+  // generate delay for various states that require it (no maximum delay
+  // requirement, make sure that terminal count is large enough to cover
+  // all cases)
+  always @(posedge clkdiv0) begin
+    case (init_state_r)
+      INIT_PRECHARGE_WAIT,
+      INIT_MODE_REGISTER_WAIT,
+      INIT_AUTO_REFRESH_WAIT,
+      INIT_DUMMY_ACTIVE_WAIT,
+      INIT_CAL1_WRITE_READ,
+      INIT_CAL1_READ_WAIT,
+      INIT_CAL2_WRITE_READ,
+      INIT_CAL2_READ_WAIT,
+      INIT_CAL3_WRITE_READ:
+        cnt_cmd_r <= cnt_cmd_r + 1;
+      default:
+        cnt_cmd_r <= 7'b0000000;
+    endcase
+  end
+
+  // assert when count reaches the value
+  always @(posedge clkdiv0) begin
+    if(cnt_cmd_r == CNTNEXT_CMD)
+      cnt_cmd_ok_r <= 1'b1;
+    else
+      cnt_cmd_ok_r <= 1'b0;
+  end
+
+  always @(posedge clkdiv0) begin
+    case (init_state_r)
+      INIT_CAL3_READ_WAIT,
+      INIT_CAL4_READ_WAIT:
+        cnt_rd_r <= cnt_rd_r + 1;
+      default:
+        cnt_rd_r <= 4'b0000;
+    endcase
+  end
+
+  always @(posedge clkdiv0) begin
+    if(cnt_rd_r == CNTNEXT_RD)
+      cnt_rd_ok_r <= 1'b1;
+    else
+      cnt_rd_ok_r <= 1'b0;
+  end
+
+  //***************************************************************************
+  // Initial delay after power-on
+  //***************************************************************************
+
+  // register the refresh flag from the controller.
+  // The refresh flag is in full frequency domain - so a pulsed version must
+  // be generated for half freq domain using 2 consecutive full clk cycles
+  // The registered version is used for the 200us counter
+  always @(posedge clk0)
+    ctrl_ref_flag_r <= ctrl_ref_flag;
+  always @(posedge clkdiv0)
+    cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;
+
+  // 200us counter for cke
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      // skip power-up count if only simulating
+      if (SIM_ONLY)
+        cke_200us_cnt_r <= 5'b00001;
+      else
+        cke_200us_cnt_r <= 5'd27;
+    end else if (cke_200us_cnt_en_r)
+      cke_200us_cnt_r <= cke_200us_cnt_r - 1;
+
+  always @(posedge clkdiv0)
+    if (rstdiv0)
+      done_200us_r <= 1'b0;
+    else if (!done_200us_r)
+      done_200us_r <= (cke_200us_cnt_r == 5'b00000);
+
+  // 200 clocks counter - count value : h'64 required for initialization
+  // Counts 100 divided by two clocks
+  always @(posedge clkdiv0)
+    if (rstdiv0 || (init_state_r == INIT_CNT_200))
+      cnt_200_cycle_r <= 8'h64;
+    else if  (init_state_r == INIT_ZQCL) // ddr3
+      cnt_200_cycle_r <= 8'hC8;
+    else if (cnt_200_cycle_r != 8'h00)
+      cnt_200_cycle_r <= cnt_200_cycle_r - 1;
+
+  always @(posedge clkdiv0)
+    if (rstdiv0 || (init_state_r == INIT_CNT_200)
+        || (init_state_r == INIT_ZQCL))
+      cnt_200_cycle_done_r <= 1'b0;
+    else if (cnt_200_cycle_r == 8'h00)
+      cnt_200_cycle_done_r <= 1'b1;
+
+  //*****************************************************************
+  //   handle deep memory configuration:
+  //   During initialization: Repeat initialization sequence once for each
+  //   chip select. Note that we could perform initalization for all chip
+  //   selects simulataneously. Probably fine - any potential SI issues with
+  //   auto refreshing all chip selects at once?
+  //   Once initialization complete, assert only CS[0] for calibration.
+  //*****************************************************************
+
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      chip_cnt_r <= 2'b00;
+    end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
+      if (chip_cnt_r != CS_NUM)
+        chip_cnt_r <= chip_cnt_r + 1;
+      else
+        chip_cnt_r <= 2'b00;
+    end
+
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      ddr_cs_n_r <= {CS_NUM{1'b1}};
+    end else begin
+      ddr_cs_n_r <= {CS_NUM{1'b1}};
+      if ((init_state_r == INIT_DUMMY_ACTIVE) ||
+          (init_state_r == INIT_PRECHARGE) ||
+          (init_state_r == INIT_LOAD_MODE) ||
+          (init_state_r == INIT_AUTO_REFRESH) ||
+          (init_state_r  == INIT_ZQCL    ) ||
+          (((init_state_r == INIT_CAL1_READ) ||
+            (init_state_r == INIT_CAL2_READ) ||
+            (init_state_r == INIT_CAL3_READ) ||
+            (init_state_r == INIT_CAL4_READ) ||
+            (init_state_r == INIT_CAL1_WRITE) ||
+            (init_state_r == INIT_CAL2_WRITE) ||
+            (init_state_r == INIT_CAL3_WRITE)) && (burst_cnt_r == 2'b00)))
+        ddr_cs_n_r[chip_cnt_r] <= 1'b0;
+      else
+        ddr_cs_n_r[chip_cnt_r] <= 1'b1;
+    end
+
+  //***************************************************************************
+  // Write/read burst logic
+  //***************************************************************************
+
+  assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
+                      (init_state_r == INIT_CAL2_WRITE) ||
+                      (init_state_r == INIT_CAL3_WRITE));
+  assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
+                     (init_state_r == INIT_CAL2_READ) ||
+                     (init_state_r == INIT_CAL3_READ) ||
+                     (init_state_r == INIT_CAL4_READ));
+  assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||
+                           (init_state_r == INIT_CAL2_READ) ||
+                           (init_state_r == INIT_CAL3_READ) ||
+                           (init_state_r == INIT_CAL4_READ) ||
+                           (init_state_r == INIT_CAL1_WRITE) ||
+                           (init_state_r == INIT_CAL2_WRITE) ||
+                           (init_state_r == INIT_CAL3_WRITE));
+
+  assign burst_val = (BURST_LEN == 4) ? 2'b00 :
+                     (BURST_LEN == 8) ? 2'b01 : 2'b00;
+
+  // keep track of current address - need this if burst length < 8 for
+  // stage 2-4 calibration writes and reads. Make sure value always gets
+  // initialized to 0 before we enter write/read state. This is used to
+  // keep track of when another burst must be issued
+  always @(posedge clkdiv0)
+    if (cal_write_read)
+      burst_addr_r <= burst_addr_r + 2;
+    else
+      burst_addr_r <= 2'b00;
+
+  // write/read burst count
+  always @(posedge clkdiv0)
+    if (cal_write_read)
+      if (burst_cnt_r == 2'b00)
+        burst_cnt_r <= burst_val;
+      else // SHOULD THIS BE -2 CHECK THIS LOGIC
+        burst_cnt_r <= burst_cnt_r - 1;
+    else
+      burst_cnt_r <= 2'b00;
+
+  // indicate when a write is occurring
+  always @(posedge clkdiv0)
+    // MIG 2.1: Remove (burst_addr_r<4) term - not used
+    // phy_init_wren <= cal_write && (burst_addr_r < 3'd4);
+    phy_init_wren <= cal_write;
+
+  // used for read enable calibration, pulse to indicate when read issued
+  always @(posedge clkdiv0)
+    // MIG 2.1: Remove (burst_addr_r<4) term - not used
+    // phy_init_rden <= cal_read && (burst_addr_r < 3'd4);
+    phy_init_rden <= cal_read;
+
+  //***************************************************************************
+  // Initialization state machine
+  //***************************************************************************
+
+  always @(posedge clkdiv0)
+    // every time we need to initialize another rank of memory, need to
+    // reset init count, and repeat the entire initialization (but not
+    // calibration) sequence
+    if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))
+      init_cnt_r <= INIT_CNTR_INIT;
+    else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&
+             (init_cnt_r == INIT_CNTR_PRECH_1))
+      // skip EMR(2) and EMR(3) register loads
+      init_cnt_r <= INIT_CNTR_EMR_EN_DLL;
+    else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&
+             (init_cnt_r == INIT_CNTR_MR_ACT_DLL))
+      // skip OCD calibration for DDR1
+      init_cnt_r <= INIT_CNTR_DEEP_MEM;
+    else if ((DDR_TYPE == DDR3) && (init_state_r ==  INIT_ZQCL))
+      // skip states for DDR3
+      init_cnt_r <= INIT_CNTR_DEEP_MEM;
+    else if ((init_state_r == INIT_LOAD_MODE) ||
+             ((init_state_r == INIT_PRECHARGE)
+              && (init_state_r1 != INIT_CALIB_REF))||
+             ((init_state_r == INIT_AUTO_REFRESH)
+              && (~init_done_r))||
+             (init_state_r == INIT_CNT_200))
+      init_cnt_r <= init_cnt_r + 1;
+
+  always @(posedge clkdiv0) begin
+    if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin
+      phy_init_done_r <= 1'b1;
+    end else
+      phy_init_done_r <= 1'b0;
+  end
+
+  // phy_init_done to the controller and the user interface.
+  // It is delayed by four clocks to account for the
+  // multi cycle path constraint to the (phy_init_data_sel)
+  // to the phy layer.
+  always @(posedge clkdiv0)begin
+    phy_init_done_r1 <= phy_init_done_r;
+    phy_init_done_r2 <= phy_init_done_r1;
+    phy_init_done_r3 <= phy_init_done_r2;
+    phy_init_done <= phy_init_done_r3;
+  end
+
+  // Instantiate primitive to allow this flop to be attached to multicycle
+  // path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO
+  // datapath logic only. Because it is a multi-cycle path, it can be
+  // clocked by either CLKDIV0 or CLK0.
+  FDRSE u_ff_phy_init_data_sel
+    (
+     .Q   (phy_init_data_sel),
+     .C   (clkdiv0),
+     .CE  (1'b1),
+     .D   (phy_init_done_r1),
+     .R   (1'b0),
+     .S   (1'b0)
+     ) /* synthesis syn_preserve=1 */
+       /* synthesis syn_replicate = 0 */;
+
+  //synthesis translate_off
+  always @(posedge calib_done[0])
+      $display ("First Stage Calibration completed at time %t", $time);
+
+  always @(posedge calib_done[1])
+    $display ("Second Stage Calibration completed at time %t", $time);
+
+  always @(posedge calib_done[2]) begin
+    $display ("Third Stage Calibration completed at time %t", $time);
+  end
+
+  always @(posedge calib_done[3]) begin
+    $display ("Fourth Stage Calibration completed at time %t", $time);
+    $display ("Calibration completed at time %t", $time);
+  end
+  //synthesis translate_on
+
+  always @(posedge clkdiv0) begin
+    if ((init_cnt_r >= INIT_CNTR_DEEP_MEM))begin
+       init_done_r <= 1'b1;
+    end else
+       init_done_r <= 1'b0;
+  end
+
+  //*****************************************************************
+
+  always @(posedge clkdiv0)
+    if (rstdiv0) begin
+      init_state_r  <= INIT_IDLE;
+      init_state_r1 <= INIT_IDLE;
+      init_state_r2 <= INIT_IDLE;
+      calib_done_r  <= 4'b0000;
+    end else begin
+      init_state_r  <= init_next_state;
+      init_state_r1 <= init_state_r;
+      init_state_r2 <= init_state_r1;
+      calib_done_r  <= calib_done; // register for timing
+    end
+
+  always @(*) begin
+    init_next_state = init_state_r;
+    (* full_case, parallel_case *) case (init_state_r)
+      INIT_IDLE: begin
+        if (done_200us_r) begin
+          (* parallel_case *) case (init_cnt_r)
+            INIT_CNTR_INIT:
+              init_next_state = INIT_CNT_200;
+            INIT_CNTR_PRECH_1:
+              init_next_state = INIT_PRECHARGE;
+            INIT_CNTR_EMR2_INIT:
+              init_next_state = INIT_LOAD_MODE; // EMR(2)
+            INIT_CNTR_EMR3_INIT:
+              init_next_state = INIT_LOAD_MODE; // EMR(3);
+            INIT_CNTR_EMR_EN_DLL:
+              init_next_state = INIT_LOAD_MODE; // EMR, enable DLL
+            INIT_CNTR_MR_RST_DLL:
+              init_next_state = INIT_LOAD_MODE; // MR, reset DLL
+            INIT_CNTR_CNT_200_WAIT:begin
+              if(DDR_TYPE == DDR3)
+                 init_next_state = INIT_ZQCL; // DDR3
+              else
+                // Wait 200cc after reset DLL
+                init_next_state = INIT_CNT_200;
+            end
+            INIT_CNTR_PRECH_2:
+              init_next_state = INIT_PRECHARGE;
+            INIT_CNTR_AR_1:
+              init_next_state = INIT_AUTO_REFRESH;
+            INIT_CNTR_AR_2:
+              init_next_state = INIT_AUTO_REFRESH;
+            INIT_CNTR_MR_ACT_DLL:
+              init_next_state = INIT_LOAD_MODE; // MR, unreset DLL
+            INIT_CNTR_EMR_DEF_OCD:
+              init_next_state = INIT_LOAD_MODE; // EMR, OCD default
+            INIT_CNTR_EMR_EXIT_OCD:
+              init_next_state = INIT_LOAD_MODE; // EMR, enable OCD exit
+            INIT_CNTR_DEEP_MEM: begin
+               if ((chip_cnt_r < CS_NUM-1))
+                  init_next_state = INIT_DEEP_MEMORY_ST;
+              else if (cnt_200_cycle_done_r)
+                init_next_state = INIT_DUMMY_ACTIVE;
+              else
+                init_next_state = INIT_IDLE;
+            end
+            INIT_CNTR_PRECH_3:
+              init_next_state = INIT_PRECHARGE;
+            INIT_CNTR_DONE:
+              init_next_state = INIT_IDLE;
+            default :
+              init_next_state = INIT_IDLE;
+          endcase
+        end
+      end
+      INIT_CNT_200:
+        init_next_state = INIT_CNT_200_WAIT;
+      INIT_CNT_200_WAIT:
+        if (cnt_200_cycle_done_r)
+          init_next_state = INIT_IDLE;
+      INIT_PRECHARGE:
+        init_next_state = INIT_PRECHARGE_WAIT;
+      INIT_PRECHARGE_WAIT:
+        if (cnt_cmd_ok_r)begin
+          if (init_done_r && (!(&calib_done_r)))
+            init_next_state = INIT_AUTO_REFRESH;
+          else
+            init_next_state = INIT_IDLE;
+        end
+      INIT_ZQCL:
+        init_next_state = INIT_WAIT_DLLK_ZQINIT;
+      INIT_WAIT_DLLK_ZQINIT:
+        if (cnt_200_cycle_done_r)
+          init_next_state = INIT_IDLE;
+      INIT_LOAD_MODE:
+        init_next_state = INIT_MODE_REGISTER_WAIT;
+      INIT_MODE_REGISTER_WAIT:
+        if (cnt_cmd_ok_r)
+          init_next_state = INIT_IDLE;
+      INIT_AUTO_REFRESH:
+        init_next_state = INIT_AUTO_REFRESH_WAIT;
+      INIT_AUTO_REFRESH_WAIT:
+        if (cnt_cmd_ok_r)begin
+          if(init_done_r)
+            init_next_state = INIT_DUMMY_ACTIVE;
+          else
+            init_next_state = INIT_IDLE;
+        end
+      INIT_DEEP_MEMORY_ST:
+        init_next_state = INIT_IDLE;
+      // single row activate. All subsequent calibration writes and
+      // read will take place in this row
+      INIT_DUMMY_ACTIVE:
+        init_next_state = INIT_DUMMY_ACTIVE_WAIT;
+      INIT_DUMMY_ACTIVE_WAIT:
+        if (cnt_cmd_ok_r)begin
+          if (~calib_done_r[0]) begin
+            // if returning to stg1 after refresh, don't need to write
+            if (cal1_started_r)
+              init_next_state = INIT_CAL1_READ;
+            // if first entering stg1, need to write training pattern
+            else
+              init_next_state = INIT_CAL1_WRITE;
+          end else if (~calib_done[1]) begin
+            if (cal2_started_r)
+              init_next_state = INIT_CAL2_READ;
+            else
+              init_next_state = INIT_CAL2_WRITE;
+          end else if (~calib_done_r[2])
+             init_next_state = INIT_CAL3_WRITE;
+          else
+            init_next_state = INIT_CAL4_READ;
+        end
+      // Stage 1 calibration (write and continuous read)
+      INIT_CAL1_WRITE:
+        if (burst_addr_r == 2'b10)
+          init_next_state = INIT_CAL1_WRITE_READ;
+      INIT_CAL1_WRITE_READ:
+        if (cnt_cmd_ok_r)
+          init_next_state = INIT_CAL1_READ;
+      INIT_CAL1_READ:
+        // Stage 1 requires inter-stage auto-refresh
+        if (calib_done_r[0] || refresh_req)
+          init_next_state = INIT_CAL1_READ_WAIT;
+      INIT_CAL1_READ_WAIT:
+        if (cnt_cmd_ok_r)
+          init_next_state = INIT_CALIB_REF;
+      // Stage 2 calibration (write and continuous read)
+      INIT_CAL2_WRITE:
+        if (burst_addr_r == 2'b10)
+          init_next_state = INIT_CAL2_WRITE_READ;
+      INIT_CAL2_WRITE_READ:
+        if (cnt_cmd_ok_r)
+          init_next_state = INIT_CAL2_READ;
+      INIT_CAL2_READ:
+        // Stage 2 requires inter-stage auto-refresh
+        if (calib_done_r[1] || refresh_req)
+          init_next_state = INIT_CAL2_READ_WAIT;
+      INIT_CAL2_READ_WAIT:
+        if(cnt_cmd_ok_r)
+          init_next_state = INIT_CALIB_REF;
+      // Stage 3 calibration (write and continuous read)
+      INIT_CAL3_WRITE:
+        if (burst_addr_r == 2'b10)
+          init_next_state = INIT_CAL3_WRITE_READ;
+      INIT_CAL3_WRITE_READ:
+        if (cnt_cmd_ok_r)
+          init_next_state = INIT_CAL3_READ;
+      INIT_CAL3_READ:
+        if (burst_addr_r == 2'b10)
+          init_next_state = INIT_CAL3_READ_WAIT;
+      INIT_CAL3_READ_WAIT: begin
+        if (cnt_rd_ok_r)
+          if (calib_done_r[2]) begin
+            init_next_state = INIT_CALIB_REF;
+          end else
+            init_next_state = INIT_CAL3_READ;
+      end
+      // Stage 4 calibration (continuous read only, same pattern as stage 3)
+      // only used if DQS_GATE supported
+      INIT_CAL4_READ:
+        if (burst_addr_r == 2'b10)
+          init_next_state = INIT_CAL4_READ_WAIT;
+      INIT_CAL4_READ_WAIT: begin
+        if (cnt_rd_ok_r)
+          // Stage 4 requires inter-stage auto-refresh
+          if (calib_done_r[3] || refresh_req)
+            init_next_state = INIT_PRECHARGE;
+          else
+            init_next_state = INIT_CAL4_READ;
+      end
+      INIT_CALIB_REF:
+        init_next_state = INIT_PRECHARGE;
+    endcase
+  end
+
+  //***************************************************************************
+  // Memory control/address
+  //***************************************************************************
+
+  always @(posedge clkdiv0)
+    if ((init_state_r == INIT_DUMMY_ACTIVE) ||
+        (init_state_r == INIT_PRECHARGE) ||
+        (init_state_r == INIT_LOAD_MODE) ||
+        (init_state_r == INIT_AUTO_REFRESH)) begin
+      ddr_ras_n_r <= 1'b0;
+    end else begin
+      ddr_ras_n_r <= 1'b1;
+    end
+
+  always @(posedge clkdiv0)
+    if ((init_state_r == INIT_LOAD_MODE) ||
+        (init_state_r == INIT_AUTO_REFRESH) ||
+        (cal_write_read && (burst_cnt_r == 2'b00))) begin
+      ddr_cas_n_r <= 1'b0;
+    end else begin
+      ddr_cas_n_r <= 1'b1;
+    end
+
+  always @(posedge clkdiv0)
+    if ((init_state_r == INIT_LOAD_MODE) ||
+        (init_state_r == INIT_PRECHARGE) ||
+        (init_state_r == INIT_ZQCL) ||
+        (cal_write && (burst_cnt_r == 2'b00)))begin
+      ddr_we_n_r <= 1'b0;
+    end else begin
+      ddr_we_n_r <= 1'b1;
+    end
+
+  //*****************************************************************
+  // memory address during init
+  //*****************************************************************
+
+  always @(posedge clkdiv0) begin
+    if ((init_state_r == INIT_PRECHARGE)
+        || (init_state_r == INIT_ZQCL))begin
+      // Precharge all - set A10 = 1
+      ddr_addr_r <= {ROW_WIDTH{1'b0}};
+      ddr_addr_r[10] <= 1'b1;
+      ddr_ba_r <= {BANK_WIDTH{1'b0}};
+    end else if (init_state_r == INIT_LOAD_MODE) begin
+      ddr_ba_r <= {BANK_WIDTH{1'b0}};
+      ddr_addr_r <= {ROW_WIDTH{1'b0}};
+      case (init_cnt_r)
+        // EMR (2)
+        INIT_CNTR_EMR2_INIT: begin
+          ddr_ba_r[1:0] <= 2'b10;
+          ddr_addr_r    <= {ROW_WIDTH{1'b0}};
+        end
+        // EMR (3)
+        INIT_CNTR_EMR3_INIT: begin
+          ddr_ba_r[1:0] <= 2'b11;
+          if(DDR_TYPE == DDR3)
+            ddr_addr_r    <= load_mode_reg3[ROW_WIDTH-1:0];
+          else
+            ddr_addr_r    <= {ROW_WIDTH{1'b0}};
+        end
+        // EMR write - A0 = 0 for DLL enable
+        INIT_CNTR_EMR_EN_DLL: begin
+          ddr_ba_r[1:0] <= 2'b01;
+          if(DDR_TYPE == DDR3)
+            ddr_addr_r <= load_mode_reg1[ROW_WIDTH-1:0];
+          else
+            ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+        end
+        // MR write, reset DLL (A8=1)
+        INIT_CNTR_MR_RST_DLL: begin
+          if(DDR_TYPE == DDR3)
+            ddr_addr_r <= load_mode_reg0[ROW_WIDTH-1:0];
+          else
+            ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
+          ddr_ba_r[1:0] <= 2'b00;
+          ddr_addr_r[8] <= 1'b1;
+        end
+        // MR write, unreset DLL (A8=0)
+        INIT_CNTR_MR_ACT_DLL: begin
+          ddr_ba_r[1:0] <= 2'b00;
+          ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
+        end
+        // EMR write, OCD default state
+        INIT_CNTR_EMR_DEF_OCD: begin
+          ddr_ba_r[1:0] <= 2'b01;
+          ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+          ddr_addr_r[9:7] <= 3'b111;
+        end
+        // EMR write - OCD exit
+        INIT_CNTR_EMR_EXIT_OCD: begin
+          ddr_ba_r[1:0] <= 2'b01;
+          ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+        end
+        default: begin
+          ddr_ba_r <= {BANK_WIDTH{1'bx}};
+          ddr_addr_r <= {ROW_WIDTH{1'bx}};
+        end
+      endcase
+    end else if (cal_write_read) begin
+      // when writing or reading for Stages 2-4, since training pattern is
+      // either 4 (stage 2) or 8 (stage 3-4) long, if BURST LEN < 8, then
+      // need to issue multiple bursts to read entire training pattern
+      ddr_addr_r[ROW_WIDTH-1:3] <= {ROW_WIDTH-4{1'b0}};
+      ddr_addr_r[2:0]           <= {burst_addr_r, 1'b0};
+      ddr_ba_r                  <= {BANK_WIDTH-1{1'b0}};
+    end else if (init_state_r == INIT_DUMMY_ACTIVE) begin
+      // all calibration writing read takes place in row 0x0 only
+      ddr_ba_r   <= {BANK_WIDTH{1'b0}};
+      ddr_addr_r <= {ROW_WIDTH{1'b0}};
+    end else begin
+      // otherwise, cry me a river
+      ddr_ba_r   <= {BANK_WIDTH{1'bx}};
+      ddr_addr_r <= {ROW_WIDTH{1'bx}};
+    end
+  end
+
+  // Keep CKE asserted after initial power-on delay
+  always @(posedge clkdiv0)
+    ddr_cke_r <= {CKE_WIDTH{done_200us_r}};
+
+  // register commands to memory. Two clock cycle delay from state -> output
+  always @(posedge clk0) begin
+    ddr_addr_r1   <= ddr_addr_r;
+    ddr_ba_r1     <= ddr_ba_r;
+    ddr_cas_n_r1  <= ddr_cas_n_r;
+    ddr_ras_n_r1  <= ddr_ras_n_r;
+    ddr_we_n_r1   <= ddr_we_n_r;
+    ddr_cs_n_r1   <= ddr_cs_n_r;
+  end // always @ (posedge clk0)
+
+  // logic to toggle chip select. The chip_select is
+  // clocked of clkdiv0 and will be asserted for
+  // two clock cycles.
+   always @(posedge clk0) begin
+      if(rst0)
+        ddr_cs_disable_r <= {CS_NUM{1'b0}};
+      else begin
+         if(ddr_cs_disable_r[chip_cnt_r])
+            ddr_cs_disable_r[chip_cnt_r] <= 1'b0;
+         else begin
+            if(TWO_T_TIME_EN)
+               ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r1[chip_cnt_r];
+            else
+               ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r[chip_cnt_r];
+         end
+       end
+   end
+
+
+  assign phy_init_addr      = ddr_addr_r;
+  assign phy_init_ba        = ddr_ba_r;
+  assign phy_init_cas_n     = ddr_cas_n_r;
+  assign phy_init_cke       = ddr_cke_r;
+  assign phy_init_ras_n     = ddr_ras_n_r;
+  assign phy_init_we_n      = ddr_we_n_r;
+  assign phy_init_cs_n      = (TWO_T_TIME_EN) ?
+                              ddr_cs_n_r1 | ddr_cs_disable_r
+                              : ddr_cs_n_r| ddr_cs_disable_r;
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_io.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_io.v
new file mode 100644 (file)
index 0000000..ba82d5b
--- /dev/null
@@ -0,0 +1,354 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_io.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/29 15:24:03 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module instantiates calibration logic, data, data strobe and the
+//   data mask iobs.
+//Reference:
+//Revision History:
+//   Rev 1.1 - DM_IOB instance made based on USE_DM_PORT value . PK. 25/6/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_io #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter CLK_WIDTH             = 1,
+   parameter USE_DM_PORT           = 1,
+   parameter DM_WIDTH              = 9,
+   parameter DQ_WIDTH              = 72,
+   parameter DQ_BITS               = 7,
+   parameter DQ_PER_DQS            = 8,
+   parameter DQS_BITS              = 4,
+   parameter DQS_WIDTH             = 9,
+   parameter HIGH_PERFORMANCE_MODE = "TRUE",
+   parameter ODT_WIDTH             = 1,
+   parameter ADDITIVE_LAT          = 0,
+   parameter CAS_LAT               = 5,
+   parameter REG_ENABLE            = 1,
+   parameter CLK_PERIOD            = 3000,
+   parameter DDR_TYPE              = 1,
+   parameter SIM_ONLY              = 0,
+   parameter DEBUG_EN              = 0,
+   parameter DQS_IO_COL            = 0,
+   parameter DQ_IO_MS              = 0
+   )
+  (
+   input                                clk0,
+   input                                clk90,
+   input                                clkdiv0,
+   input                                rst0,
+   input                                rst90,
+   input                                rstdiv0,
+   input                                dm_ce,
+   input [1:0]                          dq_oe_n,
+   input                                dqs_oe_n,
+   input                                dqs_rst_n,
+   input [3:0]                          calib_start,
+   input                                ctrl_rden,
+   input                                phy_init_rden,
+   input                                calib_ref_done,
+   output [3:0]                         calib_done,
+   output                               calib_ref_req,
+   output [DQS_WIDTH-1:0]               calib_rden,
+   output [DQS_WIDTH-1:0]               calib_rden_sel,
+   input [DQ_WIDTH-1:0]                 wr_data_rise,
+   input [DQ_WIDTH-1:0]                 wr_data_fall,
+   input [(DQ_WIDTH/8)-1:0]             mask_data_rise,
+   input [(DQ_WIDTH/8)-1:0]             mask_data_fall,
+   output [(DQ_WIDTH)-1:0]              rd_data_rise,
+   output [(DQ_WIDTH)-1:0]              rd_data_fall,
+   output [CLK_WIDTH-1:0]               ddr_ck,
+   output [CLK_WIDTH-1:0]               ddr_ck_n,
+   output [DM_WIDTH-1:0]                ddr_dm,
+   inout [DQS_WIDTH-1:0]                ddr_dqs,
+   inout [DQS_WIDTH-1:0]                ddr_dqs_n,
+   inout [DQ_WIDTH-1:0]                 ddr_dq,
+   // Debug signals (optional use)
+   input                                dbg_idel_up_all,
+   input                                dbg_idel_down_all,
+   input                                dbg_idel_up_dq,
+   input                                dbg_idel_down_dq,
+   input                                dbg_idel_up_dqs,
+   input                                dbg_idel_down_dqs,
+   input                                dbg_idel_up_gate,
+   input                                dbg_idel_down_gate,
+   input [DQ_BITS-1:0]                  dbg_sel_idel_dq,
+   input                                dbg_sel_all_idel_dq,
+   input [DQS_BITS:0]                   dbg_sel_idel_dqs,
+   input                                dbg_sel_all_idel_dqs,
+   input [DQS_BITS:0]                   dbg_sel_idel_gate,
+   input                                dbg_sel_all_idel_gate,
+   output [3:0]                         dbg_calib_done,
+   output [3:0]                         dbg_calib_err,
+   output [(6*DQ_WIDTH)-1:0]            dbg_calib_dq_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]           dbg_calib_dqs_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]           dbg_calib_gate_tap_cnt,
+   output [DQS_WIDTH-1:0]               dbg_calib_rd_data_sel,
+   output [(5*DQS_WIDTH)-1:0]           dbg_calib_rden_dly,
+   output [(5*DQS_WIDTH)-1:0]           dbg_calib_gate_dly
+   );
+
+  // ratio of # of physical DM outputs to bytes in data bus
+  // may be different - e.g. if using x4 components
+  localparam DM_TO_BYTE_RATIO = DM_WIDTH / (DQ_WIDTH/8);
+
+  wire [CLK_WIDTH-1:0]                     ddr_ck_q;
+  wire [DQS_WIDTH-1:0]                     delayed_dqs;
+  wire [DQ_WIDTH-1:0]                      dlyce_dq;
+  wire [DQS_WIDTH-1:0]                     dlyce_dqs;
+  wire [DQS_WIDTH-1:0]                     dlyce_gate;
+  wire [DQ_WIDTH-1:0]                      dlyinc_dq;
+  wire [DQS_WIDTH-1:0]                     dlyinc_dqs;
+  wire [DQS_WIDTH-1:0]                     dlyinc_gate;
+  wire                                     dlyrst_dq;
+  wire                                     dlyrst_dqs;
+  wire [DQS_WIDTH-1:0]                     dlyrst_gate;
+  wire [DQS_WIDTH-1:0]                     dq_ce;
+  (* KEEP = "TRUE" *) wire [DQS_WIDTH-1:0] en_dqs /* synthesis syn_keep = 1 */;
+  wire [DQS_WIDTH-1:0]                     rd_data_sel;
+
+  //***************************************************************************
+
+  ddr2_phy_calib #
+    (
+     .DQ_WIDTH      (DQ_WIDTH),
+     .DQ_BITS       (DQ_BITS),
+     .DQ_PER_DQS    (DQ_PER_DQS),
+     .DQS_BITS      (DQS_BITS),
+     .DQS_WIDTH     (DQS_WIDTH),
+     .ADDITIVE_LAT  (ADDITIVE_LAT),
+     .CAS_LAT       (CAS_LAT),
+     .REG_ENABLE    (REG_ENABLE),
+     .CLK_PERIOD    (CLK_PERIOD),
+     .SIM_ONLY      (SIM_ONLY),
+     .DEBUG_EN      (DEBUG_EN)
+     )
+    u_phy_calib
+      (
+       .clk                    (clk0),
+       .clkdiv                 (clkdiv0),
+       .rstdiv                 (rstdiv0),
+       .calib_start            (calib_start),
+       .ctrl_rden              (ctrl_rden),
+       .phy_init_rden          (phy_init_rden),
+       .rd_data_rise           (rd_data_rise),
+       .rd_data_fall           (rd_data_fall),
+       .calib_ref_done         (calib_ref_done),
+       .calib_done             (calib_done),
+       .calib_ref_req          (calib_ref_req),
+       .calib_rden             (calib_rden),
+       .calib_rden_sel         (calib_rden_sel),
+       .dlyrst_dq              (dlyrst_dq),
+       .dlyce_dq               (dlyce_dq),
+       .dlyinc_dq              (dlyinc_dq),
+       .dlyrst_dqs             (dlyrst_dqs),
+       .dlyce_dqs              (dlyce_dqs),
+       .dlyinc_dqs             (dlyinc_dqs),
+       .dlyrst_gate            (dlyrst_gate),
+       .dlyce_gate             (dlyce_gate),
+       .dlyinc_gate            (dlyinc_gate),
+       .en_dqs                 (en_dqs),
+       .rd_data_sel            (rd_data_sel),
+       .dbg_idel_up_all        (dbg_idel_up_all),
+       .dbg_idel_down_all      (dbg_idel_down_all),
+       .dbg_idel_up_dq         (dbg_idel_up_dq),
+       .dbg_idel_down_dq       (dbg_idel_down_dq),
+       .dbg_idel_up_dqs        (dbg_idel_up_dqs),
+       .dbg_idel_down_dqs      (dbg_idel_down_dqs),
+       .dbg_idel_up_gate       (dbg_idel_up_gate),
+       .dbg_idel_down_gate     (dbg_idel_down_gate),
+       .dbg_sel_idel_dq        (dbg_sel_idel_dq),
+       .dbg_sel_all_idel_dq    (dbg_sel_all_idel_dq),
+       .dbg_sel_idel_dqs       (dbg_sel_idel_dqs),
+       .dbg_sel_all_idel_dqs   (dbg_sel_all_idel_dqs),
+       .dbg_sel_idel_gate      (dbg_sel_idel_gate),
+       .dbg_sel_all_idel_gate  (dbg_sel_all_idel_gate),
+       .dbg_calib_done         (dbg_calib_done),
+       .dbg_calib_err          (dbg_calib_err),
+       .dbg_calib_dq_tap_cnt   (dbg_calib_dq_tap_cnt),
+       .dbg_calib_dqs_tap_cnt  (dbg_calib_dqs_tap_cnt),
+       .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+       .dbg_calib_rd_data_sel  (dbg_calib_rd_data_sel),
+       .dbg_calib_rden_dly     (dbg_calib_rden_dly),
+       .dbg_calib_gate_dly     (dbg_calib_gate_dly)
+       );
+
+  //***************************************************************************
+  // Memory clock generation
+  //***************************************************************************
+
+  genvar ck_i;
+  generate
+    for(ck_i = 0; ck_i < CLK_WIDTH; ck_i = ck_i+1) begin: gen_ck
+      ODDR #
+        (
+         .SRTYPE       ("SYNC"),
+         .DDR_CLK_EDGE ("OPPOSITE_EDGE")
+         )
+        u_oddr_ck_i
+          (
+           .Q   (ddr_ck_q[ck_i]),
+           .C   (clk0),
+           .CE  (1'b1),
+           .D1  (1'b0),
+           .D2  (1'b1),
+           .R   (1'b0),
+           .S   (1'b0)
+           );
+      // Can insert ODELAY here if required
+      OBUFDS u_obuf_ck_i
+        (
+         .I   (ddr_ck_q[ck_i]),
+         .O   (ddr_ck[ck_i]),
+         .OB  (ddr_ck_n[ck_i])
+         );
+    end
+  endgenerate
+
+  //***************************************************************************
+  // DQS instances
+  //***************************************************************************
+
+  genvar dqs_i;
+  generate
+    for(dqs_i = 0; dqs_i < DQS_WIDTH; dqs_i = dqs_i+1) begin: gen_dqs
+      ddr2_phy_dqs_iob #
+        (
+         .DDR_TYPE              (DDR_TYPE),
+         .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE)
+         )
+        u_iob_dqs
+          (
+           .clk0           (clk0),
+           .clkdiv0        (clkdiv0),
+           .rst0           (rst0),
+           .dlyinc_dqs     (dlyinc_dqs[dqs_i]),
+           .dlyce_dqs      (dlyce_dqs[dqs_i]),
+           .dlyrst_dqs     (dlyrst_dqs),
+           .dlyinc_gate    (dlyinc_gate[dqs_i]),
+           .dlyce_gate     (dlyce_gate[dqs_i]),
+           .dlyrst_gate    (dlyrst_gate[dqs_i]),
+           .dqs_oe_n       (dqs_oe_n),
+           .dqs_rst_n      (dqs_rst_n),
+           .en_dqs         (en_dqs[dqs_i]),
+           .ddr_dqs        (ddr_dqs[dqs_i]),
+           .ddr_dqs_n      (ddr_dqs_n[dqs_i]),
+           .dq_ce          (dq_ce[dqs_i]),
+           .delayed_dqs    (delayed_dqs[dqs_i])
+           );
+    end
+  endgenerate
+
+  //***************************************************************************
+  // DM instances
+  //***************************************************************************
+
+  genvar dm_i;
+  generate
+    if (USE_DM_PORT) begin: gen_dm_inst
+      for(dm_i = 0; dm_i < DM_WIDTH; dm_i = dm_i+1) begin: gen_dm
+        ddr2_phy_dm_iob u_iob_dm
+          (
+           .clk90           (clk90),
+           .dm_ce           (dm_ce),
+           .mask_data_rise  (mask_data_rise[dm_i/DM_TO_BYTE_RATIO]),
+           .mask_data_fall  (mask_data_fall[dm_i/DM_TO_BYTE_RATIO]),
+           .ddr_dm          (ddr_dm[dm_i])
+           );
+      end
+    end
+  endgenerate
+
+  //***************************************************************************
+  // DQ IOB instances
+  //***************************************************************************
+
+  genvar dq_i;
+  generate
+    for(dq_i = 0; dq_i < DQ_WIDTH; dq_i = dq_i+1) begin: gen_dq
+      ddr2_phy_dq_iob #
+        (
+         .DQ_COL (DQS_IO_COL[2*(dq_i/DQ_PER_DQS)+1:2*(dq_i/DQ_PER_DQS)]),
+         .DQ_MS  (DQ_IO_MS[dq_i]),
+         .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE)
+         )
+        u_iob_dq
+        (
+         .clk0         (clk0),
+         .clk90        (clk90),
+         .clkdiv0      (clkdiv0),
+         .rst90        (rst90),
+         .dlyinc       (dlyinc_dq[dq_i]),
+         .dlyce        (dlyce_dq[dq_i]),
+         .dlyrst       (dlyrst_dq),
+         .dq_oe_n      (dq_oe_n),
+         .dqs          (delayed_dqs[dq_i/DQ_PER_DQS]),
+         .ce           (dq_ce[dq_i/DQ_PER_DQS]),
+         .rd_data_sel  (rd_data_sel[dq_i/DQ_PER_DQS]),
+         .wr_data_rise (wr_data_rise[dq_i]),
+         .wr_data_fall (wr_data_fall[dq_i]),
+         .rd_data_rise (rd_data_rise[dq_i]),
+         .rd_data_fall (rd_data_fall[dq_i]),
+         .ddr_dq       (ddr_dq[dq_i])
+         );
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_top.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_top.v
new file mode 100644 (file)
index 0000000..bf3baf0
--- /dev/null
@@ -0,0 +1,393 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_top.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/22 15:41:06 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   Top-level for memory physical layer (PHY) interface
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+(* X_CORE_INFO = "mig_v2_3_ddr2_v5, Coregen 10.1.02" , CORE_GENERATION_INFO = "ddr2_v5,mig_v2_3,{component_name=ddr2_phy_top, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=5000, RST_ACT_LOW=1}" *)
+module ddr2_phy_top #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH            = 2,
+   parameter CLK_WIDTH             = 1,
+   parameter CKE_WIDTH             = 1,
+   parameter COL_WIDTH             = 10,
+   parameter CS_NUM                = 1,
+   parameter CS_WIDTH              = 1,
+   parameter USE_DM_PORT           = 1,
+   parameter DM_WIDTH              = 9,
+   parameter DQ_WIDTH              = 72,
+   parameter DQ_BITS               = 7,
+   parameter DQ_PER_DQS            = 8,
+   parameter DQS_WIDTH             = 9,
+   parameter DQS_BITS              = 4,
+   parameter HIGH_PERFORMANCE_MODE = "TRUE",
+   parameter ODT_WIDTH             = 1,
+   parameter ROW_WIDTH             = 14,
+   parameter ADDITIVE_LAT          = 0,
+   parameter TWO_T_TIME_EN         = 0,
+   parameter BURST_LEN             = 4,
+   parameter BURST_TYPE            = 0,
+   parameter CAS_LAT               = 5,
+   parameter TWR                   = 15000,
+   parameter ECC_ENABLE            = 0,
+   parameter ODT_TYPE              = 1,
+   parameter DDR_TYPE              = 1,
+   parameter REDUCE_DRV            = 0,
+   parameter REG_ENABLE            = 1,
+   parameter CLK_PERIOD            = 3000,
+   parameter SIM_ONLY              = 0,
+   parameter DEBUG_EN              = 0,
+   parameter DQS_IO_COL            = 0,
+   parameter DQ_IO_MS              = 0
+   )
+  (
+   input                                  clk0,
+   input                                  clk90,
+   input                                  clkdiv0,
+   input                                  rst0,
+   input                                  rst90,
+   input                                  rstdiv0,
+   input                                  ctrl_wren,
+   input [ROW_WIDTH-1:0]                  ctrl_addr,
+   input [BANK_WIDTH-1:0]                 ctrl_ba,
+   input                                  ctrl_ras_n,
+   input                                  ctrl_cas_n,
+   input                                  ctrl_we_n,
+   input [CS_NUM-1:0]                     ctrl_cs_n,
+   input                                  ctrl_rden,
+   input                                  ctrl_ref_flag,
+   input [(2*DQ_WIDTH)-1:0]               wdf_data,
+   input [(2*DQ_WIDTH/8)-1:0]             wdf_mask_data,
+   output                                 wdf_rden,
+   output                                 phy_init_done,
+   output [DQS_WIDTH-1:0]                 phy_calib_rden,
+   output [DQS_WIDTH-1:0]                 phy_calib_rden_sel,
+   output [DQ_WIDTH-1:0]                  rd_data_rise,
+   output [DQ_WIDTH-1:0]                  rd_data_fall,
+   output [CLK_WIDTH-1:0]                 ddr_ck,
+   output [CLK_WIDTH-1:0]                 ddr_ck_n,
+   output [ROW_WIDTH-1:0]                 ddr_addr,
+   output [BANK_WIDTH-1:0]                ddr_ba,
+   output                                 ddr_ras_n,
+   output                                 ddr_cas_n,
+   output                                 ddr_we_n,
+   output [CS_WIDTH-1:0]                  ddr_cs_n,
+   output [CKE_WIDTH-1:0]                 ddr_cke,
+   output [ODT_WIDTH-1:0]                 ddr_odt,
+   output [DM_WIDTH-1:0]                  ddr_dm,
+   inout [DQS_WIDTH-1:0]                  ddr_dqs,
+   inout [DQS_WIDTH-1:0]                  ddr_dqs_n,
+   inout [DQ_WIDTH-1:0]                   ddr_dq,
+   // Debug signals (optional use)
+   input                                  dbg_idel_up_all,
+   input                                  dbg_idel_down_all,
+   input                                  dbg_idel_up_dq,
+   input                                  dbg_idel_down_dq,
+   input                                  dbg_idel_up_dqs,
+   input                                  dbg_idel_down_dqs,
+   input                                  dbg_idel_up_gate,
+   input                                  dbg_idel_down_gate,
+   input [DQ_BITS-1:0]                    dbg_sel_idel_dq,
+   input                                  dbg_sel_all_idel_dq,
+   input [DQS_BITS:0]                     dbg_sel_idel_dqs,
+   input                                  dbg_sel_all_idel_dqs,
+   input [DQS_BITS:0]                     dbg_sel_idel_gate,
+   input                                  dbg_sel_all_idel_gate,
+   output [3:0]                           dbg_calib_done,
+   output [3:0]                           dbg_calib_err,
+   output [(6*DQ_WIDTH)-1:0]              dbg_calib_dq_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]             dbg_calib_dqs_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]             dbg_calib_gate_tap_cnt,
+   output [DQS_WIDTH-1:0]                 dbg_calib_rd_data_sel,
+   output [(5*DQS_WIDTH)-1:0]             dbg_calib_rden_dly,
+   output [(5*DQS_WIDTH)-1:0]             dbg_calib_gate_dly
+   );
+
+  wire [3:0]               calib_done;
+  wire                     calib_ref_done;
+  wire                     calib_ref_req;
+  wire [3:0]               calib_start;
+  wire                     dm_ce;
+  wire [1:0]               dq_oe_n;
+  wire                     dqs_oe_n;
+  wire                     dqs_rst_n;
+  wire [(DQ_WIDTH/8)-1:0]  mask_data_fall;
+  wire [(DQ_WIDTH/8)-1:0]  mask_data_rise;
+  wire [CS_NUM-1:0]        odt;
+  wire [ROW_WIDTH-1:0]     phy_init_addr;
+  wire [BANK_WIDTH-1:0]    phy_init_ba;
+  wire                     phy_init_cas_n;
+  wire [CKE_WIDTH-1:0]     phy_init_cke;
+  wire [CS_NUM-1:0]        phy_init_cs_n;
+  wire                     phy_init_data_sel;
+  wire                     phy_init_ras_n;
+  wire                     phy_init_rden;
+  wire                     phy_init_we_n;
+  wire                     phy_init_wren;
+  wire [DQ_WIDTH-1:0]      wr_data_fall;
+  wire [DQ_WIDTH-1:0]      wr_data_rise;
+
+  //***************************************************************************
+
+  ddr2_phy_write #
+    (
+     .DQ_WIDTH     (DQ_WIDTH),
+     .CS_NUM       (CS_NUM),
+     .ADDITIVE_LAT (ADDITIVE_LAT),
+     .CAS_LAT      (CAS_LAT),
+     .ECC_ENABLE   (ECC_ENABLE),
+     .ODT_TYPE     (ODT_TYPE),
+     .REG_ENABLE   (REG_ENABLE),
+     .DDR_TYPE     (DDR_TYPE)
+     )
+    u_phy_write
+      (
+       .clk0                    (clk0),
+       .clk90                   (clk90),
+       .rst90                   (rst90),
+       .wdf_data                (wdf_data),
+       .wdf_mask_data           (wdf_mask_data),
+       .ctrl_wren               (ctrl_wren),
+       .phy_init_wren           (phy_init_wren),
+       .phy_init_data_sel       (phy_init_data_sel),
+       .dm_ce                   (dm_ce),
+       .dq_oe_n                 (dq_oe_n),
+       .dqs_oe_n                (dqs_oe_n),
+       .dqs_rst_n               (dqs_rst_n),
+       .wdf_rden                (wdf_rden),
+       .odt                     (odt),
+       .wr_data_rise            (wr_data_rise),
+       .wr_data_fall            (wr_data_fall),
+       .mask_data_rise          (mask_data_rise),
+       .mask_data_fall          (mask_data_fall)
+       );
+
+  ddr2_phy_io #
+    (
+     .CLK_WIDTH             (CLK_WIDTH),
+     .USE_DM_PORT           (USE_DM_PORT),
+     .DM_WIDTH              (DM_WIDTH),
+     .DQ_WIDTH              (DQ_WIDTH),
+     .DQ_BITS               (DQ_BITS),
+     .DQ_PER_DQS            (DQ_PER_DQS),
+     .DQS_BITS              (DQS_BITS),
+     .DQS_WIDTH             (DQS_WIDTH),
+     .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+     .ODT_WIDTH             (ODT_WIDTH),
+     .ADDITIVE_LAT          (ADDITIVE_LAT),
+     .CAS_LAT               (CAS_LAT),
+     .REG_ENABLE            (REG_ENABLE),
+     .CLK_PERIOD            (CLK_PERIOD),
+     .DDR_TYPE              (DDR_TYPE),
+     .SIM_ONLY              (SIM_ONLY),
+     .DEBUG_EN              (DEBUG_EN),
+     .DQS_IO_COL            (DQS_IO_COL),
+     .DQ_IO_MS              (DQ_IO_MS)
+     )
+    u_phy_io
+      (
+       .clk0                   (clk0),
+       .clk90                  (clk90),
+       .clkdiv0                (clkdiv0),
+       .rst0                   (rst0),
+       .rst90                  (rst90),
+       .rstdiv0                (rstdiv0),
+       .dm_ce                  (dm_ce),
+       .dq_oe_n                (dq_oe_n),
+       .dqs_oe_n               (dqs_oe_n),
+       .dqs_rst_n              (dqs_rst_n),
+       .calib_start            (calib_start),
+       .ctrl_rden              (ctrl_rden),
+       .phy_init_rden          (phy_init_rden),
+       .calib_ref_done         (calib_ref_done),
+       .calib_done             (calib_done),
+       .calib_ref_req          (calib_ref_req),
+       .calib_rden             (phy_calib_rden),
+       .calib_rden_sel         (phy_calib_rden_sel),
+       .wr_data_rise           (wr_data_rise),
+       .wr_data_fall           (wr_data_fall),
+       .mask_data_rise         (mask_data_rise),
+       .mask_data_fall         (mask_data_fall),
+       .rd_data_rise           (rd_data_rise),
+       .rd_data_fall           (rd_data_fall),
+       .ddr_ck                 (ddr_ck),
+       .ddr_ck_n               (ddr_ck_n),
+       .ddr_dm                 (ddr_dm),
+       .ddr_dqs                (ddr_dqs),
+       .ddr_dqs_n              (ddr_dqs_n),
+       .ddr_dq                 (ddr_dq),
+       .dbg_idel_up_all        (dbg_idel_up_all),
+       .dbg_idel_down_all      (dbg_idel_down_all),
+       .dbg_idel_up_dq         (dbg_idel_up_dq),
+       .dbg_idel_down_dq       (dbg_idel_down_dq),
+       .dbg_idel_up_dqs        (dbg_idel_up_dqs),
+       .dbg_idel_down_dqs      (dbg_idel_down_dqs),
+       .dbg_idel_up_gate       (dbg_idel_up_gate),
+       .dbg_idel_down_gate     (dbg_idel_down_gate),
+       .dbg_sel_idel_dq        (dbg_sel_idel_dq),
+       .dbg_sel_all_idel_dq    (dbg_sel_all_idel_dq),
+       .dbg_sel_idel_dqs       (dbg_sel_idel_dqs),
+       .dbg_sel_all_idel_dqs   (dbg_sel_all_idel_dqs),
+       .dbg_sel_idel_gate      (dbg_sel_idel_gate),
+       .dbg_sel_all_idel_gate  (dbg_sel_all_idel_gate),
+       .dbg_calib_done         (dbg_calib_done),
+       .dbg_calib_err          (dbg_calib_err),
+       .dbg_calib_dq_tap_cnt   (dbg_calib_dq_tap_cnt),
+       .dbg_calib_dqs_tap_cnt  (dbg_calib_dqs_tap_cnt),
+       .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+       .dbg_calib_rd_data_sel  (dbg_calib_rd_data_sel),
+       .dbg_calib_rden_dly     (dbg_calib_rden_dly),
+       .dbg_calib_gate_dly     (dbg_calib_gate_dly)
+       );
+
+  ddr2_phy_ctl_io #
+    (
+     .BANK_WIDTH    (BANK_WIDTH),
+     .CKE_WIDTH     (CKE_WIDTH),
+     .COL_WIDTH     (COL_WIDTH),
+     .CS_NUM        (CS_NUM),
+     .CS_WIDTH      (CS_WIDTH),
+     .TWO_T_TIME_EN (TWO_T_TIME_EN),
+     .ODT_WIDTH     (ODT_WIDTH),
+     .ROW_WIDTH     (ROW_WIDTH),
+     .DDR_TYPE      (DDR_TYPE)
+     )
+    u_phy_ctl_io
+      (
+       .clk0                    (clk0),
+       .clk90                   (clk90),
+       .rst0                    (rst0),
+       .rst90                   (rst90),
+       .ctrl_addr               (ctrl_addr),
+       .ctrl_ba                 (ctrl_ba),
+       .ctrl_ras_n              (ctrl_ras_n),
+       .ctrl_cas_n              (ctrl_cas_n),
+       .ctrl_we_n               (ctrl_we_n),
+       .ctrl_cs_n               (ctrl_cs_n),
+       .phy_init_addr           (phy_init_addr),
+       .phy_init_ba             (phy_init_ba),
+       .phy_init_ras_n          (phy_init_ras_n),
+       .phy_init_cas_n          (phy_init_cas_n),
+       .phy_init_we_n           (phy_init_we_n),
+       .phy_init_cs_n           (phy_init_cs_n),
+       .phy_init_cke            (phy_init_cke),
+       .phy_init_data_sel       (phy_init_data_sel),
+       .odt                     (odt),
+       .ddr_addr                (ddr_addr),
+       .ddr_ba                  (ddr_ba),
+       .ddr_ras_n               (ddr_ras_n),
+       .ddr_cas_n               (ddr_cas_n),
+       .ddr_we_n                (ddr_we_n),
+       .ddr_cke                 (ddr_cke),
+       .ddr_cs_n                (ddr_cs_n),
+       .ddr_odt                 (ddr_odt)
+       );
+
+  ddr2_phy_init #
+    (
+     .BANK_WIDTH   (BANK_WIDTH),
+     .CKE_WIDTH    (CKE_WIDTH),
+     .COL_WIDTH    (COL_WIDTH),
+     .CS_NUM       (CS_NUM),
+     .DQ_WIDTH     (DQ_WIDTH),
+     .ODT_WIDTH    (ODT_WIDTH),
+     .ROW_WIDTH    (ROW_WIDTH),
+     .ADDITIVE_LAT (ADDITIVE_LAT),
+     .BURST_LEN    (BURST_LEN),
+     .BURST_TYPE   (BURST_TYPE),
+     .TWO_T_TIME_EN(TWO_T_TIME_EN),
+     .CAS_LAT      (CAS_LAT),
+     .ODT_TYPE     (ODT_TYPE),
+     .REDUCE_DRV   (REDUCE_DRV),
+     .REG_ENABLE   (REG_ENABLE),
+     .TWR          (TWR),
+     .CLK_PERIOD   (CLK_PERIOD),
+     .DDR_TYPE     (DDR_TYPE),
+     .SIM_ONLY     (SIM_ONLY)
+     )
+    u_phy_init
+      (
+       .clk0                    (clk0),
+       .clkdiv0                 (clkdiv0),
+       .rst0                    (rst0),
+       .rstdiv0                 (rstdiv0),
+       .calib_done              (calib_done),
+       .ctrl_ref_flag           (ctrl_ref_flag),
+       .calib_ref_req           (calib_ref_req),
+       .calib_start             (calib_start),
+       .calib_ref_done          (calib_ref_done),
+       .phy_init_wren           (phy_init_wren),
+       .phy_init_rden           (phy_init_rden),
+       .phy_init_addr           (phy_init_addr),
+       .phy_init_ba             (phy_init_ba),
+       .phy_init_ras_n          (phy_init_ras_n),
+       .phy_init_cas_n          (phy_init_cas_n),
+       .phy_init_we_n           (phy_init_we_n),
+       .phy_init_cs_n           (phy_init_cs_n),
+       .phy_init_cke            (phy_init_cke),
+       .phy_init_done           (phy_init_done),
+       .phy_init_data_sel       (phy_init_data_sel)
+       );
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_write.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_phy_write.v
new file mode 100644 (file)
index 0000000..4b9b3e0
--- /dev/null
@@ -0,0 +1,446 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_phy_write.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/29 15:24:03 $
+// \   \  /  \    Date Created: Thu Aug 24 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//Reference:
+//   Handles delaying various write control signals appropriately depending
+//   on CAS latency, additive latency, etc. Also splits the data and mask in
+//   rise and fall buses.
+//Revision History:
+//   Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_write #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter DQ_WIDTH      = 72,
+   parameter CS_NUM        = 1,
+   parameter ADDITIVE_LAT  = 0,
+   parameter CAS_LAT       = 5,
+   parameter ECC_ENABLE    = 0,
+   parameter ODT_TYPE      = 1,
+   parameter REG_ENABLE    = 1,
+   parameter DDR_TYPE      = 1
+   )
+  (
+   input                       clk0,
+   input                       clk90,
+   input                       rst90,
+   input [(2*DQ_WIDTH)-1:0]    wdf_data,
+   input [(2*DQ_WIDTH/8)-1:0]  wdf_mask_data,
+   input                       ctrl_wren,
+   input                       phy_init_wren,
+   input                       phy_init_data_sel,
+   output reg                  dm_ce,
+   output reg [1:0]            dq_oe_n,
+   output reg                  dqs_oe_n ,
+   output reg                  dqs_rst_n ,
+   output                      wdf_rden,
+   output reg [CS_NUM-1:0]     odt ,
+   output [DQ_WIDTH-1:0]       wr_data_rise,
+   output [DQ_WIDTH-1:0]       wr_data_fall,
+   output [(DQ_WIDTH/8)-1:0]   mask_data_rise,
+   output [(DQ_WIDTH/8)-1:0]   mask_data_fall
+   );
+
+  localparam   MASK_WIDTH               = DQ_WIDTH/8;
+  localparam   DDR1                     = 0;
+  localparam   DDR2                     = 1;
+  localparam   DDR3                     = 2;
+
+  // (MIN,MAX) value of WR_LATENCY for DDR1:
+  //   REG_ENABLE   = (0,1)
+  //   ECC_ENABLE   = (0,1)
+  //   Write latency = 1
+  //   Total: (1,3)
+  // (MIN,MAX) value of WR_LATENCY for DDR2:
+  //   REG_ENABLE   = (0,1)
+  //   ECC_ENABLE   = (0,1)
+  //   Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
+  //     ADDITIVE_LAT = (0,4) (JEDEC79-2B)
+  //     CAS_LAT      = (3,5) (JEDEC79-2B)
+  //   Total: (2,10)
+  localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
+             (ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
+             (DDR_TYPE == DDR2) ?
+             (ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
+             (1 + REG_ENABLE );
+
+  // NOTE that ODT timing does not need to be delayed for registered
+  // DIMM case, since like other control/address signals, it gets
+  // delayed by one clock cycle at the DIMM
+  localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
+
+  wire                     dm_ce_0;
+  reg                      dm_ce_r;
+  wire [1:0]               dq_oe_0;
+  reg [1:0]                dq_oe_n_90_r1;
+  reg [1:0]                dq_oe_270;
+  wire                     dqs_oe_0;
+  reg                      dqs_oe_270;
+  reg                      dqs_oe_n_180_r1;
+  wire                     dqs_rst_0;
+  reg                      dqs_rst_n_180_r1;
+  reg                      dqs_rst_270;
+  reg                      ecc_dm_error_r;
+  reg                      ecc_dm_error_r1;
+  reg [(DQ_WIDTH-1):0]     init_data_f;
+  reg [(DQ_WIDTH-1):0]     init_data_r;
+  reg [3:0]                init_wdf_cnt_r;
+  wire                     odt_0;
+  reg                      rst90_r /* synthesis syn_maxfan = 10 */;
+  reg [10:0]               wr_stages ;
+  reg [(2*DQ_WIDTH)-1:0]   wdf_data_r;
+  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
+  wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
+
+  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
+  wire                     wdf_rden_0;
+  reg                      calib_rden_90_r;
+  reg                      wdf_rden_90_r;
+  reg                      wdf_rden_90_r1;
+  reg                      wdf_rden_270;
+
+  always @(posedge clk90)
+      rst90_r <= rst90;
+
+  //***************************************************************************
+  // Analysis of additional pipeline delays:
+  //   1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
+  //   2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
+  //   3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
+  //      in IOB DDR
+  //   4. odt (ODT control): 1 CLK0 cyc in IOB FF
+  //   5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
+  //      output register enabled): 2 CLK90 cyc in OSERDES
+  //***************************************************************************
+
+  // DQS 3-state must be asserted one extra clock cycle due b/c of write
+  // pre- and post-amble (extra half clock cycle for each)
+  assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
+
+  // same goes for ODT, need to handle both pre- and post-amble (generate
+  // ODT only for DDR2)
+  // ODT generation for DDR2 based on write latency. The MIN write
+  // latency is 2. Based on the write latency ODT is asserted.
+  generate
+    if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
+       if(ODT_WR_LATENCY > 2)
+         assign odt_0 =
+                   wr_stages[ODT_WR_LATENCY-1] |
+                   wr_stages[ODT_WR_LATENCY-2] |
+                   wr_stages[ODT_WR_LATENCY-3] ;
+       else
+         assign odt_0 =
+                  wr_stages[ODT_WR_LATENCY] |
+                  wr_stages[ODT_WR_LATENCY-1] |
+                  wr_stages[ODT_WR_LATENCY-2] ;
+    end else
+      assign odt_0 = 1'b0;
+   endgenerate
+
+  assign dq_oe_0[0]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
+  assign dq_oe_0[1]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
+  assign dqs_rst_0    = ~wr_stages[WR_LATENCY-2];
+  assign dm_ce_0      = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
+                        | wr_stages[WR_LATENCY-2];
+
+  // write data fifo, read flag assertion
+  generate
+    if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
+      if (WR_LATENCY > 2)
+        assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
+      else
+        assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
+    end else begin: gen_wdf_ddr1
+      assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
+    end
+  endgenerate
+
+  // first stage isn't registered
+  always @(*)
+    wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
+
+  always @(posedge clk0) begin
+    wr_stages[1] <= wr_stages[0];
+    wr_stages[2] <= wr_stages[1];
+    wr_stages[3] <= wr_stages[2];
+    wr_stages[4] <= wr_stages[3];
+    wr_stages[5] <= wr_stages[4];
+    wr_stages[6] <= wr_stages[5];
+    wr_stages[7] <= wr_stages[6];
+    wr_stages[8] <= wr_stages[7];
+    wr_stages[9] <= wr_stages[8];
+    wr_stages[10] <= wr_stages[9];
+  end
+
+  // intermediate synchronization to CLK270
+  always @(negedge clk90) begin
+    dq_oe_270         <= dq_oe_0;
+    dqs_oe_270        <= dqs_oe_0;
+    dqs_rst_270       <= dqs_rst_0;
+    wdf_rden_270      <= wdf_rden_0;
+  end
+
+  // synchronize DQS signals to CLK180
+  always @(negedge clk0) begin
+    dqs_oe_n_180_r1  <= ~dqs_oe_270;
+    dqs_rst_n_180_r1 <= ~dqs_rst_270;
+  end
+
+  // All write data-related signals synced to CLK90
+  always @(posedge clk90) begin
+    dq_oe_n_90_r1  <= ~dq_oe_270;
+    wdf_rden_90_r  <= wdf_rden_270;
+  end
+
+  // generate for wdf_rden and calib rden. These signals
+  // are asserted based on write latency. For write
+  // latency of 2, the extra register stage is taken out.
+  generate
+   if (WR_LATENCY > 2) begin
+     always @(posedge clk90) begin
+        // assert wdf rden only for non calibration opertations
+        wdf_rden_90_r1 <=  wdf_rden_90_r &
+                           phy_init_data_sel;
+        // rden for calibration
+        calib_rden_90_r <= wdf_rden_90_r;
+     end
+   end else begin
+     always @(*) begin
+        wdf_rden_90_r1 = wdf_rden_90_r
+                         & phy_init_data_sel;
+        calib_rden_90_r = wdf_rden_90_r;
+     end
+  end // else: !if(WR_LATENCY > 2)
+  endgenerate
+
+  // dm CE signal to stop dm oscilation
+  always @(negedge clk90)begin
+    dm_ce_r <= dm_ce_0;
+    dm_ce <= dm_ce_r;
+  end
+
+  // When in ECC mode the upper byte [71:64] will have the
+  // ECC parity. Mapping the bytes which have valid data
+  // to the upper byte in ecc mode. Also in ecc mode there
+  // is an extra register stage to account for timing.
+
+  genvar mask_i;
+  generate
+    if(ECC_ENABLE) begin
+      for (mask_i  = 0; mask_i < (2*DQ_WIDTH)/72;
+          mask_i = mask_i+1) begin: gen_mask
+       assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
+                {&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
+                wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
+      end
+    end
+   endgenerate
+
+  generate
+    if (ECC_ENABLE) begin:gen_ecc_reg
+       always @(posedge clk90)begin
+          if(phy_init_data_sel)
+               wdf_mask_r <= wdf_ecc_mask;
+          else
+             wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
+      end       
+    end else begin
+      always@(posedge clk90) begin
+        if (phy_init_data_sel)
+          wdf_mask_r <= wdf_mask_data;
+        else
+          wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
+      end
+    end
+  endgenerate
+
+   always @(posedge clk90) begin
+      if(phy_init_data_sel)
+          wdf_data_r <= wdf_data;
+      else
+          wdf_data_r <={init_data_f,init_data_r};
+   end
+
+  // Error generation block during simulation.
+  // Error will be displayed when all the DM
+  // bits are not zero. The error will be
+  // displayed only during the start of the sequence
+  // for errors that are continous over many cycles.
+  generate
+    if (ECC_ENABLE) begin: gen_ecc_error
+      always @(posedge clk90) begin
+        //synthesis translate_off
+        wdf_mask_r1 <= wdf_mask_r;
+        if(DQ_WIDTH > 72)
+           ecc_dm_error_r
+              <= (
+              (~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
+              (~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
+              (~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
+              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
+         else
+            ecc_dm_error_r
+              <= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
+              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
+        ecc_dm_error_r1 <= ecc_dm_error_r ;
+        if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
+          $display ("ECC DM ERROR. ");
+        //synthesis translate_on
+      end
+    end
+  endgenerate
+
+  //***************************************************************************
+  // State logic to write calibration training patterns
+  //***************************************************************************
+
+  always @(posedge clk90) begin
+    if (rst90_r) begin
+      init_wdf_cnt_r  <= 4'd0;
+      init_data_r <= {64{1'bx}};
+      init_data_f <= {64{1'bx}};
+    end else begin
+      init_wdf_cnt_r  <= init_wdf_cnt_r + calib_rden_90_r;
+      casex (init_wdf_cnt_r)
+        // First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
+        // The rise data and fall data are already interleaved in the manner
+        // required for data into the WDF write FIFO
+        4'b00xx: begin
+          init_data_r <= {DQ_WIDTH{1'b1}};
+          init_data_f <= {DQ_WIDTH{1'b0}};
+        end
+        // Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
+        4'b01x0: begin
+           init_data_r <= {DQ_WIDTH{1'b1}};
+           init_data_f <= {DQ_WIDTH{1'b1}};
+          end
+        4'b01x1: begin
+           init_data_r <= {DQ_WIDTH{1'b0}};
+           init_data_f <= {DQ_WIDTH{1'b0}};
+        end
+       // MIG 2.1: Changed Stage 3/4 training pattern
+        // Third and fourth stage calibration patern = 
+       //   11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
+        4'b1000: begin
+          init_data_r <= {DQ_WIDTH/4{4'h1}};
+          init_data_f <= {DQ_WIDTH/4{4'hE}};
+        end
+        4'b1001: begin
+          init_data_r <= {DQ_WIDTH/4{4'hE}};
+          init_data_f <= {DQ_WIDTH/4{4'h1}};
+          end
+        4'b1010: begin
+          init_data_r <= {(DQ_WIDTH/4){4'h1}};
+          init_data_f <= {(DQ_WIDTH/4){4'hE}};
+        end
+        4'b1011: begin
+          init_data_r <= {(DQ_WIDTH/4){4'hE}};
+          init_data_f <= {(DQ_WIDTH/4){4'h1}};
+         end
+        default: begin
+          init_data_f <= {(2*DQ_WIDTH){1'bx}};
+          init_data_r <= {(2*DQ_WIDTH){1'bx}};
+        end
+      endcase
+    end
+  end
+
+  //***************************************************************************
+
+  always @(posedge clk90)
+    dq_oe_n   <= dq_oe_n_90_r1;
+
+  always @(negedge clk0)
+    dqs_oe_n  <= dqs_oe_n_180_r1;
+
+  always @(negedge clk0)
+    dqs_rst_n <= dqs_rst_n_180_r1;
+
+  // generate for odt. odt is asserted based on
+  //  write latency. For write latency of 2
+  //  the extra register stage is taken out.
+  generate
+    if (ODT_WR_LATENCY > 2) begin
+      always @(posedge clk0) begin
+        odt    <= 'b0;
+        odt[0] <= odt_0;
+      end
+    end else begin
+      always @ (*) begin
+        odt = 'b0;
+        odt[0] = odt_0;
+      end
+    end
+  endgenerate
+
+  assign wdf_rden  = wdf_rden_90_r1;
+
+  //***************************************************************************
+  // Format write data/mask: Data is in format: {fall, rise}
+  //***************************************************************************
+
+  assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
+  assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
+  assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
+  assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_sdram.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_sdram.v
new file mode 100644 (file)
index 0000000..f4f9e14
--- /dev/null
@@ -0,0 +1,602 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_sdram.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/09 12:33:12 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   Top-level  module. Simple model for what the user might use
+//   Typically, the user will only instantiate MEM_INTERFACE_TOP in their
+//   code, and generate all backend logic (test bench) and all the other infrastructure logic
+//    separately. 
+//   In addition to the memory controller, the module instantiates:
+//     1. Reset logic based on user clocks
+//     2. IDELAY control block
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+(* X_CORE_INFO = "mig_v2_3_ddr2_sdram_v5, Coregen 10.1.02" , CORE_GENERATION_INFO = "ddr2_sdram_v5,mig_v2_3,{component_name=ddr2_sdram, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=5000, RST_ACT_LOW=1}" *)
+module ddr2_sdram #
+  (
+   parameter BANK_WIDTH              = 2,       
+                                       // # of memory bank addr bits.
+   parameter CKE_WIDTH               = 1,       
+                                       // # of memory clock enable outputs.
+   parameter CLK_WIDTH               = 2,       
+                                       // # of clock outputs.
+   parameter COL_WIDTH               = 10,       
+                                       // # of memory column bits.
+   parameter CS_NUM                  = 1,       
+                                       // # of separate memory chip selects.
+   parameter CS_WIDTH                = 1,       
+                                       // # of total memory chip selects.
+   parameter CS_BITS                 = 0,       
+                                       // set to log2(CS_NUM) (rounded up).
+   parameter DM_WIDTH                = 8,       
+                                       // # of data mask bits.
+   parameter DQ_WIDTH                = 64,       
+                                       // # of data width.
+   parameter DQ_PER_DQS              = 8,       
+                                       // # of DQ data bits per strobe.
+   parameter DQS_WIDTH               = 8,       
+                                       // # of DQS strobes.
+   parameter DQ_BITS                 = 6,       
+                                       // set to log2(DQS_WIDTH*DQ_PER_DQS).
+   parameter DQS_BITS                = 3,       
+                                       // set to log2(DQS_WIDTH).
+   parameter ODT_WIDTH               = 1,       
+                                       // # of memory on-die term enables.
+   parameter ROW_WIDTH               = 13,       
+                                       // # of memory row and # of addr bits.
+   parameter ADDITIVE_LAT            = 0,       
+                                       // additive write latency.
+   parameter BURST_LEN               = 4,       
+                                       // burst length (in double words).
+   parameter BURST_TYPE              = 0,       
+                                       // burst type (=0 seq; =1 interleaved).
+   parameter CAS_LAT                 = 3,       
+                                       // CAS latency.
+   parameter ECC_ENABLE              = 0,       
+                                       // enable ECC (=1 enable).
+   parameter APPDATA_WIDTH           = 128,       
+                                       // # of usr read/write data bus bits.
+   parameter MULTI_BANK_EN           = 1,       
+                                       // Keeps multiple banks open. (= 1 enable).
+   parameter TWO_T_TIME_EN           = 1,       
+                                       // 2t timing for unbuffered dimms.
+   parameter ODT_TYPE                = 1,       
+                                       // ODT (=0(none),=1(75),=2(150),=3(50)).
+   parameter REDUCE_DRV              = 0,       
+                                       // reduced strength mem I/O (=1 yes).
+   parameter REG_ENABLE              = 0,       
+                                       // registered addr/ctrl (=1 yes).
+   parameter TREFI_NS                = 7800,       
+                                       // auto refresh interval (ns).
+   parameter TRAS                    = 40000,       
+                                       // active->precharge delay.
+   parameter TRCD                    = 15000,       
+                                       // active->read/write delay.
+   parameter TRFC                    = 105000,       
+                                       // refresh->refresh, refresh->active delay.
+   parameter TRP                     = 15000,       
+                                       // precharge->command delay.
+   parameter TRTP                    = 7500,       
+                                       // read->precharge delay.
+   parameter TWR                     = 15000,       
+                                       // used to determine write->precharge.
+   parameter TWTR                    = 7500,       
+                                       // write->read delay.
+   parameter HIGH_PERFORMANCE_MODE   = "TRUE",       
+                              // # = TRUE, the IODELAY performance mode is set
+                              // to high.
+                              // # = FALSE, the IODELAY performance mode is set
+                              // to low.
+   parameter SIM_ONLY                = 0,       
+                                       // = 1 to skip SDRAM power up delay.
+   parameter DEBUG_EN                = 0,       
+                                       // Enable debug signals/controls.
+                                       // When this parameter is changed from 0 to 1,
+                                       // make sure to uncomment the coregen commands
+                                       // in ise_flow.bat or create_ise.bat files in
+                                       // par folder.
+   parameter CLK_PERIOD              = 5000,       
+                                       // Core/Memory clock period (in ps).
+   parameter DQS_IO_COL              = 16'b0000000000000000,       
+                                       // I/O column location of DQS groups
+                                       // (=0, left; =1 center, =2 right).
+   parameter DQ_IO_MS                = 64'b10100101_10100101_10100101_10100101_10100101_10100101_10100101_10100101,       
+                                       // Master/Slave location of DQ I/O (=0 slave).
+   parameter RST_ACT_LOW             = 1        
+                                       // =1 for active low reset, =0 for active high.
+   )
+  (
+   inout  [DQ_WIDTH-1:0]              ddr2_dq,
+   output [ROW_WIDTH-1:0]             ddr2_a,
+   output [BANK_WIDTH-1:0]            ddr2_ba,
+   output                             ddr2_ras_n,
+   output                             ddr2_cas_n,
+   output                             ddr2_we_n,
+   output [CS_WIDTH-1:0]              ddr2_cs_n,
+   output [ODT_WIDTH-1:0]             ddr2_odt,
+   output [CKE_WIDTH-1:0]             ddr2_cke,
+   output [DM_WIDTH-1:0]              ddr2_dm,
+   input                              sys_rst_n,
+   output                             phy_init_done,
+   input                              dcm_lock,
+   output                             rst0_tb,
+   input                              clk0,
+   output                             clk0_tb,
+   input                              clk90,
+   input                              clkdiv0,
+   input                              clk200,
+   output                             app_wdf_afull,
+   output                             app_af_afull,
+   output                             rd_data_valid,
+   input                              app_wdf_wren,
+   input                              app_af_wren,
+   input  [30:0]                      app_af_addr,
+   input  [2:0]                       app_af_cmd,
+   output [(APPDATA_WIDTH)-1:0]                rd_data_fifo_out,
+   input  [(APPDATA_WIDTH)-1:0]                app_wdf_data,
+   input  [(APPDATA_WIDTH/8)-1:0]              app_wdf_mask_data,
+   inout  [DQS_WIDTH-1:0]             ddr2_dqs,
+   inout  [DQS_WIDTH-1:0]             ddr2_dqs_n,
+   output [CLK_WIDTH-1:0]             ddr2_ck,
+   output [CLK_WIDTH-1:0]             ddr2_ck_n
+   );
+
+  /////////////////////////////////////////////////////////////////////////////
+  // The following parameter "IDELAYCTRL_NUM" indicates the number of
+  // IDELAYCTRLs that are LOCed for the design. The IDELAYCTRL LOCs are
+  // provided in the UCF file of par folder. MIG provides the parameter value
+  // and the LOCs in the UCF file based on the selected Data Read banks for
+  // the design. You must not alter this value unless it is needed. If you
+  // modify this value, you should make sure that the value of "IDELAYCTRL_NUM"
+  // and IDELAYCTRL LOCs in UCF file are same and are relavent to the Data Read
+  // banks used.
+  /////////////////////////////////////////////////////////////////////////////
+
+  localparam IDELAYCTRL_NUM = 3;
+
+
+
+
+
+  wire                              rst0;
+  wire                              rst90;
+  wire                              rstdiv0;
+  wire                              rst200;
+  wire                              idelay_ctrl_rdy;
+
+
+  //Debug signals
+
+
+  wire [3:0]                        dbg_calib_done;
+  wire [3:0]                        dbg_calib_err;
+  wire [(6*DQ_WIDTH)-1:0]           dbg_calib_dq_tap_cnt;
+  wire [(6*DQS_WIDTH)-1:0]          dbg_calib_dqs_tap_cnt;
+  wire [(6*DQS_WIDTH)-1:0]          dbg_calib_gate_tap_cnt;
+  wire [DQS_WIDTH-1:0]              dbg_calib_rd_data_sel;
+  wire [(5*DQS_WIDTH)-1:0]          dbg_calib_rden_dly;
+  wire [(5*DQS_WIDTH)-1:0]          dbg_calib_gate_dly;
+  wire                              dbg_idel_up_all;
+  wire                              dbg_idel_down_all;
+  wire                              dbg_idel_up_dq;
+  wire                              dbg_idel_down_dq;
+  wire                              dbg_idel_up_dqs;
+  wire                              dbg_idel_down_dqs;
+  wire                              dbg_idel_up_gate;
+  wire                              dbg_idel_down_gate;
+  wire [DQ_BITS-1:0]                dbg_sel_idel_dq;
+  wire                              dbg_sel_all_idel_dq;
+  wire [DQS_BITS:0]                 dbg_sel_idel_dqs;
+  wire                              dbg_sel_all_idel_dqs;
+  wire [DQS_BITS:0]                 dbg_sel_idel_gate;
+  wire                              dbg_sel_all_idel_gate;
+
+
+    // Debug signals (optional use)
+
+  //***********************************
+  // PHY Debug Port demo
+  //***********************************
+  wire [35:0]                        cs_control0;
+  wire [35:0]                        cs_control1;
+  wire [35:0]                        cs_control2;
+  wire [35:0]                        cs_control3;
+  wire [191:0]                       vio0_in;
+  wire [95:0]                        vio1_in;
+  wire [99:0]                        vio2_in;
+  wire [31:0]                        vio3_out;
+
+
+
+  //***************************************************************************
+
+  assign  rst0_tb = rst0;
+  assign  clk0_tb = clk0;
+
+
+   ddr2_idelay_ctrl #
+   (
+    .IDELAYCTRL_NUM         (IDELAYCTRL_NUM)
+   )
+   u_ddr2_idelay_ctrl
+   (
+   .rst200                 (rst200),
+   .clk200                 (clk200),
+   .idelay_ctrl_rdy        (idelay_ctrl_rdy)
+   );
+
+ ddr2_infrastructure #
+ (
+   .RST_ACT_LOW            (RST_ACT_LOW)
+   )
+u_ddr2_infrastructure
+ (
+   .sys_rst_n              (sys_rst_n),
+   .dcm_lock               (dcm_lock),
+   .rst0                   (rst0),
+   .rst90                  (rst90),
+   .rstdiv0                (rstdiv0),
+   .rst200                 (rst200),
+   .clk0                   (clk0),
+   .clk90                  (clk90),
+   .clkdiv0                (clkdiv0),
+   .clk200                 (clk200),
+   .idelay_ctrl_rdy        (idelay_ctrl_rdy)
+   );
+
+ ddr2_top #
+ (
+   .BANK_WIDTH             (BANK_WIDTH),
+   .CKE_WIDTH              (CKE_WIDTH),
+   .CLK_WIDTH              (CLK_WIDTH),
+   .COL_WIDTH              (COL_WIDTH),
+   .CS_NUM                 (CS_NUM),
+   .CS_WIDTH               (CS_WIDTH),
+   .CS_BITS                (CS_BITS),
+   .DM_WIDTH               (DM_WIDTH),
+   .DQ_WIDTH               (DQ_WIDTH),
+   .DQ_PER_DQS             (DQ_PER_DQS),
+   .DQS_WIDTH              (DQS_WIDTH),
+   .DQ_BITS                (DQ_BITS),
+   .DQS_BITS               (DQS_BITS),
+   .ODT_WIDTH              (ODT_WIDTH),
+   .ROW_WIDTH              (ROW_WIDTH),
+   .ADDITIVE_LAT           (ADDITIVE_LAT),
+   .BURST_LEN              (BURST_LEN),
+   .BURST_TYPE             (BURST_TYPE),
+   .CAS_LAT                (CAS_LAT),
+   .ECC_ENABLE             (ECC_ENABLE),
+   .APPDATA_WIDTH          (APPDATA_WIDTH),
+   .MULTI_BANK_EN          (MULTI_BANK_EN),
+   .TWO_T_TIME_EN          (TWO_T_TIME_EN),
+   .ODT_TYPE               (ODT_TYPE),
+   .REDUCE_DRV             (REDUCE_DRV),
+   .REG_ENABLE             (REG_ENABLE),
+   .TREFI_NS               (TREFI_NS),
+   .TRAS                   (TRAS),
+   .TRCD                   (TRCD),
+   .TRFC                   (TRFC),
+   .TRP                    (TRP),
+   .TRTP                   (TRTP),
+   .TWR                    (TWR),
+   .TWTR                   (TWTR),
+   .HIGH_PERFORMANCE_MODE  (HIGH_PERFORMANCE_MODE),
+   .SIM_ONLY               (SIM_ONLY),
+   .DEBUG_EN               (DEBUG_EN),
+   .CLK_PERIOD             (CLK_PERIOD),
+   .DQS_IO_COL             (DQS_IO_COL),
+   .DQ_IO_MS               (DQ_IO_MS),
+   .USE_DM_PORT            (1)
+   )
+u_ddr2_top_0
+(
+   .ddr2_dq                (ddr2_dq),
+   .ddr2_a                 (ddr2_a),
+   .ddr2_ba                (ddr2_ba),
+   .ddr2_ras_n             (ddr2_ras_n),
+   .ddr2_cas_n             (ddr2_cas_n),
+   .ddr2_we_n              (ddr2_we_n),
+   .ddr2_cs_n              (ddr2_cs_n),
+   .ddr2_odt               (ddr2_odt),
+   .ddr2_cke               (ddr2_cke),
+   .ddr2_dm                (ddr2_dm),
+   .phy_init_done          (phy_init_done),
+   .rst0                   (rst0),
+   .rst90                  (rst90),
+   .rstdiv0                (rstdiv0),
+   .clk0                   (clk0),
+   .clk90                  (clk90),
+   .clkdiv0                (clkdiv0),
+   .app_wdf_afull          (app_wdf_afull),
+   .app_af_afull           (app_af_afull),
+   .rd_data_valid          (rd_data_valid),
+   .app_wdf_wren           (app_wdf_wren),
+   .app_af_wren            (app_af_wren),
+   .app_af_addr            (app_af_addr),
+   .app_af_cmd             (app_af_cmd),
+   .rd_data_fifo_out       (rd_data_fifo_out),
+   .app_wdf_data           (app_wdf_data),
+   .app_wdf_mask_data      (app_wdf_mask_data),
+   .ddr2_dqs               (ddr2_dqs),
+   .ddr2_dqs_n             (ddr2_dqs_n),
+   .ddr2_ck                (ddr2_ck),
+   .rd_ecc_error           (),
+   .ddr2_ck_n              (ddr2_ck_n),
+
+   .dbg_calib_done         (dbg_calib_done),
+   .dbg_calib_err          (dbg_calib_err),
+   .dbg_calib_dq_tap_cnt   (dbg_calib_dq_tap_cnt),
+   .dbg_calib_dqs_tap_cnt  (dbg_calib_dqs_tap_cnt),
+   .dbg_calib_gate_tap_cnt  (dbg_calib_gate_tap_cnt),
+   .dbg_calib_rd_data_sel  (dbg_calib_rd_data_sel),
+   .dbg_calib_rden_dly     (dbg_calib_rden_dly),
+   .dbg_calib_gate_dly     (dbg_calib_gate_dly),
+   .dbg_idel_up_all        (dbg_idel_up_all),
+   .dbg_idel_down_all      (dbg_idel_down_all),
+   .dbg_idel_up_dq         (dbg_idel_up_dq),
+   .dbg_idel_down_dq       (dbg_idel_down_dq),
+   .dbg_idel_up_dqs        (dbg_idel_up_dqs),
+   .dbg_idel_down_dqs      (dbg_idel_down_dqs),
+   .dbg_idel_up_gate       (dbg_idel_up_gate),
+   .dbg_idel_down_gate     (dbg_idel_down_gate),
+   .dbg_sel_idel_dq        (dbg_sel_idel_dq),
+   .dbg_sel_all_idel_dq    (dbg_sel_all_idel_dq),
+   .dbg_sel_idel_dqs       (dbg_sel_idel_dqs),
+   .dbg_sel_all_idel_dqs   (dbg_sel_all_idel_dqs),
+   .dbg_sel_idel_gate      (dbg_sel_idel_gate),
+   .dbg_sel_all_idel_gate  (dbg_sel_all_idel_gate)
+   );
+
+   //*****************************************************************
+  // Hooks to prevent sim/syn compilation errors (mainly for VHDL - but
+  // keep it also in Verilog version of code) w/ floating inputs if
+  // DEBUG_EN = 0.
+  //*****************************************************************
+
+  generate
+    if (DEBUG_EN == 0) begin: gen_dbg_tie_off
+      assign dbg_idel_up_all       = 'b0;
+      assign dbg_idel_down_all     = 'b0;
+      assign dbg_idel_up_dq        = 'b0;
+      assign dbg_idel_down_dq      = 'b0;
+      assign dbg_idel_up_dqs       = 'b0;
+      assign dbg_idel_down_dqs     = 'b0;
+      assign dbg_idel_up_gate      = 'b0;
+      assign dbg_idel_down_gate    = 'b0;
+      assign dbg_sel_idel_dq       = 'b0;
+      assign dbg_sel_all_idel_dq   = 'b0;
+      assign dbg_sel_idel_dqs      = 'b0;
+      assign dbg_sel_all_idel_dqs  = 'b0;
+      assign dbg_sel_idel_gate     = 'b0;
+      assign dbg_sel_all_idel_gate = 'b0;
+    end else begin: gen_dbg_enable
+      
+      //*****************************************************************
+      // PHY Debug Port example - see MIG User's Guide, XAPP858 or 
+      // Answer Record 29443
+      // This logic supports up to 32 DQ and 8 DQS I/O
+      // NOTES:
+      //   1. PHY Debug Port demo connects to 4 VIO modules:
+      //     - 3 VIO modules with only asynchronous inputs
+      //      * Monitor IDELAY taps for DQ, DQS, DQS Gate
+      //      * Calibration status
+      //     - 1 VIO module with synchronous outputs
+      //      * Allow dynamic adjustment o f IDELAY taps
+      //   2. User may need to modify this code to incorporate other
+      //      chipscope-related modules in their larger design (e.g.
+      //      if they have other ILA/VIO modules, they will need to
+      //      for example instantiate a larger ICON module). In addition
+      //      user may want to instantiate more VIO modules to control
+      //      IDELAY for more DQ, DQS than is shown here
+      //*****************************************************************
+
+      icon4 u_icon
+        (
+         .control0 (cs_control0),
+         .control1 (cs_control1),
+         .control2 (cs_control2),
+         .control3 (cs_control3)
+         );
+
+      //*****************************************************************
+      // VIO ASYNC input: Display current IDELAY setting for up to 32
+      // DQ taps (32x6) = 192
+      //*****************************************************************
+
+      vio_async_in192 u_vio0
+        (
+         .control  (cs_control0),
+         .async_in (vio0_in)
+         );
+
+      //*****************************************************************
+      // VIO ASYNC input: Display current IDELAY setting for up to 8 DQS
+      // and DQS Gate taps (8x6x2) = 96
+      //*****************************************************************
+
+      vio_async_in96 u_vio1
+        (
+         .control  (cs_control1),
+         .async_in (vio1_in)
+         );
+
+      //*****************************************************************
+      // VIO ASYNC input: Display other calibration results
+      //*****************************************************************
+
+      vio_async_in100 u_vio2
+        (
+         .control  (cs_control2),
+         .async_in (vio2_in)
+         );
+      
+      //*****************************************************************
+      // VIO SYNC output: Dynamically change IDELAY taps
+      //*****************************************************************
+      
+      vio_sync_out32 u_vio3
+        (
+         .control  (cs_control3),
+         .clk      (clkdiv0),
+         .sync_out (vio3_out)
+         );
+
+      //*****************************************************************
+      // Bit assignments:
+      // NOTE: Not all VIO, ILA inputs/outputs may be used - these will
+      //       be dependent on the user's particular bit width
+      //*****************************************************************
+
+      if (DQ_WIDTH <= 32) begin: gen_dq_le_32
+        assign vio0_in[(6*DQ_WIDTH)-1:0] 
+                 = dbg_calib_dq_tap_cnt[(6*DQ_WIDTH)-1:0];
+      end else begin: gen_dq_gt_32
+        assign vio0_in = dbg_calib_dq_tap_cnt[191:0];
+      end
+
+      if (DQS_WIDTH <= 8) begin: gen_dqs_le_8
+        assign vio1_in[(6*DQS_WIDTH)-1:0]
+                 = dbg_calib_dqs_tap_cnt[(6*DQS_WIDTH)-1:0];
+        assign vio1_in[(12*DQS_WIDTH)-1:(6*DQS_WIDTH)] 
+                 =  dbg_calib_gate_tap_cnt[(6*DQS_WIDTH)-1:0];
+      end else begin: gen_dqs_gt_32
+        assign vio1_in[47:0]  = dbg_calib_dqs_tap_cnt[47:0];
+        assign vio1_in[95:48] = dbg_calib_gate_tap_cnt[47:0];
+      end
+//dbg_calib_rd_data_sel
+
+     if (DQS_WIDTH <= 8) begin: gen_rdsel_le_8
+        assign vio2_in[(DQS_WIDTH)+7:8]    
+                = dbg_calib_rd_data_sel[(DQS_WIDTH)-1:0];
+     end else begin: gen_rdsel_gt_32
+      assign vio2_in[15:8]    
+                 = dbg_calib_rd_data_sel[7:0];
+     end
+//dbg_calib_rden_dly
+
+     if (DQS_WIDTH <= 8) begin: gen_calrd_le_8
+       assign vio2_in[(5*DQS_WIDTH)+19:20]   
+                 = dbg_calib_rden_dly[(5*DQS_WIDTH)-1:0];
+     end else begin: gen_calrd_gt_32
+       assign vio2_in[59:20]   
+                 = dbg_calib_rden_dly[39:0];
+     end
+
+//dbg_calib_gate_dly
+
+     if (DQS_WIDTH <= 8) begin: gen_calgt_le_8
+       assign vio2_in[(5*DQS_WIDTH)+59:60]   
+                 = dbg_calib_gate_dly[(5*DQS_WIDTH)-1:0];
+     end else begin: gen_calgt_gt_32
+       assign vio2_in[99:60]   
+                 = dbg_calib_gate_dly[39:0];
+     end
+
+//dbg_sel_idel_dq
+
+     if (DQ_BITS <= 5) begin: gen_selid_le_5
+       assign dbg_sel_idel_dq[DQ_BITS-1:0]      
+                 = vio3_out[DQ_BITS+7:8];
+     end else begin: gen_selid_gt_32
+       assign dbg_sel_idel_dq[4:0]      
+                 = vio3_out[12:8];
+     end
+
+//dbg_sel_idel_dqs
+
+     if (DQS_BITS <= 3) begin: gen_seldqs_le_3
+       assign dbg_sel_idel_dqs[DQS_BITS:0]     
+                 = vio3_out[(DQS_BITS+16):16];
+     end else begin: gen_seldqs_gt_32
+       assign dbg_sel_idel_dqs[3:0]     
+                 = vio3_out[19:16];
+     end
+
+//dbg_sel_idel_gate
+
+     if (DQS_BITS <= 3) begin: gen_gtdqs_le_3
+       assign dbg_sel_idel_gate[DQS_BITS:0]    
+                 = vio3_out[(DQS_BITS+21):21];
+     end else begin: gen_gtdqs_gt_32
+       assign dbg_sel_idel_gate[3:0]    
+                 = vio3_out[24:21];
+     end
+
+
+      assign vio2_in[3:0]              = dbg_calib_done;
+      assign vio2_in[7:4]              = dbg_calib_err;
+      
+      assign dbg_idel_up_all           = vio3_out[0];
+      assign dbg_idel_down_all         = vio3_out[1];
+      assign dbg_idel_up_dq            = vio3_out[2];
+      assign dbg_idel_down_dq          = vio3_out[3];
+      assign dbg_idel_up_dqs           = vio3_out[4];
+      assign dbg_idel_down_dqs         = vio3_out[5];
+      assign dbg_idel_up_gate          = vio3_out[6];
+      assign dbg_idel_down_gate        = vio3_out[7];
+      assign dbg_sel_all_idel_dq       = vio3_out[15];
+      assign dbg_sel_all_idel_dqs      = vio3_out[20];
+      assign dbg_sel_all_idel_gate     = vio3_out[25];
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_top.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_top.v
new file mode 100644 (file)
index 0000000..000d06c
--- /dev/null
@@ -0,0 +1,277 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information
+// "as-is" solely for use in developing programs and
+// solutions for Xilinx devices, with no obligation on the
+// part of Xilinx to provide support. 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. 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 or fitness for a particular
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part
+// of this text at all times.
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_top.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/29 15:24:03 $
+// \   \  /  \    Date Created: Wed Aug 16 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   System level module. This level contains just the memory controller.
+//   This level will be intiantated when the user wants to remove the
+//   synthesizable test bench, IDELAY control block and the clock
+//   generation modules.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_top #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+   // board design). Actual values may be different. Actual parameters values
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH            = 2,      // # of memory bank addr bits
+   parameter CKE_WIDTH             = 1,      // # of memory clock enable outputs
+   parameter CLK_WIDTH             = 1,      // # of clock outputs
+   parameter COL_WIDTH             = 10,     // # of memory column bits
+   parameter CS_NUM                = 1,      // # of separate memory chip selects
+   parameter CS_BITS               = 0,      // set to log2(CS_NUM) (rounded up)
+   parameter CS_WIDTH              = 1,      // # of total memory chip selects
+   parameter USE_DM_PORT           = 1,      // enable Data Mask (=1 enable)
+   parameter DM_WIDTH              = 9,      // # of data mask bits
+   parameter DQ_WIDTH              = 72,     // # of data width
+   parameter DQ_BITS               = 7,      // set to log2(DQS_WIDTH*DQ_PER_DQS)
+   parameter DQ_PER_DQS            = 8,      // # of DQ data bits per strobe
+   parameter DQS_WIDTH             = 9,      // # of DQS strobes
+   parameter DQS_BITS              = 4,      // set to log2(DQS_WIDTH)
+   parameter HIGH_PERFORMANCE_MODE = "TRUE", // IODELAY Performance Mode
+   parameter ODT_WIDTH             = 1,      // # of memory on-die term enables
+   parameter ROW_WIDTH             = 14,     // # of memory row & # of addr bits
+   parameter APPDATA_WIDTH         = 144,    // # of usr read/write data bus bits
+   parameter ADDITIVE_LAT          = 0,      // additive write latency
+   parameter BURST_LEN             = 4,      // burst length (in double words)
+   parameter BURST_TYPE            = 0,      // burst type (=0 seq; =1 interlved)
+   parameter CAS_LAT               = 5,      // CAS latency
+   parameter ECC_ENABLE            = 0,      // enable ECC (=1 enable)
+   parameter ODT_TYPE              = 1,      // ODT (=0(none),=1(75),=2(150),=3(50))
+   parameter MULTI_BANK_EN         = 1,      // enable bank management
+   parameter TWO_T_TIME_EN         = 0,      // 2t timing for unbuffered dimms
+   parameter REDUCE_DRV            = 0,      // reduced strength mem I/O (=1 yes)
+   parameter REG_ENABLE            = 1,      // registered addr/ctrl (=1 yes)
+   parameter TREFI_NS              = 7800,   // auto refresh interval (ns)
+   parameter TRAS                  = 40000,  // active->precharge delay
+   parameter TRCD                  = 15000,  // active->read/write delay
+   parameter TRFC                  = 105000, // ref->ref, ref->active delay
+   parameter TRP                   = 15000,  // precharge->command delay
+   parameter TRTP                  = 7500,   // read->precharge delay
+   parameter TWR                   = 15000,  // used to determine wr->prech
+   parameter TWTR                  = 10000,  // write->read delay
+   parameter CLK_PERIOD            = 3000,   // Core/Mem clk period (in ps)
+   parameter SIM_ONLY              = 0,      // = 1 to skip power up delay
+   parameter DEBUG_EN              = 0,      // Enable debug signals/controls
+   parameter DQS_IO_COL            = 0,      // I/O column location of DQS groups
+   parameter DQ_IO_MS              = 0       // Master/Slave location of DQ I/O
+   )
+  (
+   input                                    clk0,
+   input                                    clk90,
+   input                                    clkdiv0,
+   input                                    rst0,
+   input                                    rst90,
+   input                                    rstdiv0,
+   input [2:0]                              app_af_cmd,
+   input [30:0]                             app_af_addr,
+   input                                    app_af_wren,
+   input                                    app_wdf_wren,
+   input [APPDATA_WIDTH-1:0]                app_wdf_data,
+   input [(APPDATA_WIDTH/8)-1:0]            app_wdf_mask_data,
+   output                                   app_af_afull,
+   output                                   app_wdf_afull,
+   output                                   rd_data_valid,
+   output [APPDATA_WIDTH-1:0]               rd_data_fifo_out,
+   output [1:0]                             rd_ecc_error,
+   output                                   phy_init_done,
+   output [CLK_WIDTH-1:0]                   ddr2_ck,
+   output [CLK_WIDTH-1:0]                   ddr2_ck_n,
+   output [ROW_WIDTH-1:0]                   ddr2_a,
+   output [BANK_WIDTH-1:0]                  ddr2_ba,
+   output                                   ddr2_ras_n,
+   output                                   ddr2_cas_n,
+   output                                   ddr2_we_n,
+   output [CS_WIDTH-1:0]                    ddr2_cs_n,
+   output [CKE_WIDTH-1:0]                   ddr2_cke,
+   output [ODT_WIDTH-1:0]                   ddr2_odt,
+   output [DM_WIDTH-1:0]                    ddr2_dm,
+   inout [DQS_WIDTH-1:0]                    ddr2_dqs,
+   inout [DQS_WIDTH-1:0]                    ddr2_dqs_n,
+   inout [DQ_WIDTH-1:0]                     ddr2_dq,
+   // Debug signals (optional use)
+   input                                    dbg_idel_up_all,
+   input                                    dbg_idel_down_all,
+   input                                    dbg_idel_up_dq,
+   input                                    dbg_idel_down_dq,
+   input                                    dbg_idel_up_dqs,
+   input                                    dbg_idel_down_dqs,
+   input                                    dbg_idel_up_gate,
+   input                                    dbg_idel_down_gate,
+   input [DQ_BITS-1:0]                      dbg_sel_idel_dq,
+   input                                    dbg_sel_all_idel_dq,
+   input [DQS_BITS:0]                       dbg_sel_idel_dqs,
+   input                                    dbg_sel_all_idel_dqs,
+   input [DQS_BITS:0]                       dbg_sel_idel_gate,
+   input                                    dbg_sel_all_idel_gate,
+   output [3:0]                             dbg_calib_done,
+   output [3:0]                             dbg_calib_err,
+   output [(6*DQ_WIDTH)-1:0]                dbg_calib_dq_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]               dbg_calib_dqs_tap_cnt,
+   output [(6*DQS_WIDTH)-1:0]               dbg_calib_gate_tap_cnt,
+   output [DQS_WIDTH-1:0]                   dbg_calib_rd_data_sel,
+   output [(5*DQS_WIDTH)-1:0]               dbg_calib_rden_dly,
+   output [(5*DQS_WIDTH)-1:0]               dbg_calib_gate_dly
+   );
+
+  // memory initialization/control logic
+  ddr2_mem_if_top #
+    (
+     .BANK_WIDTH            (BANK_WIDTH),
+     .CKE_WIDTH             (CKE_WIDTH),
+     .CLK_WIDTH             (CLK_WIDTH),
+     .COL_WIDTH             (COL_WIDTH),
+     .CS_BITS               (CS_BITS),
+     .CS_NUM                (CS_NUM),
+     .CS_WIDTH              (CS_WIDTH),
+     .USE_DM_PORT           (USE_DM_PORT),
+     .DM_WIDTH              (DM_WIDTH),
+     .DQ_WIDTH              (DQ_WIDTH),
+     .DQ_BITS               (DQ_BITS),
+     .DQ_PER_DQS            (DQ_PER_DQS),
+     .DQS_BITS              (DQS_BITS),
+     .DQS_WIDTH             (DQS_WIDTH),
+     .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+     .ODT_WIDTH             (ODT_WIDTH),
+     .ROW_WIDTH             (ROW_WIDTH),
+     .APPDATA_WIDTH         (APPDATA_WIDTH),
+     .ADDITIVE_LAT          (ADDITIVE_LAT),
+     .BURST_LEN             (BURST_LEN),
+     .BURST_TYPE            (BURST_TYPE),
+     .CAS_LAT               (CAS_LAT),
+     .ECC_ENABLE            (ECC_ENABLE),
+     .MULTI_BANK_EN         (MULTI_BANK_EN),
+     .TWO_T_TIME_EN         (TWO_T_TIME_EN),
+     .ODT_TYPE              (ODT_TYPE),
+     .DDR_TYPE              (1),
+     .REDUCE_DRV            (REDUCE_DRV),
+     .REG_ENABLE            (REG_ENABLE),
+     .TREFI_NS              (TREFI_NS),
+     .TRAS                  (TRAS),
+     .TRCD                  (TRCD),
+     .TRFC                  (TRFC),
+     .TRP                   (TRP),
+     .TRTP                  (TRTP),
+     .TWR                   (TWR),
+     .TWTR                  (TWTR),
+     .CLK_PERIOD            (CLK_PERIOD),
+     .SIM_ONLY              (SIM_ONLY),
+     .DEBUG_EN              (DEBUG_EN),
+     .DQS_IO_COL            (DQS_IO_COL),
+     .DQ_IO_MS              (DQ_IO_MS)
+     )
+    u_mem_if_top
+      (
+       .clk0                   (clk0),
+       .clk90                  (clk90),
+       .clkdiv0                (clkdiv0),
+       .rst0                   (rst0),
+       .rst90                  (rst90),
+       .rstdiv0                (rstdiv0),
+       .app_af_cmd             (app_af_cmd),
+       .app_af_addr            (app_af_addr),
+       .app_af_wren            (app_af_wren),
+       .app_wdf_wren           (app_wdf_wren),
+       .app_wdf_data           (app_wdf_data),
+       .app_wdf_mask_data      (app_wdf_mask_data),
+       .app_af_afull           (app_af_afull),
+       .app_wdf_afull          (app_wdf_afull),
+       .rd_data_valid          (rd_data_valid),
+       .rd_data_fifo_out       (rd_data_fifo_out),
+       .rd_ecc_error           (rd_ecc_error),
+       .phy_init_done          (phy_init_done),
+       .ddr_ck                 (ddr2_ck),
+       .ddr_ck_n               (ddr2_ck_n),
+       .ddr_addr               (ddr2_a),
+       .ddr_ba                 (ddr2_ba),
+       .ddr_ras_n              (ddr2_ras_n),
+       .ddr_cas_n              (ddr2_cas_n),
+       .ddr_we_n               (ddr2_we_n),
+       .ddr_cs_n               (ddr2_cs_n),
+       .ddr_cke                (ddr2_cke),
+       .ddr_odt                (ddr2_odt),
+       .ddr_dm                 (ddr2_dm),
+       .ddr_dqs                (ddr2_dqs),
+       .ddr_dqs_n              (ddr2_dqs_n),
+       .ddr_dq                 (ddr2_dq),
+       .dbg_idel_up_all        (dbg_idel_up_all),
+       .dbg_idel_down_all      (dbg_idel_down_all),
+       .dbg_idel_up_dq         (dbg_idel_up_dq),
+       .dbg_idel_down_dq       (dbg_idel_down_dq),
+       .dbg_idel_up_dqs        (dbg_idel_up_dqs),
+       .dbg_idel_down_dqs      (dbg_idel_down_dqs),
+       .dbg_idel_up_gate       (dbg_idel_up_gate),
+       .dbg_idel_down_gate     (dbg_idel_down_gate),
+       .dbg_sel_idel_dq        (dbg_sel_idel_dq),
+       .dbg_sel_all_idel_dq    (dbg_sel_all_idel_dq),
+       .dbg_sel_idel_dqs       (dbg_sel_idel_dqs),
+       .dbg_sel_all_idel_dqs   (dbg_sel_all_idel_dqs),
+       .dbg_sel_idel_gate      (dbg_sel_idel_gate),
+       .dbg_sel_all_idel_gate  (dbg_sel_all_idel_gate),
+       .dbg_calib_done         (dbg_calib_done),
+       .dbg_calib_err          (dbg_calib_err),
+       .dbg_calib_dq_tap_cnt   (dbg_calib_dq_tap_cnt),
+       .dbg_calib_dqs_tap_cnt  (dbg_calib_dqs_tap_cnt),
+       .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+       .dbg_calib_rd_data_sel  (dbg_calib_rd_data_sel),
+       .dbg_calib_rden_dly     (dbg_calib_rden_dly),
+       .dbg_calib_gate_dly     (dbg_calib_gate_dly)
+       );
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_addr_fifo.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_addr_fifo.v
new file mode 100644 (file)
index 0000000..18302a7
--- /dev/null
@@ -0,0 +1,135 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_usr_addr_fifo.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/08 15:20:47 $
+// \   \  /  \    Date Created: Mon Aug 28 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module instantiates the block RAM based FIFO to store the user
+//   address and the command information. Also calculates potential bank/row
+//   conflicts by comparing the new address with last address issued.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_addr_fifo #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH    = 2,
+   parameter COL_WIDTH     = 10,
+   parameter CS_BITS       = 0,
+   parameter ROW_WIDTH     = 14
+   )
+  (
+   input          clk0,
+   input          rst0,
+   input [2:0]    app_af_cmd,
+   input [30:0]   app_af_addr,
+   input          app_af_wren,
+   input          ctrl_af_rden,
+   output [2:0]   af_cmd,
+   output [30:0]  af_addr,
+   output         af_empty,
+   output         app_af_afull
+   );
+
+  wire [35:0]     fifo_data_out;
+   reg            rst_r;
+
+
+  always @(posedge clk0)
+     rst_r <= rst0;
+
+
+  //***************************************************************************
+
+  assign af_cmd      = fifo_data_out[33:31];
+  assign af_addr     = fifo_data_out[30:0];
+
+  //***************************************************************************
+
+  FIFO36 #
+    (
+     .ALMOST_EMPTY_OFFSET     (13'h0007),
+     .ALMOST_FULL_OFFSET      (13'h000F),
+     .DATA_WIDTH              (36),
+     .DO_REG                  (1),
+     .EN_SYN                  ("TRUE"),
+     .FIRST_WORD_FALL_THROUGH ("FALSE")
+     )
+    u_af
+      (
+       .ALMOSTEMPTY (),
+       .ALMOSTFULL  (app_af_afull),
+       .DO          (fifo_data_out[31:0]),
+       .DOP         (fifo_data_out[35:32]),
+       .EMPTY       (af_empty),
+       .FULL        (),
+       .RDCOUNT     (),
+       .RDERR       (),
+       .WRCOUNT     (),
+       .WRERR       (),
+       .DI          ({app_af_cmd[0],app_af_addr}),
+       .DIP         ({2'b00,app_af_cmd[2:1]}),
+       .RDCLK       (clk0),
+       .RDEN        (ctrl_af_rden),
+       .RST         (rst_r),
+       .WRCLK       (clk0),
+       .WREN        (app_af_wren)
+       );
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_rd.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_rd.v
new file mode 100644 (file)
index 0000000..8f20e0d
--- /dev/null
@@ -0,0 +1,301 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_usr_rd.v
+// /___/   /\     Date Last Modified: $Date: 2008/07/02 14:03:08 $
+// \   \  /  \    Date Created: Tue Aug 29 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   The delay between the read data with respect to the command issued is
+//   calculted in terms of no. of clocks. This data is then stored into the
+//   FIFOs and then read back and given as the ouput for comparison.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_rd #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter DQ_PER_DQS    = 8,
+   parameter DQS_WIDTH     = 9,
+   parameter APPDATA_WIDTH = 144,
+   parameter ECC_WIDTH     = 72,
+   parameter ECC_ENABLE    = 0
+   )
+  (
+   input                                    clk0,
+   input                                    rst0,
+   input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_rise,
+   input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_fall,
+   input [DQS_WIDTH-1:0]                    ctrl_rden,
+   input [DQS_WIDTH-1:0]                    ctrl_rden_sel,
+   output reg [1:0]                         rd_ecc_error,
+   output                                   rd_data_valid,
+   output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_rise,
+   output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_fall
+   );
+
+  // determine number of FIFO72's to use based on data width
+  localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
+
+  reg [DQS_WIDTH-1:0]               ctrl_rden_r;
+  wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
+  reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_fall_r;
+  reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_rise_r;
+  wire                              rden;
+  reg [DQS_WIDTH-1:0]               rden_sel_r
+                                    /* synthesis syn_preserve=1 */;
+  wire [DQS_WIDTH-1:0]              rden_sel_mux;
+  wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
+
+  // ECC specific signals
+  wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
+  reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  fall_data_r;
+  reg                               fifo_rden_r0;
+  reg                               fifo_rden_r1;
+  reg                               fifo_rden_r2;
+  reg                               fifo_rden_r3;
+  reg                               fifo_rden_r4;
+  reg                               fifo_rden_r5;
+  reg                               fifo_rden_r6;
+  wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_fall_temp;
+  wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_rise_temp;
+  reg                               rst_r;
+  reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rise_data_r;
+  wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
+
+
+  //***************************************************************************
+
+  always @(posedge clk0) begin
+    rden_sel_r        <= ctrl_rden_sel;
+    ctrl_rden_r       <= ctrl_rden;
+    rd_data_in_rise_r <= rd_data_in_rise;
+    rd_data_in_fall_r <= rd_data_in_fall;
+  end
+
+  // Instantiate primitive to allow this flop to be attached to multicycle
+  // path constraint in UCF. Multicycle path allowed for data from read FIFO.
+  // This is the same signal as RDEN_SEL_R, but is only used to select data
+  // (does not affect control signals)
+  genvar rd_i;
+  generate
+    for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
+      FDRSE u_ff_rden_sel_mux
+        (
+         .Q   (rden_sel_mux[rd_i]),
+         .C   (clk0),
+         .CE  (1'b1),
+         .D   (ctrl_rden_sel[rd_i]),
+         .R   (1'b0),
+         .S   (1'b0)
+         ) /* synthesis syn_preserve=1 */;
+    end
+  endgenerate
+
+  // determine correct read data valid signal timing
+  assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
+
+  // assign data based on the skew
+  genvar data_i;
+  generate
+    for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
+      assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+                       (data_i*DQ_PER_DQS)]
+               = (rden_sel_mux[data_i]) ?
+                 rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
+                                 (data_i*DQ_PER_DQS)] :
+                 rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+                                   (data_i*DQ_PER_DQS)];
+       assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+                        (data_i*DQ_PER_DQS)]
+                = (rden_sel_mux[data_i]) ?
+                  rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+                                  (data_i*DQ_PER_DQS)] :
+                  rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+                                    (data_i*DQ_PER_DQS)];
+    end
+  endgenerate
+
+  // Generate RST for FIFO reset AND for read/write enable:
+  // ECC FIFO always being read from and written to
+  always @(posedge clk0)
+    rst_r <= rst0;
+
+  genvar rdf_i;
+  generate
+    if (ECC_ENABLE) begin
+      always @(posedge clk0) begin
+        rd_ecc_error[0]   <= (|sb_ecc_error) & fifo_rden_r5;
+        rd_ecc_error[1]   <= (|db_ecc_error) & fifo_rden_r5;
+        rd_data_out_rise  <= rd_data_out_rise_temp;
+        rd_data_out_fall  <= rd_data_out_fall_temp;
+        rise_data_r       <= rise_data;
+        fall_data_r       <= fall_data;
+      end
+
+      // can use any of the read valids, they're all delayed by same amount
+      assign rd_data_valid = fifo_rden_r6;
+
+      // delay read valid to take into account max delay difference btw
+      // the read enable coming from the different DQS groups
+      always @(posedge clk0) begin
+        if (rst0) begin
+          fifo_rden_r0 <= 1'b0;
+          fifo_rden_r1 <= 1'b0;
+          fifo_rden_r2 <= 1'b0;
+          fifo_rden_r3 <= 1'b0;
+          fifo_rden_r4 <= 1'b0;
+          fifo_rden_r5 <= 1'b0;
+          fifo_rden_r6 <= 1'b0;
+        end else begin
+          fifo_rden_r0 <= rden;
+          fifo_rden_r1 <= fifo_rden_r0;
+          fifo_rden_r2 <= fifo_rden_r1;
+          fifo_rden_r3 <= fifo_rden_r2;
+          fifo_rden_r4 <= fifo_rden_r3;
+          fifo_rden_r5 <= fifo_rden_r4;
+          fifo_rden_r6 <= fifo_rden_r5;
+        end
+      end
+
+      for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
+
+        FIFO36_72  # // rise fifo
+          (
+           .ALMOST_EMPTY_OFFSET     (9'h007),
+           .ALMOST_FULL_OFFSET      (9'h00F),
+           .DO_REG                  (1),          // extra CC output delay
+           .EN_ECC_WRITE            ("FALSE"),
+           .EN_ECC_READ             ("TRUE"),
+           .EN_SYN                  ("FALSE"),
+           .FIRST_WORD_FALL_THROUGH ("FALSE")
+           )
+          u_rdf
+            (
+             .ALMOSTEMPTY (),
+             .ALMOSTFULL  (),
+             .DBITERR     (db_ecc_error[rdf_i + rdf_i]),
+             .DO          (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
+                                                 (64 *rdf_i)]),
+             .DOP         (),
+             .ECCPARITY   (),
+             .EMPTY       (),
+             .FULL        (),
+             .RDCOUNT     (),
+             .RDERR       (),
+             .SBITERR     (sb_ecc_error[rdf_i + rdf_i]),
+             .WRCOUNT     (),
+             .WRERR       (),
+             .DI          (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
+                                       (64 *rdf_i)+(rdf_i*8)]),
+             .DIP         (rise_data_r[(72*(rdf_i+1))-1:
+                                       (64*(rdf_i+1))+ (8*rdf_i)]),
+             .RDCLK       (clk0),
+             .RDEN        (~rst_r),
+             .RST         (rst_r),
+             .WRCLK       (clk0),
+             .WREN        (~rst_r)
+             );
+
+        FIFO36_72  # // fall_fifo
+          (
+           .ALMOST_EMPTY_OFFSET     (9'h007),
+           .ALMOST_FULL_OFFSET      (9'h00F),
+           .DO_REG                  (1),          // extra CC output delay
+           .EN_ECC_WRITE            ("FALSE"),
+           .EN_ECC_READ             ("TRUE"),
+           .EN_SYN                  ("FALSE"),
+           .FIRST_WORD_FALL_THROUGH ("FALSE")
+           )
+          u_rdf1
+            (
+             .ALMOSTEMPTY (),
+             .ALMOSTFULL  (),
+             .DBITERR     (db_ecc_error[(rdf_i+1) + rdf_i]),
+             .DO          (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
+                                                 (64 *rdf_i)]),
+             .DOP         (),
+             .ECCPARITY   (),
+             .EMPTY       (),
+             .FULL        (),
+             .RDCOUNT     (),
+             .RDERR       (),
+             .SBITERR     (sb_ecc_error[(rdf_i+1) + rdf_i]),
+             .WRCOUNT     (),
+             .WRERR       (),
+             .DI          (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
+                                       (64*rdf_i)+(rdf_i*8)]),
+             .DIP         (fall_data_r[(72*(rdf_i+1))-1:
+                                       (64*(rdf_i+1))+ (8*rdf_i)]),
+             .RDCLK       (clk0),
+             .RDEN        (~rst_r),
+             .RST         (rst_r),          // or can use rst0
+             .WRCLK       (clk0),
+             .WREN        (~rst_r)
+             );
+      end
+    end else begin
+      assign rd_data_valid = fifo_rden_r0;
+      always @(posedge clk0) begin
+        rd_data_out_rise <= rise_data;
+        rd_data_out_fall <= fall_data;
+        fifo_rden_r0 <= rden;
+      end
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_top.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_top.v
new file mode 100644 (file)
index 0000000..1c25ce1
--- /dev/null
@@ -0,0 +1,185 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_usr_top.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/08 15:20:47 $
+// \   \  /  \    Date Created: Mon Aug 28 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//   This module interfaces with the user. The user should provide the data
+//   and  various commands.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_top #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH     = 2,
+   parameter CS_BITS        = 0,
+   parameter COL_WIDTH      = 10,
+   parameter DQ_WIDTH       = 72,
+   parameter DQ_PER_DQS     = 8,
+   parameter APPDATA_WIDTH  = 144,
+   parameter ECC_ENABLE     = 0,
+   parameter DQS_WIDTH      = 9,
+   parameter ROW_WIDTH      = 14
+   )
+  (
+   input                                     clk0,
+   input                                     clk90,
+   input                                     rst0,
+   input [DQ_WIDTH-1:0]                      rd_data_in_rise,
+   input [DQ_WIDTH-1:0]                      rd_data_in_fall,
+   input [DQS_WIDTH-1:0]                     phy_calib_rden,
+   input [DQS_WIDTH-1:0]                     phy_calib_rden_sel,
+   output                                    rd_data_valid,
+   output [APPDATA_WIDTH-1:0]                rd_data_fifo_out,
+   input [2:0]                               app_af_cmd,
+   input [30:0]                              app_af_addr,
+   input                                     app_af_wren,
+   input                                     ctrl_af_rden,
+   output [2:0]                              af_cmd,
+   output [30:0]                             af_addr,
+   output                                    af_empty,
+   output                                    app_af_afull,
+   output [1:0]                              rd_ecc_error,
+   input                                     app_wdf_wren,
+   input [APPDATA_WIDTH-1:0]                 app_wdf_data,
+   input [(APPDATA_WIDTH/8)-1:0]             app_wdf_mask_data,
+   input                                     wdf_rden,
+   output                                    app_wdf_afull,
+   output [(2*DQ_WIDTH)-1:0]                 wdf_data,
+   output [((2*DQ_WIDTH)/8)-1:0]             wdf_mask_data
+   );
+
+  wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_fall;
+  wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_rise;
+
+  //***************************************************************************
+
+  assign rd_data_fifo_out = {i_rd_data_fifo_out_fall,
+                             i_rd_data_fifo_out_rise};
+
+  // read data de-skew and ECC calculation
+  ddr2_usr_rd #
+    (
+     .DQ_PER_DQS    (DQ_PER_DQS),
+     .ECC_ENABLE    (ECC_ENABLE),
+     .APPDATA_WIDTH (APPDATA_WIDTH),
+     .DQS_WIDTH     (DQS_WIDTH)
+     )
+     u_usr_rd
+      (
+       .clk0             (clk0),
+       .rst0             (rst0),
+       .rd_data_in_rise  (rd_data_in_rise),
+       .rd_data_in_fall  (rd_data_in_fall),
+       .rd_ecc_error     (rd_ecc_error),
+       .ctrl_rden        (phy_calib_rden),
+       .ctrl_rden_sel    (phy_calib_rden_sel),
+       .rd_data_valid    (rd_data_valid),
+       .rd_data_out_rise (i_rd_data_fifo_out_rise),
+       .rd_data_out_fall (i_rd_data_fifo_out_fall)
+       );
+
+  // Command/Addres FIFO
+  ddr2_usr_addr_fifo #
+    (
+     .BANK_WIDTH (BANK_WIDTH),
+     .COL_WIDTH  (COL_WIDTH),
+     .CS_BITS    (CS_BITS),
+     .ROW_WIDTH  (ROW_WIDTH)
+     )
+     u_usr_addr_fifo
+      (
+       .clk0         (clk0),
+       .rst0         (rst0),
+       .app_af_cmd   (app_af_cmd),
+       .app_af_addr  (app_af_addr),
+       .app_af_wren  (app_af_wren),
+       .ctrl_af_rden (ctrl_af_rden),
+       .af_cmd       (af_cmd),
+       .af_addr      (af_addr),
+       .af_empty     (af_empty),
+       .app_af_afull (app_af_afull)
+       );
+
+  ddr2_usr_wr #
+    (
+     .BANK_WIDTH    (BANK_WIDTH),
+     .COL_WIDTH     (COL_WIDTH),
+     .CS_BITS       (CS_BITS),
+     .DQ_WIDTH      (DQ_WIDTH),
+     .APPDATA_WIDTH (APPDATA_WIDTH),
+     .ECC_ENABLE    (ECC_ENABLE),
+     .ROW_WIDTH     (ROW_WIDTH)
+     )
+    u_usr_wr
+      (
+       .clk0              (clk0),
+       .clk90             (clk90),
+       .rst0              (rst0),
+       .app_wdf_wren      (app_wdf_wren),
+       .app_wdf_data      (app_wdf_data),
+       .app_wdf_mask_data (app_wdf_mask_data),
+       .wdf_rden          (wdf_rden),
+       .app_wdf_afull     (app_wdf_afull),
+       .wdf_data          (wdf_data),
+       .wdf_mask_data     (wdf_mask_data)
+       );
+
+endmodule
\ No newline at end of file
diff --git a/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_wr.v b/src/edu/berkeley/fleet/fpga/ddr2/ddr2_usr_wr.v
new file mode 100644 (file)
index 0000000..df2e260
--- /dev/null
@@ -0,0 +1,338 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+// 
+// This text/file contains proprietary, confidential
+// information of Xilinx, Inc., is distributed under license
+// from Xilinx, Inc., and may be used, copied and/or
+// disclosed only pursuant to the terms of a valid license
+// agreement with Xilinx, Inc. Xilinx hereby grants you a 
+// license to use this text/file 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 unless covered by
+// a separate agreement.
+//
+// Xilinx is providing this design, code, or information 
+// "as-is" solely for use in developing programs and 
+// solutions for Xilinx devices, with no obligation on the 
+// part of Xilinx to provide support. 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. 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 or fitness for a particular 
+// purpose.
+//
+// Xilinx products are not intended for use in life support
+// appliances, devices, or systems. Use in such applications is
+// expressly prohibited.
+//
+// Any modifications that are made to the Source Code are 
+// done at the users sole risk and will be unsupported.
+//
+// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
+//
+// This copyright and support notice must be retained as part 
+// of this text at all times. 
+//*****************************************************************************
+//   ____  ____
+//  /   /\/   /
+// /___/  \  /    Vendor: Xilinx
+// \   \   \/     Version: 2.3
+//  \   \         Application: MIG
+//  /   /         Filename: ddr2_usr_wr.v
+// /___/   /\     Date Last Modified: $Date: 2008/05/08 15:20:47 $
+// \   \  /  \    Date Created: Mon Aug 28 2006
+//  \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+//   This module instantiates the modules containing internal FIFOs
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_wr #
+  (
+   // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
+   // board design). Actual values may be different. Actual parameters values 
+   // are passed from design top module ddr2_sdram module. Please refer to
+   // the ddr2_sdram module for actual values.
+   parameter BANK_WIDTH    = 2,
+   parameter COL_WIDTH     = 10,
+   parameter CS_BITS       = 0,
+   parameter DQ_WIDTH      = 72,
+   parameter APPDATA_WIDTH = 144,
+   parameter ECC_ENABLE    = 0,
+   parameter ROW_WIDTH     = 14
+   )
+  (
+   input                         clk0,
+   input                         clk90,
+   input                         rst0,
+   // Write data FIFO interface
+   input                         app_wdf_wren,
+   input [APPDATA_WIDTH-1:0]     app_wdf_data,
+   input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+   input                         wdf_rden,
+   output                        app_wdf_afull,
+   output [(2*DQ_WIDTH)-1:0]     wdf_data,
+   output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
+   );
+
+  // determine number of FIFO72's to use based on data width
+  // round up to next integer value when determining WDF_FIFO_NUM
+  localparam WDF_FIFO_NUM = (ECC_ENABLE) ? (APPDATA_WIDTH+63)/64 :
+             ((2*DQ_WIDTH)+63)/64;
+  // MASK_WIDTH = number of bytes in data bus
+  localparam MASK_WIDTH = DQ_WIDTH/8;
+
+  wire [WDF_FIFO_NUM-1:0]      i_wdf_afull;
+  wire [DQ_WIDTH-1:0]          i_wdf_data_fall_in;
+  wire [DQ_WIDTH-1:0]          i_wdf_data_fall_out;
+  wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_in;
+  wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_out;
+  wire [DQ_WIDTH-1:0]          i_wdf_data_rise_in;
+  wire [DQ_WIDTH-1:0]          i_wdf_data_rise_out;
+  wire [MASK_WIDTH-1:0]        i_wdf_mask_data_fall_in;
+  wire [MASK_WIDTH-1:0]        i_wdf_mask_data_fall_out;
+  wire [(8*WDF_FIFO_NUM)-1:0]  i_wdf_mask_data_in;
+  wire [(8*WDF_FIFO_NUM)-1:0]  i_wdf_mask_data_out;
+  wire [MASK_WIDTH-1:0]        i_wdf_mask_data_rise_in;
+  wire [MASK_WIDTH-1:0]        i_wdf_mask_data_rise_out;
+  reg                          rst_r;
+
+  // ECC signals
+  wire [(2*DQ_WIDTH)-1:0]      i_wdf_data_out_ecc;
+  wire [((2*DQ_WIDTH)/8)-1:0]  i_wdf_mask_data_out_ecc;
+  wire [63:0]                  i_wdf_mask_data_out_ecc_wire;
+  wire [((2*DQ_WIDTH)/8)-1:0]  mask_data_in_ecc;
+  wire [63:0]                  mask_data_in_ecc_wire;
+
+  //***************************************************************************
+
+  assign app_wdf_afull = i_wdf_afull[0];
+
+  always @(posedge clk0 )
+      rst_r <= rst0;
+
+  genvar wdf_di_i;
+  genvar wdf_do_i;
+  genvar mask_i;
+  genvar wdf_i;
+  generate
+    if(ECC_ENABLE) begin    // ECC code
+
+      assign wdf_data = i_wdf_data_out_ecc;
+
+      // the byte 9 dm is always held to 0
+      assign wdf_mask_data = i_wdf_mask_data_out_ecc;
+
+
+
+      // generate for write data fifo .
+      for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
+
+        FIFO36_72  #
+          (
+           .ALMOST_EMPTY_OFFSET     (9'h007),
+           .ALMOST_FULL_OFFSET      (9'h00F),
+           .DO_REG                  (1),          // extra CC output delay
+           .EN_ECC_WRITE            ("TRUE"),
+           .EN_ECC_READ             ("FALSE"),
+           .EN_SYN                  ("FALSE"),
+           .FIRST_WORD_FALL_THROUGH ("FALSE")
+           )
+          u_wdf_ecc
+            (
+             .ALMOSTEMPTY (),
+             .ALMOSTFULL  (i_wdf_afull[wdf_i]),
+             .DBITERR     (),
+             .DO          (i_wdf_data_out_ecc[((64*(wdf_i+1))+(wdf_i *8))-1:
+                                              (64*wdf_i)+(wdf_i *8)]),
+             .DOP         (i_wdf_data_out_ecc[(72*(wdf_i+1))-1:
+                                              (64*(wdf_i+1))+ (8*wdf_i) ]),
+             .ECCPARITY   (),
+             .EMPTY       (),
+             .FULL        (),
+             .RDCOUNT     (),
+             .RDERR       (),
+             .SBITERR     (),
+             .WRCOUNT     (),
+             .WRERR       (),
+             .DI          (app_wdf_data[(64*(wdf_i+1))-1:
+                                        (64*wdf_i)]),
+             .DIP         (),
+             .RDCLK       (clk90),
+             .RDEN        (wdf_rden),
+             .RST         (rst_r),          // or can use rst0
+             .WRCLK       (clk0),
+             .WREN        (app_wdf_wren)
+             );
+      end
+
+      // remapping the mask data. The mask data from user i/f does not have
+      // the mask for the ECC byte. Assigning 0 to the ECC mask byte.
+      for (mask_i = 0; mask_i < (DQ_WIDTH)/36;
+           mask_i = mask_i +1) begin: gen_mask
+        assign mask_data_in_ecc[((8*(mask_i+1))+ mask_i)-1:((8*mask_i)+mask_i)]
+                 = app_wdf_mask_data[(8*(mask_i+1))-1:8*(mask_i)] ;
+        assign mask_data_in_ecc[((8*(mask_i+1))+mask_i)] = 1'd0;
+      end
+
+      // assign ecc bits to temp variables to avoid
+      // sim warnings. Not all the 64 bits of the fifo
+      // are used in ECC mode.
+       assign  mask_data_in_ecc_wire[((2*DQ_WIDTH)/8)-1:0] = mask_data_in_ecc;
+       assign  mask_data_in_ecc_wire[63:((2*DQ_WIDTH)/8)]  =
+              {(64-((2*DQ_WIDTH)/8)){1'b0}};
+       assign i_wdf_mask_data_out_ecc =
+               i_wdf_mask_data_out_ecc_wire[((2*DQ_WIDTH)/8)-1:0];
+
+
+      FIFO36_72  #
+        (
+         .ALMOST_EMPTY_OFFSET     (9'h007),
+         .ALMOST_FULL_OFFSET      (9'h00F),
+         .DO_REG                  (1),          // extra CC output delay
+         .EN_ECC_WRITE            ("TRUE"),
+         .EN_ECC_READ             ("FALSE"),
+         .EN_SYN                  ("FALSE"),
+         .FIRST_WORD_FALL_THROUGH ("FALSE")
+         )
+        u_wdf_ecc_mask
+          (
+           .ALMOSTEMPTY (),
+           .ALMOSTFULL  (),
+           .DBITERR     (),
+           .DO          (i_wdf_mask_data_out_ecc_wire),
+           .DOP         (),
+           .ECCPARITY   (),
+           .EMPTY       (),
+           .FULL        (),
+           .RDCOUNT     (),
+           .RDERR       (),
+           .SBITERR     (),
+           .WRCOUNT     (),
+           .WRERR       (),
+           .DI          (mask_data_in_ecc_wire),
+           .DIP         (),
+           .RDCLK       (clk90),
+           .RDEN        (wdf_rden),
+           .RST         (rst_r),          // or can use rst0
+           .WRCLK       (clk0),
+           .WREN        (app_wdf_wren)
+           );
+    end else begin
+
+      //***********************************************************************
+
+      // Define intermediate buses:
+      assign i_wdf_data_rise_in
+        = app_wdf_data[DQ_WIDTH-1:0];
+      assign i_wdf_data_fall_in
+        = app_wdf_data[(2*DQ_WIDTH)-1:DQ_WIDTH];
+      assign i_wdf_mask_data_rise_in
+        = app_wdf_mask_data[MASK_WIDTH-1:0];
+      assign i_wdf_mask_data_fall_in
+        = app_wdf_mask_data[(2*MASK_WIDTH)-1:MASK_WIDTH];
+
+      //***********************************************************************
+      // Write data FIFO Input:
+      // Arrange DQ's so that the rise data and fall data are interleaved.
+      // the data arrives at the input of the wdf fifo as {fall,rise}.
+      // It is remapped as:
+      //     {...fall[15:8],rise[15:8],fall[7:0],rise[7:0]}
+      // This is done to avoid having separate fifo's for rise and fall data
+      // and to keep rise/fall data for the same DQ's on same FIFO
+      // Data masks are interleaved in a similar manner
+      // NOTE: Initialization data from PHY_INIT module does not need to be
+      //  interleaved - it's already in the correct format - and the same
+      //  initialization pattern from PHY_INIT is sent to all write FIFOs
+      //***********************************************************************
+
+      for (wdf_di_i = 0; wdf_di_i < MASK_WIDTH;
+           wdf_di_i = wdf_di_i + 1) begin: gen_wdf_data_in
+        assign i_wdf_data_in[(16*wdf_di_i)+15:(16*wdf_di_i)]
+                 = {i_wdf_data_fall_in[(8*wdf_di_i)+7:(8*wdf_di_i)],
+                    i_wdf_data_rise_in[(8*wdf_di_i)+7:(8*wdf_di_i)]};
+        assign i_wdf_mask_data_in[(2*wdf_di_i)+1:(2*wdf_di_i)]
+                 = {i_wdf_mask_data_fall_in[wdf_di_i],
+                    i_wdf_mask_data_rise_in[wdf_di_i]};
+      end
+
+      //***********************************************************************
+      // Write data FIFO Output:
+      // FIFO DQ and mask outputs must be untangled and put in the standard
+      // format of {fall,rise}. Same goes for mask output
+      //***********************************************************************
+
+      for (wdf_do_i = 0; wdf_do_i < MASK_WIDTH;
+           wdf_do_i = wdf_do_i + 1) begin: gen_wdf_data_out
+        assign i_wdf_data_rise_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
+                 = i_wdf_data_out[(16*wdf_do_i)+7:(16*wdf_do_i)];
+        assign i_wdf_data_fall_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
+                 = i_wdf_data_out[(16*wdf_do_i)+15:(16*wdf_do_i)+8];
+        assign i_wdf_mask_data_rise_out[wdf_do_i]
+                 = i_wdf_mask_data_out[2*wdf_do_i];
+        assign i_wdf_mask_data_fall_out[wdf_do_i]
+                 = i_wdf_mask_data_out[(2*wdf_do_i)+1];
+      end
+
+      assign wdf_data = {i_wdf_data_fall_out,
+                         i_wdf_data_rise_out};
+
+      assign wdf_mask_data = {i_wdf_mask_data_fall_out,
+                              i_wdf_mask_data_rise_out};
+
+      //***********************************************************************
+
+      for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
+
+        FIFO36_72  #
+          (
+           .ALMOST_EMPTY_OFFSET     (9'h007),
+           .ALMOST_FULL_OFFSET      (9'h00F),
+           .DO_REG                  (1),          // extra CC output delay
+           .EN_ECC_WRITE            ("FALSE"),
+           .EN_ECC_READ             ("FALSE"),
+           .EN_SYN                  ("FALSE"),
+           .FIRST_WORD_FALL_THROUGH ("FALSE")
+           )
+          u_wdf
+            (
+             .ALMOSTEMPTY (),
+             .ALMOSTFULL  (i_wdf_afull[wdf_i]),
+             .DBITERR     (),
+             .DO          (i_wdf_data_out[(64*(wdf_i+1))-1:64*wdf_i]),
+             .DOP         (i_wdf_mask_data_out[(8*(wdf_i+1))-1:8*wdf_i]),
+             .ECCPARITY   (),
+             .EMPTY       (),
+             .FULL        (),
+             .RDCOUNT     (),
+             .RDERR       (),
+             .SBITERR     (),
+             .WRCOUNT     (),
+             .WRERR       (),
+             .DI          (i_wdf_data_in[(64*(wdf_i+1))-1:64*wdf_i]),
+             .DIP         (i_wdf_mask_data_in[(8*(wdf_i+1))-1:8*wdf_i]),
+             .RDCLK       (clk90),
+             .RDEN        (wdf_rden),
+             .RST         (rst_r),          // or can use rst0
+             .WRCLK       (clk0),
+             .WREN        (app_wdf_wren)
+             );
+      end
+    end
+  endgenerate
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/dvi/i2c_core.vhd b/src/edu/berkeley/fleet/fpga/dvi/i2c_core.vhd
new file mode 100644 (file)
index 0000000..b65bf86
--- /dev/null
@@ -0,0 +1,192 @@
+-- Module Name:  i2c_core.vhd
+-- File Description:  Generic i2c module with write capability only.
+-- Project:  FPGA Image Registration
+-- Target Device:  XC5VSX50T (Xilinx Virtex5 SXT)
+-- Target Board:  ML506
+-- Synthesis Tool:  Xilinx ISE 9.2
+-- Copyright (C) 2008 Brandyn Allen White
+-- Contact:  bwhite(at)cs.ucf.edu
+-- Project Website:  http://code.google.com/p/fpga-image-registration/
+
+-- 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 3 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, see <http://www.gnu.org/licenses/>.
+
+-- NOTE The data is in little endian byte ordering, data is sent lowest byte
+-- first, highest bit first (I2C convention).
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.STD_LOGIC_ARITH.ALL;
+USE IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+
+ENTITY i2c_core IS
+  PORT (clk           : IN  std_logic;
+        data          : IN  std_logic_vector (23 DOWNTO 0);
+        new_data      : IN  std_logic;
+        reset         : IN  std_logic;
+        i2c_sda       : OUT std_logic;
+        i2c_scl       : OUT std_logic;
+        received_data : OUT std_logic);
+END i2c_core;
+
+ARCHITECTURE Behavioral OF i2c_core IS
+  SIGNAL cur_data          : std_logic_vector (23 DOWNTO 0);  -- {device_id(7 downto 0), address(7 downto 0), data(7 downto 0)}
+  SIGNAL i2c_state         : std_logic_vector (2 DOWNTO 0) := (OTHERS => '0');  -- {START, DATA, POST_DATA, STOP, STOP_WAIT, X, X, X}
+  SIGNAL byte_position     : std_logic_vector(1 DOWNTO 0)  := (OTHERS => '0');  -- {device_id, address, data, X}
+  SIGNAL bit_position      : std_logic_vector(2 DOWNTO 0)  := (OTHERS => '0');
+  SIGNAL received_data_reg : std_logic                     := '0';
+  SIGNAL i2c_sda_reg       : std_logic                     := '1';
+
+-- I2C Clock Variables
+  SIGNAL i2c_clock_counter    : std_logic_vector (8 DOWNTO 0) := (OTHERS => '0');  -- [0,499]
+  SIGNAL i2c_edge_count       : std_logic_vector (2 DOWNTO 0) := (OTHERS => '0');  -- [0,4]
+  SIGNAL i2c_clock            : std_logic                     := '1';
+  SIGNAL i2c_clock_5x         : std_logic                     := '1';
+  SIGNAL i2c_clock_5x_posedge : std_logic                     := '1';
+
+BEGIN
+  i2c_scl       <= '0' WHEN i2c_clock = '0'   ELSE 'Z';  -- Output using {0,Z logic}
+  i2c_sda       <= '0' WHEN i2c_sda_reg = '0' ELSE 'Z';  -- Output using {0,Z logic}
+  received_data <= received_data_reg;
+
+  PROCESS(clk)
+  BEGIN
+    IF (clk'event AND clk = '1') THEN
+      -- Set initial register values upon synchronous reset
+      IF (reset = '1') THEN
+        i2c_state         <= (OTHERS => '0');
+        byte_position     <= (OTHERS => '0');
+        bit_position      <= (OTHERS => '0');
+        received_data_reg <= '0';
+        i2c_sda_reg       <= '1';
+
+        -- I2C Clock Variables
+        i2c_clock_counter    <= (OTHERS => '0');
+        i2c_edge_count       <= (OTHERS => '0');
+        i2c_clock            <= '1';
+        i2c_clock_5x         <= '1';
+        i2c_clock_5x_posedge <= '1';
+      ELSE
+        -- If we are supposed to start; however, no data is ready, then reset the clock logic to hold it high
+        IF (i2c_state = "000" AND new_data = '0') THEN
+          i2c_sda_reg       <= '1';
+          received_data_reg <= '0';
+
+                                        -- I2C Clock Variables
+          i2c_clock_counter    <= (OTHERS => '0');
+          i2c_edge_count       <= (OTHERS => '0');
+          i2c_clock            <= '1';
+          i2c_clock_5x         <= '1';
+          i2c_clock_5x_posedge <= '1';
+        ELSE
+                                        -- I2C Clock generation - Reduces clock rate by 100 for internal use and 500 for external use.
+          IF (i2c_clock_counter = 99 OR i2c_clock_counter = 199 OR i2c_clock_counter = 299 OR i2c_clock_counter = 399 OR i2c_clock_counter = 499) THEN
+            i2c_clock_5x <= NOT i2c_clock_5x;
+            IF (i2c_clock_5x = '0') THEN
+              i2c_clock_5x_posedge <= '1';
+              IF (i2c_edge_count < 4) THEN
+                i2c_edge_count <= i2c_edge_count + 1;
+              ELSE
+                i2c_edge_count <= (OTHERS => '0');
+              END IF;
+            END IF;
+          END IF;
+
+                                        -- Toggle the external I2C clock every 500 ticks
+          IF (i2c_clock_counter = 499) THEN
+            i2c_clock_counter <= (OTHERS => '0');
+            i2c_clock         <= NOT i2c_clock;
+          ELSE
+            i2c_clock_counter <= i2c_clock_counter + 1;
+          END IF;
+        END IF;
+
+        -- Main I2C Logic
+        IF (i2c_clock_5x_posedge = '1') THEN
+          i2c_clock_5x_posedge <= '0';
+          CASE i2c_edge_count IS  -- Edge selection -> individual state selection
+            WHEN "001" =>
+              IF (i2c_state = "011") THEN      -- STATE: stop
+                i2c_sda_reg <= '1';
+                i2c_state   <= "000";   -- 'start'
+              END IF;
+            WHEN "010" =>
+              IF (i2c_state = "000") THEN      -- STATE: start
+                IF (new_data = '1' AND received_data_reg = '0') THEN
+                  i2c_sda_reg       <= '0';
+                  cur_data          <= data;
+                  received_data_reg <= '1';
+                  i2c_state         <= "001";  -- 'data'
+                END IF;
+              END IF;
+
+            WHEN "100" =>
+              CASE i2c_state IS
+                WHEN "001" =>           -- STATE: data
+                  CASE bit_position IS  -- Select bit position and output it (NOTE:  MSB is output first!), TODO investigate other bit selection methods
+                    WHEN "000" =>
+                      i2c_sda_reg <= cur_data(7);
+                    WHEN "001" =>
+                      i2c_sda_reg <= cur_data(6);
+                    WHEN "010" =>
+                      i2c_sda_reg <= cur_data(5);
+                    WHEN "011" =>
+                      i2c_sda_reg <= cur_data(4);
+                    WHEN "100" =>
+                      i2c_sda_reg <= cur_data(3);
+                    WHEN "101" =>
+                      i2c_sda_reg <= cur_data(2);
+                    WHEN "110" =>
+                      i2c_sda_reg <= cur_data(1);
+                    WHEN "111" =>
+                      i2c_sda_reg <= cur_data(0);
+                    WHEN OTHERS =>
+                      NULL;
+                  END CASE;
+                      bit_position <= bit_position + 1;
+                      IF (bit_position = "111") THEN
+                        i2c_state <= "010";  -- 'post_data'
+                      ELSE
+                        i2c_state <= "001";  -- 'data'
+                      END IF;
+                WHEN "010" =>           -- STATE: post_data
+                  cur_data(15 DOWNTO 0) <= cur_data(23 DOWNTO 8);  -- Shift right by 8, TODO investigate other shifting methods
+                  i2c_sda_reg           <= '1';
+                  IF (byte_position = 2) THEN
+                    byte_position <= (OTHERS => '0');
+                    i2c_state     <= "100";
+                  ELSE
+                    byte_position <= byte_position + 1;
+                    i2c_state     <= "001";
+                  END IF;
+                WHEN "100" =>           -- STATE: stop_wait
+                  i2c_sda_reg <= '0';
+                  i2c_state   <= "011";      -- 'stop'
+                WHEN OTHERS =>
+                  NULL;
+              END CASE;
+            WHEN OTHERS =>
+              NULL;
+          END CASE;
+        END IF;
+
+        -- Data synchronization acknowledgement
+        IF (new_data = '0' AND received_data_reg = '1') THEN
+          received_data_reg <= '0';
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+END Behavioral;
+
diff --git a/src/edu/berkeley/fleet/fpga/dvi/i2c_video_programmer.vhd b/src/edu/berkeley/fleet/fpga/dvi/i2c_video_programmer.vhd
new file mode 100644 (file)
index 0000000..817daeb
--- /dev/null
@@ -0,0 +1,159 @@
+-- Module Name:  i2c_video_programmer
+-- File Description:  Uses the I2C module to program the CH7301C and AD9980.
+-- Project:  FPGA Image Registration
+-- Target Device:  XC5VSX50T (Xilinx Virtex5 SXT)
+-- Target Board:  ML506
+-- Synthesis Tool:  Xilinx ISE 9.2
+-- Copyright (C) 2008 Brandyn Allen White
+-- Contact:  bwhite(at)cs.ucf.edu
+-- Project Website:  http://code.google.com/p/fpga-image-registration/
+
+-- 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 3 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, see <http://www.gnu.org/licenses/>.
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE ieee.numeric_std.ALL;
+LIBRARY UNISIM;
+USE UNISIM.VComponents.ALL;
+
+ENTITY i2c_video_programmer IS
+  PORT (CLK200Mhz : IN  std_logic;
+        RST       : IN  std_logic;
+        I2C_SDA   : OUT std_logic;
+        I2C_SCL   : OUT std_logic);
+END i2c_video_programmer;
+
+ARCHITECTURE Behavioral OF i2c_video_programmer IS
+  COMPONENT i2c_core IS
+                       PORT (clk                : IN  std_logic;
+                             data               : IN  std_logic_vector (23 DOWNTO 0);
+                             new_data           : IN  std_logic;
+                             reset              : IN  std_logic;
+                             i2c_sda            : OUT std_logic;
+                             i2c_scl            : OUT std_logic;
+                             received_data      : OUT std_logic);
+  END COMPONENT;
+  COMPONENT vga_timing_decode IS
+                                PORT (PIXEL_CLK : IN  std_logic;
+                                      VSYNC     : IN  std_logic;
+                                      HSYNC     : IN  std_logic;
+                                      HCOUNT    : OUT std_logic_vector(9 DOWNTO 0);
+                                      VCOUNT    : OUT std_logic_vector(9 DOWNTO 0));
+  END COMPONENT;
+
+
+  SIGNAL received_data : std_logic;
+  SIGNAL new_data      : std_logic            := '0';
+  SIGNAL data_count    : unsigned(3 DOWNTO 0) := (OTHERS => '0');  -- Used to count the data
+  SIGNAL i2c_data      : std_logic_vector(23 DOWNTO 0);
+                                        -- bytes sent over I2C
+  SIGNAL i2c_clk       : std_logic;     -- 50Mhz i2c module input clock
+  SIGNAL i2c_dcm_fb    : std_logic;
+BEGIN
+  PROCESS (data_count) IS
+  BEGIN  -- PROCESS
+    CASE data_count IS
+      -- START VGA IN I2C Codes
+      WHEN "0000"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#320198#, 24));
+      WHEN "0001"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#000298#, 24));
+      WHEN "0010"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#600398#, 24));
+        -- END VGA IN I2C Codes
+        -- START DVI OUT I2C Codes
+      WHEN "0011"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#C049EC#, 24));
+      WHEN "0100"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#0921EC#, 24));
+      WHEN "0101"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#0833EC#, 24));
+      WHEN "0110"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#1634EC#, 24));
+      WHEN "0111"                                        =>
+        i2c_data <= std_logic_vector(to_unsigned(16#6036EC#, 24));
+        -- END DVI OUT I2C Codes
+      WHEN OTHERS                                        =>
+        i2c_data <= (OTHERS                              => '0');
+
+    END CASE;
+  END PROCESS;
+
+  -- DCM to divide input clock (200 mhz) by 16 to produce a 12.5 Mhz I2C Input
+  -- clock (which will be divided by 500 for the SCL clock and 100 for the
+  -- internal clock)
+  -- controller input
+  DCM_BASE_i2c : DCM_BASE
+    GENERIC MAP (
+      CLKDV_DIVIDE          => 8.0,    -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5  -- used to be 16
+      --   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
+      CLKFX_DIVIDE          => 16,      -- Can be any interger from 1 to 32 -- USED TO BE "32"!!!
+      CLKFX_MULTIPLY        => 2,       -- Can be any integer from 2 to 32 
+      CLKIN_DIVIDE_BY_2     => false,   -- TRUE/FALSE to enable CLKIN divide by two feature
+      CLKIN_PERIOD          => 10.0,     -- Specify period of input clock in ns from 1.25 to 1000.00
+      CLKOUT_PHASE_SHIFT    => "NONE",  -- Specify phase shift mode of NONE or FIXED
+      CLK_FEEDBACK          => "1X",    -- Specify clock feedback of NONE or 1X
+      DCM_AUTOCALIBRATION   => true,    -- DCM calibrartion circuitry TRUE/FALSE
+      DCM_PERFORMANCE_MODE  => "MAX_SPEED",  -- Can be MAX_SPEED or MAX_RANGE
+      DESKEW_ADJUST         => "SYSTEM_SYNCHRONOUS",  -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+                                        --   an integer from 0 to 15
+--     DFS_FREQUENCY_MODE    => "HIGH",  -- LOW or HIGH frequency mode for frequency synthesis
+      DLL_FREQUENCY_MODE    => "LOW",  -- LOW, HIGH, or HIGH_SER frequency mode for DLL
+      DUTY_CYCLE_CORRECTION => true,    -- Duty cycle correction, TRUE or FALSE
+      FACTORY_JF            => X"F0F0",  -- FACTORY JF Values Suggested to be set to X"F0F0" 
+      PHASE_SHIFT           => 0,       -- Amount of fixed phase shift from -255 to 1023
+      STARTUP_WAIT          => false)   -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
+    PORT MAP (
+      CLK0                  => i2c_dcm_fb,  -- 0 degree DCM CLK ouptput
+      CLKDV                 => i2c_clk,
+      CLKFB                 => i2c_dcm_fb,  -- DCM clock feedback
+      CLKIN                 => CLK200Mhz,  -- Clock input (from IBUFG, BUFG or DCM)
+      RST                   => '0'      -- DCM asynchronous reset input
+      );
+
+
+  -- purpose: This controls the data handshake with the I2C module, and manages the data to be sent
+  -- type   : sequential
+  -- inputs : CLK, RST, new_data
+  -- outputs: received_data
+  PROCESS (i2c_clk) IS
+  BEGIN  -- PROCESS
+    IF i2c_clk'event AND i2c_clk = '1' THEN  -- rising clock edge
+      IF new_data = '0' AND received_data = '0' THEN
+        new_data <= '1';
+      END IF;
+
+      IF new_data = '1' AND received_data = '1' THEN
+        new_data     <= '0';
+        IF data_count < 7 THEN          -- Prevents overflow
+          data_count <= data_count + 1;
+        ELSE
+          data_count <= (OTHERS => '0');
+        END IF;
+      END IF; END IF;
+    END PROCESS;
+
+      i2c_core_i : i2c_core
+        PORT MAP (
+          CLK           => i2c_clk,
+          data          => i2c_data,
+          new_data      => new_data,
+          reset         => '0',
+          i2c_sda       => I2C_SDA,
+          i2c_scl       => I2C_SCL,
+          received_data => received_data);
+
+
+    END Behavioral;
+
diff --git a/src/edu/berkeley/fleet/fpga/dvi/vga_timing_generator.vhd b/src/edu/berkeley/fleet/fpga/dvi/vga_timing_generator.vhd
new file mode 100644 (file)
index 0000000..d4fcb84
--- /dev/null
@@ -0,0 +1,154 @@
+-- Module Name:  vga_timing_generator.vhd
+-- File Description:  Generates VGA timing signals.
+-- Project:  FPGA Image Registration
+-- Target Device:  XC5VSX50T (Xilinx Virtex5 SXT)
+-- Target Board:  ML506
+-- Synthesis Tool:  Xilinx ISE 9.2
+-- Copyright (C) 2008 Brandyn Allen White
+-- Contact:  bwhite(at)cs.ucf.edu
+-- Project Website:  http://code.google.com/p/fpga-image-registration/
+
+-- 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 3 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, see <http://www.gnu.org/licenses/>.
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+
+ENTITY vga_timing_generator IS
+  GENERIC (WIDTH       : integer := 1024;
+           H_FP        : integer := 24;
+           H_SYNC      : integer := 136;
+           H_BP        : integer := 160;
+           HEIGHT      : integer := 768;
+           V_FP        : integer := 3;
+           V_SYNC      : integer := 6;
+           V_BP        : integer := 29;
+           HEIGHT_BITS : integer := 10;
+           WIDTH_BITS  : integer := 10;
+           HCOUNT_BITS : integer := 11;
+           VCOUNT_BITS : integer := 11;
+           DATA_DELAY  : integer := 0
+
+
+           );
+  PORT (CLK            : IN  std_logic;
+        RST            : IN  std_logic;
+        HSYNC          : OUT std_logic;
+        VSYNC          : OUT std_logic;
+        X_COORD        : OUT std_logic_vector(WIDTH_BITS-1 DOWNTO 0);
+        Y_COORD        : OUT std_logic_vector(HEIGHT_BITS-1 DOWNTO 0);
+        PIXEL_COUNT    : OUT std_logic_vector(WIDTH_BITS+HEIGHT_BITS-1 DOWNTO 0);
+        DATA_VALID     : OUT std_logic;
+        DATA_VALID_EXT : OUT std_logic);
+END vga_timing_generator;
+
+ARCHITECTURE Behavioral OF vga_timing_generator IS
+  CONSTANT H_TOTAL                  : integer                                     := WIDTH+H_FP+H_SYNC+H_BP;
+  CONSTANT V_TOTAL                  : integer                                     := HEIGHT+V_FP+V_SYNC+V_BP;
+  -- bit more than specified to cover the H_FP
+  SIGNAL   hcount                   : unsigned(HCOUNT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
+  SIGNAL   vcount                   : unsigned(VCOUNT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
+  SIGNAL   vsync_reg, hsync_reg     : std_logic                                   := '0';  -- NOTE These are active high signals
+  SIGNAL   pixel_count_reg          : unsigned(WIDTH_BITS+HEIGHT_BITS-1 DOWNTO 0) := (OTHERS => '0');  -- This is used to keep track of the number of valid pixels that have been output this frame.  Used to allow pixel selection to be made based on 1D memory addresses.
+  SIGNAL   x_coord_reg              : unsigned(WIDTH_BITS-1 DOWNTO 0)             := (OTHERS => '0');
+  SIGNAL   y_coord_reg              : unsigned(HEIGHT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
+  SIGNAL   data_valid_reg           : std_logic                                   := '0';
+BEGIN
+  HSYNC       <= hsync_reg;
+  VSYNC       <= vsync_reg;
+  X_COORD     <= std_logic_vector(x_coord_reg);
+  Y_COORD     <= std_logic_vector(y_coord_reg);
+  PIXEL_COUNT <= std_logic_vector(pixel_count_reg);
+  DATA_VALID  <= data_valid_reg;
+  PROCESS(CLK)
+  BEGIN
+    -----------------------------------------------------------------------
+    -- Zones w.r.t. hcount
+    -- 0<=X<H_BP-1                        -  Back Porch of H
+    -- H_BP-1=<X<H_BP+WIDTH-1             -  Active horizontal data
+    -- H_BP+WIDTH-1<=X<WIDTH+H_FP+H_BP-1  -  Front Porch/HSYNC
+    -- WIDTH+H_FP+H_BP-1<=X<H_TOTAL-1     -  HSYNC
+
+    -- Horizontal Pixel Count
+    IF (CLK'event AND CLK = '1') THEN
+      IF (RST = '1') THEN
+        vcount          <= (OTHERS => '0');
+        hcount          <= (OTHERS => '0');
+        hsync_reg       <= '0';
+        vsync_reg       <= '0';
+        pixel_count_reg <= (OTHERS => '0');
+        x_coord_reg     <= (OTHERS => '0');
+        y_coord_reg     <= (OTHERS => '0');
+      ELSE
+        -- Data valid signal - This is corrected for the data delay by doing
+        -- everything early by DATA_DELAY CTs.
+        IF (H_BP-DATA_DELAY-1 <= hcount AND hcount < WIDTH+H_BP-DATA_DELAY-1 AND V_BP <= vcount AND vcount < HEIGHT+V_BP) THEN
+          data_valid_reg <= '1';
+          IF data_valid_reg = '1' THEN
+            x_coord_reg <= x_coord_reg + 1;
+          END IF;
+          IF (data_valid_reg = '1' AND vcount = V_BP) OR vcount > V_BP THEN
+            pixel_count_reg <= pixel_count_reg + 1;
+          END IF;
+        ELSE
+          x_coord_reg    <= (OTHERS => '0');
+          data_valid_reg <= '0';
+        END IF;
+
+        -- Data valid external signal (to be in line with HSYNC/VSYNC)
+        IF (H_BP-1 <= hcount AND hcount < WIDTH+H_BP-1 AND V_BP <= vcount AND vcount < HEIGHT+V_BP) THEN
+          DATA_VALID_EXT <= '1';
+        ELSE
+          DATA_VALID_EXT <= '0';
+        END IF;
+
+        -- Horizontal Line Counter
+        IF hcount = (H_TOTAL-1) THEN    -- Reset hcount
+          hcount <= (OTHERS => '0');
+        ELSE
+          hcount <= hcount + 1;
+        END IF;
+
+        -- Vertical Line Counter
+        IF hcount = (H_TOTAL - 1) AND (vcount = (V_TOTAL - 1)) THEN  -- Reset
+                                                                     -- vcount
+          vcount          <= (OTHERS => '0');
+          pixel_count_reg <= (OTHERS => '0');
+          y_coord_reg     <= (OTHERS => '0');
+        ELSIF hcount = (H_TOTAL - 1) THEN
+          vcount  <= vcount + 1;
+          IF V_BP <= vcount AND vcount < HEIGHT+V_BP-1 THEN
+            y_coord_reg <= y_coord_reg + 1;
+          END IF;
+        END IF;
+
+        -- Horizontal Sync Pulse
+        IF hcount = (WIDTH+H_FP+H_BP-1) THEN
+          hsync_reg <= '1';
+        ELSIF hcount = (H_TOTAL-1) THEN
+          hsync_reg <= '0';
+        END IF;
+
+        -- Vertical Sync Pulse
+        IF hcount = (H_TOTAL-1) AND vcount = (HEIGHT+V_FP+V_BP-1) THEN
+          vsync_reg <= '1';
+        ELSIF hcount = (H_TOTAL-1) AND vcount = (V_TOTAL-1) THEN
+          vsync_reg <= '0';
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+END Behavioral;
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/async_fifo.v b/src/edu/berkeley/fleet/fpga/mem/async_fifo.v
new file mode 100644 (file)
index 0000000..885dfbe
--- /dev/null
@@ -0,0 +1,116 @@
+//==========================================
+// Function : Asynchronous FIFO (w/ 2 asynchronous clocks).
+// Coder    : Alex Claros F.
+// Date     : 15/May/2005.
+// Notes    : This implementation is based on the article 
+//            'Asynchronous FIFO in Virtex-II FPGAs'
+//            writen by Peter Alfke. This TechXclusive 
+//            article can be downloaded from the
+//            Xilinx website. It has some minor modifications.
+//=========================================
+
+`timescale 1ns / 1ps
+
+module async_fifo
+  #(parameter    DATA_WIDTH    = 8,
+                 ADDRESS_WIDTH = 4,
+                 FIFO_DEPTH    = (1 << ADDRESS_WIDTH))
+     //Reading port
+    (output wire [DATA_WIDTH-1:0]        Data_out, 
+     output reg                          Empty_out,
+     input wire                          ReadEn_in,
+     input wire                          RClk,        
+     //Writing port.    
+     input wire  [DATA_WIDTH-1:0]        Data_in,  
+     output reg                          Full_out,
+     input wire                          WriteEn_in,
+     input wire                          WClk,
+        
+     input wire                          Clear_in);
+
+    /////Internal connections & variables//////
+    reg   [DATA_WIDTH-1:0]              Mem [FIFO_DEPTH-1:0];
+    wire  [ADDRESS_WIDTH-1:0]           pNextWordToWrite, pNextWordToRead;
+    wire                                EqualAddresses;
+    wire                                NextWriteAddressEn, NextReadAddressEn;
+    wire                                Set_Status, Rst_Status;
+    reg                                 Status;
+    wire                                PresetFull, PresetEmpty;
+    
+    //////////////Code///////////////
+    //Data ports logic:
+    //(Uses a dual-port RAM).
+    //'Data_out' logic:
+    assign  Data_out = Mem[pNextWordToRead];
+//    always @ (posedge RClk)
+//        if (!PresetEmpty)
+//            Data_out <= Mem[pNextWordToRead];
+//        if (ReadEn_in & !Empty_out)
+            
+    //'Data_in' logic:
+    always @ (posedge WClk)
+        if (WriteEn_in & !Full_out)
+            Mem[pNextWordToWrite] <= Data_in;
+
+    //Fifo addresses support logic: 
+    //'Next Addresses' enable logic:
+    assign NextWriteAddressEn = WriteEn_in & ~Full_out;
+    assign NextReadAddressEn  = ReadEn_in  & ~Empty_out;
+           
+    //Addreses (Gray counters) logic:
+    GrayCounter #(
+               .COUNTER_WIDTH( ADDRESS_WIDTH )
+    ) GrayCounter_pWr (
+        .GrayCount_out(pNextWordToWrite),
+        .Enable_in(NextWriteAddressEn),
+        .Clear_in(Clear_in),
+        
+        .Clk(WClk)
+       );
+       
+    GrayCounter #(
+               .COUNTER_WIDTH( ADDRESS_WIDTH )
+    ) GrayCounter_pRd (
+        .GrayCount_out(pNextWordToRead),
+        .Enable_in(NextReadAddressEn),
+        .Clear_in(Clear_in),
+        .Clk(RClk)
+       );
+     
+
+    //'EqualAddresses' logic:
+    assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
+
+    //'Quadrant selectors' logic:
+    assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) &
+                         (pNextWordToWrite[ADDRESS_WIDTH-1] ^  pNextWordToRead[ADDRESS_WIDTH-2]);
+                            
+    assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^  pNextWordToRead[ADDRESS_WIDTH-1]) &
+                         (pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]);
+                         
+    //'Status' latch logic:
+    always @ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset.
+        if (Rst_Status | Clear_in)
+            Status = 0;  //Going 'Empty'.
+        else if (Set_Status)
+            Status = 1;  //Going 'Full'.
+            
+    //'Full_out' logic for the writing port:
+    assign PresetFull = Status & EqualAddresses;  //'Full' Fifo.
+    
+    always @ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset.
+        if (PresetFull)
+            Full_out <= 1;
+        else
+            Full_out <= 0;
+            
+    //'Empty_out' logic for the reading port:
+    assign PresetEmpty = ~Status & EqualAddresses;  //'Empty' Fifo.
+    
+    always @ (posedge RClk, posedge PresetEmpty)  //D Flip-Flop w/ Asynchronous Preset.
+        if (PresetEmpty)
+            Empty_out <= 1;
+        else
+            Empty_out <= 0;
+            
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_clkgen.v b/src/edu/berkeley/fleet/fpga/mem/ddr_clkgen.v
new file mode 100644 (file)
index 0000000..3827a74
--- /dev/null
@@ -0,0 +1,181 @@
+//---------------------------------------------------------------------------
+// Wishbone DDR Controller
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//---------------------------------------------------------------------------
+
+`timescale 1ns / 1ps
+`include "ddr_include.v"
+
+module ddr_clkgen
+#(
+       parameter phase_shift  = 0,
+       parameter clk_multiply = 13,
+       parameter clk_divide   = 5
+) (
+       input        clk,
+       input        reset,
+       output       locked,
+       //
+       output       read_clk,
+       output       write_clk,
+       output       write_clk90,
+       // 
+       input  [2:0] rot
+);
+
+
+//----------------------------------------------------------------------------
+// rotary decoder
+//----------------------------------------------------------------------------
+rotary rotdec0 (
+       .clk(       clk        ),
+       .reset(     reset      ),
+       .rot(       rot        ),
+       // output
+       .rot_btn(   rot_btn    ),
+       .rot_event( rot_event  ),
+       .rot_left(  rot_left   )
+);
+
+//----------------------------------------------------------------------------
+// ~133 MHz DDR Clock generator
+//----------------------------------------------------------------------------
+wire  read_clk_u;
+wire  dcm_fx_locked;
+
+DCM #(
+       .CLKDV_DIVIDE(2.0),          // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
+                                 //   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
+       .CLKFX_DIVIDE(clk_divide),   // Can be any integer from 1 to 32
+       .CLKFX_MULTIPLY(clk_multiply), // Can be any integer from 2 to 32
+       .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
+       .CLKIN_PERIOD(),             // Specify period of input clock
+       .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
+       .CLK_FEEDBACK("NONE"),       // Specify clock feedback of NONE, 1X or 2X
+       .DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+                                 //   an integer from 0 to 15
+       .DFS_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for frequency synthesis
+       .DLL_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for DLL
+       .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
+       .FACTORY_JF(16'hC080),       // FACTORY JF values
+       .PHASE_SHIFT(0),             // Amount of fixed phase shift from -255 to 255
+       .STARTUP_WAIT("FALSE")       // Delay configuration DONE until DCM LOCK, TRUE/FALSE
+) dcm_fx (
+       .DSSEN(),
+       .CLK0(),                   // 0 degree DCM CLK output
+       .CLK180(),                 // 180 degree DCM CLK output
+       .CLK270(),                 // 270 degree DCM CLK output
+       .CLK2X(),                  // 2X DCM CLK output
+       .CLK2X180(),               // 2X, 180 degree DCM CLK out
+       .CLK90(),                  // 90 degree DCM CLK output
+       .CLKDV(),                  // Divided DCM CLK out (CLKDV_DIVIDE)
+       .CLKFX(    read_clk_u ),   // DCM CLK synthesis out (M/D)
+       .CLKFX180(),               // 180 degree CLK synthesis out
+       .LOCKED(   dcm_fx_locked), // DCM LOCK status output
+       .PSDONE(),                 // Dynamic phase adjust done output
+       .STATUS(),                 // 8-bit DCM status bits output
+       .CLKFB(),                  // DCM clock feedback
+       .CLKIN(    clk   ),        // Clock input (from IBUFG, BUFG or DCM)
+       .PSCLK(    gnd   ),        // Dynamic phase adjust clock input
+       .PSEN(     gnd   ),        // Dynamic phase adjust enable input
+       .PSINCDEC( gnd   ),        // Dynamic phase adjust increment/decrement
+       .RST(      reset )         // DCM asynchronous reset input
+);
+
+//----------------------------------------------------------------------------
+// BUFG read clock
+//----------------------------------------------------------------------------
+BUFG bufg_fx_clk (
+       .O(read_clk),             // Clock buffer output
+       .I(read_clk_u)            // Clock buffer input
+);
+
+//----------------------------------------------------------------------------
+// Phase shifted clock for write path 
+//----------------------------------------------------------------------------
+wire  phase_dcm_reset;
+wire  phase_dcm_locked;
+wire  write_clk_u, write_clk90_u, write_clk180_u, write_clk270_u;
+
+DCM #(
+       .CLKDV_DIVIDE(2.0),     // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
+                            //   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
+       .CLKFX_DIVIDE(2),       // Can be any integer from 1 to 32
+       .CLKFX_MULTIPLY(2),     // Can be any integer from 2 to 32
+       .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
+       .CLKIN_PERIOD(),        // Specify period of input clock
+       .CLK_FEEDBACK("1X"),    // Specify clock feedback of NONE, 1X or 2X
+       .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+                                          //   an integer from 0 to 15
+       .DFS_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for frequency synthesis
+       .DLL_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for DLL
+       .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
+       .FACTORY_JF(16'hC080),   // FACTORY JF values
+       .CLKOUT_PHASE_SHIFT("VARIABLE"), // Specify phase shift of NONE, FIXED or VARIABLE
+       .PHASE_SHIFT( phase_shift ), // Amount of fixed phase shift from -255 to 255
+       .STARTUP_WAIT("FALSE")   // Delay configuration DONE until DCM LOCK, TRUE/FALSE
+) dcm_phase (
+       .DSSEN(),
+       .CLK0(   write_clk_u ),      // 0 degree DCM CLK output
+       .CLK90(  write_clk90_u ),    // 90 degree DCM CLK output
+       .CLK180( write_clk180_u ),   // 180 degree DCM CLK output
+       .CLK270( write_clk270_u ),   // 270 degree DCM CLK output
+       .CLK2X(),                    // 2X DCM CLK output
+       .CLK2X180(),                 // 2X, 180 degree DCM CLK out
+       .CLKDV(),                    // Divided DCM CLK out (CLKDV_DIVIDE)
+       .CLKFX(),                    // DCM CLK synthesis out (M/D)
+       .CLKFX180(),                 // 180 degree CLK synthesis out
+       .LOCKED( phase_dcm_locked ), // DCM LOCK status output
+       .PSDONE(),                   // Dynamic phase adjust done output
+       .STATUS(),                   // 8-bit DCM status bits output
+       .CLKFB( write_clk ),         // DCM clock feedback
+       .CLKIN( read_clk ),          // Clock input (from IBUFG, BUFG or DCM)
+       .PSCLK( clk ),               // Dynamic phase adjust clock input
+       .PSEN( rot_event ),          // Dynamic phase adjust enable input
+       .PSINCDEC( rot_left ),       // Dynamic phase adjust increment/decrement
+       .RST( phase_dcm_reset )      // DCM asynchronous reset input
+);
+
+reg [3:0] reset_counter;
+assign phase_dcm_reset = reset | (reset_counter != 0);
+
+always @(posedge clk)
+begin
+       if (reset) 
+               reset_counter <= 1;
+       else begin
+               if (dcm_fx_locked & (reset_counter != 0))
+                       reset_counter <= reset_counter + 1;
+       end
+end
+
+
+//----------------------------------------------------------------------------
+// BUFG write clock
+//----------------------------------------------------------------------------
+
+BUFG bufg_write_clk (
+       .O(write_clk  ),          // Clock buffer output
+       .I(write_clk_u)           // Clock buffer input
+);
+
+BUFG bufg_write_clk90 (
+       .O(write_clk90  ),        // Clock buffer output
+       .I(write_clk90_u)         // Clock buffer input
+);
+
+//----------------------------------------------------------------------------
+// LOCKED logic
+//----------------------------------------------------------------------------
+reg phase_dcm_locked_delayed;
+
+always @(posedge write_clk)
+begin
+       phase_dcm_locked_delayed <= phase_dcm_locked;
+end
+
+assign locked = ~reset & phase_dcm_locked_delayed;
+
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_ctrl.v b/src/edu/berkeley/fleet/fpga/mem/ddr_ctrl.v
new file mode 100644 (file)
index 0000000..45218bd
--- /dev/null
@@ -0,0 +1,477 @@
+//----------------------------------------------------------------------------
+// Pipelined, asyncronous DDR Controller
+//
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//----------------------------------------------------------------------------
+module ddr_ctrl 
+#(
+       parameter clk_freq     = 50000000,
+       parameter clk_multiply = 12,
+       parameter clk_divide   = 5,
+       parameter phase_shift  = 0,
+       parameter wait200_init = 26
+) (
+       input                   clk, 
+       input                   reset,
+       //  DDR ports
+       output                  ddr_clk,
+       output                  ddr_clk_n,
+       input                   ddr_clk_fb,
+       output                  ddr_ras_n,
+       output                  ddr_cas_n,
+       output                  ddr_we_n,
+       output                  ddr_cke,
+       output                  ddr_cs_n,
+       output [  `A_RNG]       ddr_a,
+       output [ `BA_RNG]       ddr_ba,
+       inout  [ `DQ_RNG]       ddr_dq,
+       inout  [`DQS_RNG]       ddr_dqs,
+       output [ `DM_RNG]       ddr_dm,
+       // FML (FastMemoryLink)
+       input                   fml_wr,
+       input                   fml_rd,
+       output reg              fml_done,
+       input  [`FML_ADR_RNG]   fml_adr,
+       input  [`FML_DAT_RNG]   fml_din,
+       input  [`FML_MSK_RNG]   fml_msk,
+       output reg [`FML_DAT_RNG]   fml_dout,
+       // Temporary DCM control input
+       input  [2:0]            rot      // XXX
+);
+
+wire [ `DQ_RNG]       ddr_dq_i,  ddr_dq_o;
+wire [`DQS_RNG]       ddr_dqs_i, ddr_dqs_o;
+wire                  ddr_dqs_oe;
+
+//----------------------------------------------------------------------------
+// clock generator
+//----------------------------------------------------------------------------
+wire clk_locked;
+wire write_clk, write_clk90;
+wire read_clk;
+
+wire reset_int = reset | ~clk_locked;
+
+ddr_clkgen #(
+       .phase_shift(  phase_shift  ),
+       .clk_multiply( clk_multiply ),
+       .clk_divide(   clk_divide   )
+) clkgen (
+       .clk(             clk            ),
+       .reset(           reset          ),
+       .locked(          clk_locked     ),
+       // ddr-clk 
+       .read_clk(        read_clk       ),
+       .write_clk(       write_clk      ),
+       .write_clk90(     write_clk90    ),
+       // phase shift control
+       .rot(             rot            )      // XXX
+);
+
+//----------------------------------------------------------------------------
+// async_fifos (cmd, wdata, rdata)
+//----------------------------------------------------------------------------
+wire                  cba_fifo_full;
+reg  [`CBA_RNG]       cba_fifo_din;
+reg                   cba_fifo_we;
+
+wire                  wfifo_full;
+reg   [`WFIFO_RNG]    wfifo_din;
+reg                   wfifo_we;
+
+
+wire [`RFIFO_RNG]     rfifo_dout;
+wire                  rfifo_empty;
+wire                  rfifo_next;
+
+//----------------------------------------------------------------------------
+// High-speed cmd, write and read datapath
+//----------------------------------------------------------------------------
+ddr_wpath wpath0 (
+       .clk(         write_clk    ),
+       .clk90(       write_clk90  ),
+       .reset(       reset_int    ),
+       // CBA async fifo
+       .cba_clk(     clk           ),
+       .cba_din(     cba_fifo_din  ),
+       .cba_wr(      cba_fifo_we   ),
+       .cba_full(    cba_fifo_full ),
+       // WDATA async fifo
+       .wdata_clk(   clk           ),
+       .wdata_din(   wfifo_din     ),
+       .wdata_wr(    wfifo_we      ),
+       .wdata_full(  wfifo_full    ),
+       //
+       .sample(     sample      ), 
+       // DDR
+       .ddr_clk(     ddr_clk    ),
+       .ddr_clk_n(   ddr_clk_n  ),
+       .ddr_ras_n(   ddr_ras_n  ),
+       .ddr_cas_n(   ddr_cas_n  ),
+       .ddr_we_n(    ddr_we_n   ),
+       .ddr_a(       ddr_a      ),
+       .ddr_ba(      ddr_ba     ),
+       .ddr_dm(      ddr_dm     ),
+       .ddr_dq(      ddr_dq_o   ),
+       .ddr_dqs(     ddr_dqs_o  ),
+       .ddr_dqs_oe(  ddr_dqs_oe )
+);
+
+ddr_rpath rpath0 (
+       .clk(         read_clk   ),
+       .reset(       reset_int  ),
+       // 
+       .sample(      sample     ),
+       //
+       .rfifo_clk(   clk        ),
+       .rfifo_empty( rfifo_empty),
+       .rfifo_dout(  rfifo_dout ),
+       .rfifo_next(  rfifo_next ),
+       // DDR
+       .ddr_dq(      ddr_dq_i   ),
+       .ddr_dqs(     ddr_dqs_i  )
+);
+
+//----------------------------------------------------------------------------
+// 7.8 us pulse generator
+//----------------------------------------------------------------------------
+wire pulse78;
+reg  ar_req;
+reg  ar_done;
+
+ddr_pulse78 #(
+       .clk_freq( clk_freq )
+) pulse78_gen (
+       .clk(      clk        ),
+       .reset(    reset_int  ),
+       .pulse78(  pulse78    )
+);
+
+//----------------------------------------------------------------------------
+// Auto Refresh request generator
+//----------------------------------------------------------------------------
+always @(posedge clk)
+       if (reset_int)
+               ar_req <= 0;
+       else
+               ar_req <= pulse78 | (ar_req & ~ar_done);
+
+// operations we might want to submit
+wire [`CBA_RNG] ar_pre_cba;
+wire [`CBA_RNG] ar_ar_cba;
+
+assign ar_pre_cba   = { `DDR_CMD_PRE, 2'b00, 13'b1111111111111 };
+assign ar_ar_cba    = { `DDR_CMD_AR,  2'b00, 13'b0000000000000 };
+
+//----------------------------------------------------------------------------
+// Init & management
+//----------------------------------------------------------------------------
+wire                 init_req;
+reg                  init_ack;
+wire [`CBA_RNG]      init_cba;
+wire                 init_done;
+wire                 wait200;
+
+ddr_init #(
+       .wait200_init( wait200_init )
+) init (
+       .clk(         clk         ),
+       .reset(       reset_int   ),
+       .pulse78(     pulse78     ),
+       .wait200(     wait200     ),
+       .init_done(   init_done   ),
+       //
+       .mngt_req(    init_req    ),
+       .mngt_ack(    init_ack    ),
+       .mngt_cba(    init_cba    )
+);
+
+//----------------------------------------------------------------------------
+// Active Bank Information 
+//----------------------------------------------------------------------------
+reg [`ROW_RNG] ba_row [3:0];
+reg [3:0]      ba_active;
+
+//----------------------------------------------------------------------------
+// Handle write FIFO
+//----------------------------------------------------------------------------
+wire wfifo_proc_reset;
+wire wfifo_proc_start;
+reg  wfifo_proc_done;
+
+parameter w_idle   = 0;
+parameter w_1      = 1;
+parameter w_2      = 2;
+parameter w_3      = 3;
+parameter w_finish = 4;
+
+reg [2:0] wstate;
+
+always @(posedge clk)
+begin
+       if (reset_int) begin
+               wstate          <= w_idle;
+               wfifo_proc_done <= 0;
+       end else begin
+               wfifo_we <= 0;
+
+               case (wstate)
+                       w_idle: begin
+                               if (wfifo_proc_start & ~wfifo_full) begin
+                                       wfifo_din[`WFIFO_D0_RNG] <= fml_din[15: 0];
+                                       wfifo_din[`WFIFO_D1_RNG] <= fml_din[31:16];
+                                       wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 1: 0];
+                                       wfifo_din[`WFIFO_M1_RNG] <= fml_msk[ 3: 2];
+                                       wfifo_we                 <= 1;
+                                       wstate                   <= w_1;
+                               end
+                       end
+                       w_1: begin
+                               if (~wfifo_full) begin
+                                       wfifo_din[`WFIFO_D0_RNG] <= fml_din[47:32];
+                                       wfifo_din[`WFIFO_D1_RNG] <= fml_din[63:48];
+                                       wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 5: 4];
+                                       wfifo_din[`WFIFO_M1_RNG] <= fml_msk[ 7: 6];
+                                       wfifo_we                 <= 1;
+                                       wstate                   <= w_2;
+                               end
+                       end
+                       w_2: begin
+                               if (~wfifo_full) begin
+                                       wfifo_din[`WFIFO_D0_RNG] <= fml_din[79:64];
+                                       wfifo_din[`WFIFO_D1_RNG] <= fml_din[95:80];
+                                       wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 9: 8];
+                                       wfifo_din[`WFIFO_M1_RNG] <= fml_msk[11:10];
+                                       wfifo_we                 <= 1;
+                                       wstate                   <= w_3;
+                               end
+                       end
+                       w_3: begin
+                               if (~wfifo_full) begin
+                                       wfifo_din[`WFIFO_D0_RNG] <= fml_din[111: 96];
+                                       wfifo_din[`WFIFO_D1_RNG] <= fml_din[127:112];
+                                       wfifo_din[`WFIFO_M0_RNG] <= fml_msk[12:12];
+                                       wfifo_din[`WFIFO_M1_RNG] <= fml_msk[15:14];
+                                       wfifo_we                 <= 1;
+                                       wstate                   <= w_finish;
+                                       wfifo_proc_done          <= 1;
+                               end
+                       end
+                       w_finish: begin
+                               if (wfifo_proc_reset) begin
+                                       wstate          <= w_idle;
+                                       wfifo_proc_done <= 0;
+                               end
+                       end
+               endcase
+       end
+end
+
+//----------------------------------------------------------------------------
+// Handle read FIFO
+//----------------------------------------------------------------------------
+wire rfifo_proc_reset;
+wire rfifo_proc_start;
+reg  rfifo_proc_done ;
+
+parameter r_idle   = 0;
+parameter r_1      = 1;
+parameter r_2      = 2;
+parameter r_3      = 3;
+parameter r_finish = 4;
+
+reg [2:0] rstate;
+
+assign rfifo_next = ~rfifo_empty;
+
+always @(posedge clk)
+begin
+       if (reset_int) begin
+               rstate          <= r_idle;
+               rfifo_proc_done <= 0;
+       end else begin
+               case (rstate)
+                       r_idle: begin
+                               if (rfifo_proc_start & ~rfifo_empty) begin
+                                       fml_dout[31:0]   <= rfifo_dout;
+                                       rstate           <= r_1;
+                               end
+                       end
+                       r_1: begin
+                               if (~rfifo_empty) begin
+                                       fml_dout[63:32]  <= rfifo_dout;
+                                       rstate           <= r_2;
+                               end
+                       end
+                       r_2: begin
+                               if (~rfifo_empty) begin
+                                       fml_dout[95:64]  <= rfifo_dout;
+                                       rstate           <= r_3;
+                               end
+                       end
+                       r_3: begin
+                               if (~rfifo_empty) begin
+                                       fml_dout[127:96] <= rfifo_dout;
+                                       rstate           <= r_finish;
+                                       rfifo_proc_done  <= 1;
+                               end
+                       end
+                       r_finish: begin
+                               if (rfifo_proc_reset) begin
+                                       rfifo_proc_done  <= 0;
+                                       rstate           <= r_idle;
+                               end
+                       end
+               endcase
+       end
+end
+
+//----------------------------------------------------------------------------
+// FML decoding
+//----------------------------------------------------------------------------
+wire [`FML_ADR_BA_RNG]    fml_ba  = fml_adr[`FML_ADR_BA_RNG];
+wire [`FML_ADR_ROW_RNG]   fml_row = fml_adr[`FML_ADR_ROW_RNG];
+wire [`FML_ADR_COL_RNG]   fml_col = fml_adr[`FML_ADR_COL_RNG];
+
+wire [`FML_ADR_ROW_RNG]   fml_cur_row;   // current active row in sel. bank
+assign fml_cur_row    = ba_row[fml_ba];
+
+wire   fml_row_active;  // is row in selected ba really active?
+assign fml_row_active = ba_active[fml_ba]; 
+
+
+/*
+wire   fml_row_active = (fml_ba == 0) ? ba0_active :     // is row in selected
+                        (fml_ba == 1) ? ba1_active :     // bank really active?
+                        (fml_ba == 2) ? ba2_active :
+                                        ba3_active ;
+*/
+
+// request operation iff correct bank is active
+wire fml_req       = fml_rd | fml_wr;
+wire fml_row_match = (fml_row == fml_cur_row) & fml_row_active;
+wire fml_pre_req   = fml_req & ~fml_row_match & fml_row_active;
+wire fml_act_req   = fml_req & ~fml_row_active;
+wire fml_read_req  = fml_rd  &  fml_row_match & ~fml_done;
+wire fml_write_req = fml_wr  &  fml_row_match & ~fml_done;
+
+// actual operations we might want to submit
+wire [`CBA_RNG] fml_pre_cba;
+wire [`CBA_RNG] fml_act_cba;
+wire [`CBA_RNG] fml_read_cba;
+wire [`CBA_RNG] fml_write_cba;
+
+assign fml_pre_cba   = { `DDR_CMD_PRE,   fml_ba, 13'b0  };
+assign fml_act_cba   = { `DDR_CMD_ACT,   fml_ba, fml_row };
+assign fml_read_cba  = { `DDR_CMD_READ,  fml_ba, {3'b000}, fml_col, {3'b000} };
+assign fml_write_cba = { `DDR_CMD_WRITE, fml_ba, {3'b000}, fml_col, {3'b000} };
+
+//----------------------------------------------------------------------------
+// Schedule and issue commands
+//----------------------------------------------------------------------------
+
+parameter s_init      = 0;
+parameter s_idle      = 1;
+parameter s_ar        = 2;
+parameter s_reading   = 3;
+
+reg [1:0] state;
+
+always @(posedge clk)
+begin
+       if (reset_int) begin
+               state        <= s_init;
+               ba_active    <= 0;
+               ba_row[0]    <= 0;
+               ba_row[1]    <= 0;
+               ba_row[2]    <= 0;
+               ba_row[3]    <= 0;
+
+               fml_done     <= 0;
+               init_ack     <= 0;
+               cba_fifo_we  <= 0;
+               ar_done      <= 0;
+       end else begin
+               fml_done     <= 0;
+               init_ack     <= 0;
+               cba_fifo_we  <= 0;
+               ar_done      <= 0;
+
+               case (state)
+                       s_init: begin
+                               if (init_done)
+                                       state <= s_idle;
+
+                               if (init_req & ~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= init_cba;
+                                       init_ack          <= 1;
+                               end
+                       end
+                       s_idle: begin
+                               if (fml_read_req & ~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= fml_read_cba;
+                                       state             <= s_reading;
+                               end else if (fml_write_req & ~cba_fifo_full & wfifo_proc_done) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= fml_write_cba;
+                                       fml_done          <= 1;
+                               end else if (ar_req & ~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= ar_pre_cba;
+                                       ar_done           <= 1;
+                                       ba_active         <= 'b0;
+                                       state             <= s_ar;
+                               end else if (fml_pre_req & ~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= fml_pre_cba;
+                                       ba_active[fml_ba] <= 0;
+                               end else if (fml_act_req & ~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= fml_act_cba;
+                                       ba_active[fml_ba] <= 1;
+                                       ba_row[fml_ba]    <= fml_row;
+                               end
+                       end
+                       s_ar: begin
+                               if (~cba_fifo_full) begin
+                                       cba_fifo_we       <= 1;
+                                       cba_fifo_din      <= ar_ar_cba;
+                                       state             <= s_idle;
+                               end
+                       end
+                       s_reading: begin
+                               if (rfifo_proc_done) begin
+                                       fml_done          <= 1;
+                                       state             <= s_idle;
+                               end
+                       end
+               endcase
+       end
+end
+
+// start and stop rfifo engine
+assign rfifo_proc_start = fml_read_req;
+assign rfifo_proc_reset = fml_done;
+
+// start and stop wfifo engine
+assign wfifo_proc_start = fml_wr;
+assign wfifo_proc_reset = fml_done;
+
+//----------------------------------------------------------------------------
+// Demux dqs and dq
+//----------------------------------------------------------------------------
+assign ddr_cke   = ~wait200;     // bring up CKE as soon 200us wait is finished
+
+assign ddr_dqs = ddr_dqs_oe!=1'b0 ? ddr_dqs_o : 'bz;
+assign ddr_dq  = ddr_dqs_oe!=1'b0 ? ddr_dq_o  : 'bz;
+
+assign ddr_dqs_i = ddr_dqs;
+assign ddr_dq_i  = ddr_dq;
+
+assign ddr_cs_n = 0;
+
+endmodule
+
+// vim: set ts=4
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_include.v b/src/edu/berkeley/fleet/fpga/mem/ddr_include.v
new file mode 100644 (file)
index 0000000..ebcc4bf
--- /dev/null
@@ -0,0 +1,89 @@
+//---------------------------------------------------------------------------
+// DDR Controller
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//---------------------------------------------------------------------------
+
+`ifdef DDR_INCLUDE_V
+`else
+`define DDR_INCLUDE_V
+
+`timescale 1ns/10ps
+
+//---------------------------------------------------------------------------
+// Frequency 
+//---------------------------------------------------------------------------
+`define SYS_CLK_FREQUENCY   50000     // in kHz
+`define DDR_CLK_MULTIPLY    5        
+`define DDR_CLK_DIVIDE      2
+
+//---------------------------------------------------------------------------
+// FML ranges
+//---------------------------------------------------------------------------
+`define FML_ADR_RNG     25:4 
+`define FML_ADR_BA_RNG  25:24
+`define FML_ADR_ROW_RNG 23:11
+`define FML_ADR_COL_RNG 10:4
+`define FML_DAT_RNG    127:0
+`define FML_MSK_RNG     15:0
+
+//---------------------------------------------------------------------------
+// Width
+//---------------------------------------------------------------------------
+`define CMD_WIDTH  3
+`define A_WIDTH    13
+`define BA_WIDTH   2
+`define DQ_WIDTH   32
+`define DQS_WIDTH  4
+`define DM_WIDTH   4
+
+`define RFIFO_WIDTH  (2 * `DQ_WIDTH )
+`define WFIFO_WIDTH  (2 * (`DQ_WIDTH + `DM_WIDTH))
+`define CBA_WIDTH    (`CMD_WIDTH+`BA_WIDTH+`A_WIDTH)
+
+// Ranges
+`define CMD_RNG      (`CMD_WIDTH-1):0
+`define A_RNG        (`A_WIDTH-1):0
+`define BA_RNG       (`BA_WIDTH-1):0
+`define DQ_RNG       (`DQ_WIDTH-1):0
+`define DQS_RNG      (`DQS_WIDTH-1):0
+`define DM_RNG       (`DM_WIDTH-1):0
+
+`define RFIFO_RNG    (`RFIFO_WIDTH-1):0
+`define WFIFO_RNG    (`WFIFO_WIDTH-1):0
+`define WFIFO_D0_RNG (1*`DQ_WIDTH-1):0
+`define WFIFO_D1_RNG (2*`DQ_WIDTH-1):(`DQ_WIDTH)
+`define WFIFO_M0_RNG (2*`DQ_WIDTH+1*`DM_WIDTH-1):(2*`DQ_WIDTH+0*`DM_WIDTH)
+`define WFIFO_M1_RNG (2*`DQ_WIDTH+2*`DM_WIDTH-1):(2*`DQ_WIDTH+1*`DM_WIDTH)
+`define CBA_RNG      (`CBA_WIDTH-1):0
+`define CBA_CMD_RNG  (`CBA_WIDTH-1):(`CBA_WIDTH-3)
+`define CBA_BA_RNG   (`CBA_WIDTH-4):(`CBA_WIDTH-5)
+`define CBA_A_RNG    (`CBA_WIDTH-6):0
+
+`define ROW_RNG      12:0
+
+//---------------------------------------------------------------------------
+// DDR 
+//---------------------------------------------------------------------------
+`define DDR_CMD_NOP   3'b111
+`define DDR_CMD_ACT   3'b011
+`define DDR_CMD_READ  3'b101
+`define DDR_CMD_WRITE 3'b100
+`define DDR_CMD_TERM  3'b110
+`define DDR_CMD_PRE   3'b010
+`define DDR_CMD_AR    3'b001
+`define DDR_CMD_MRS   3'b000
+
+`define T_MRD   2           // Mode register set 
+`define T_RP    2           // Precharge Command Period
+`define T_RFC   8           // Precharge Command Period
+
+`define DDR_INIT_EMRS  `A_WIDTH'b0000000000000  // DLL enable
+`define DDR_INIT_MRS1  `A_WIDTH'b0000101100011  // BURST=8, CL=2.5, DLL RESET
+`define DDR_INIT_MRS2  `A_WIDTH'b0000001100011  // BURST=8, CL=2.5
+
+`define ADR_BA_RNG    25:24
+`define ADR_ROW_RNG   23:11
+`define ADR_COL_RNG   10:4
+
+`endif
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_init.v b/src/edu/berkeley/fleet/fpga/mem/ddr_init.v
new file mode 100644 (file)
index 0000000..343d0af
--- /dev/null
@@ -0,0 +1,191 @@
+//----------------------------------------------------------------------------
+// Wishbone DDR Controller
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//----------------------------------------------------------------------------
+`include "ddr_include.v"
+
+module ddr_init 
+#(
+       parameter               wait200_init = 26
+) (
+       input                   clk, 
+       input                   reset,
+       input                   pulse78,
+       output                  wait200,
+       output                  init_done,
+       //
+       output                  mngt_req,
+       input                   mngt_ack,
+       output [`CBA_RNG]       mngt_cba       // CMD, BA and ADDRESS
+);
+
+reg              cmd_req_reg;
+reg [`CMD_RNG]   cmd_cmd_reg;
+reg [ `BA_RNG]   cmd_ba_reg;
+reg [  `A_RNG]   cmd_a_reg;
+reg [7:0]        cmd_idle_reg;
+
+//---------------------------------------------------------------------------
+// Initial 200us delay
+//---------------------------------------------------------------------------
+
+// `define WAIT200_INIT 26
+// `define WAIT200_INIT 1
+
+reg [4:0] wait200_counter;
+reg       wait200_reg;
+
+always @(posedge clk)
+begin
+       if (reset) begin
+               wait200_reg     <= 1;
+               wait200_counter <= wait200_init;
+       end else begin
+               if (wait200_counter == 0)
+                       wait200_reg <= 0;
+
+               if (wait200_reg & pulse78)
+                       wait200_counter <= wait200_counter - 1;
+       end
+end
+
+assign wait200 = wait200_reg;
+
+//---------------------------------------------------------------------------
+// Auto refresh counter
+//---------------------------------------------------------------------------
+
+reg [2:0] ar_counter;
+wire      ar_cmd_acked;
+wire      ar_needed;
+wire      ar_badly_needed;
+
+assign ar_cmd_acked    = (cmd_cmd_reg == `DDR_CMD_AR) & mngt_ack;
+assign ar_needed       = (ar_counter != 0) & ~ar_cmd_acked; 
+assign ar_badly_needed = ar_counter[2] == 1'b1;  // >= 4
+
+always @(posedge clk)
+begin
+       if (reset) begin
+               ar_counter <= 0;
+       end else begin
+               if (~init_done)
+                       ar_counter <= 0;
+               else if (pulse78 & ~ar_cmd_acked) 
+                       ar_counter <= ar_counter + 1;
+               else if (ar_cmd_acked & ~pulse78) 
+                       ar_counter <= ar_counter - 1;
+       end
+end
+
+//----------------------------------------------------------------------------
+// DDR Initialization State Machine
+//----------------------------------------------------------------------------
+
+parameter s_wait200 = 0;
+parameter s_init1   = 1;
+parameter s_init2   = 2;
+parameter s_init3   = 3;
+parameter s_init4   = 4;
+parameter s_init5   = 5;
+parameter s_init6   = 6;
+parameter s_waitack = 7;
+parameter s_idle    = 8;
+
+reg [3:0]        state;
+reg              init_done_reg;
+
+assign mngt_cba     = {cmd_cmd_reg, cmd_ba_reg, cmd_a_reg};
+assign mngt_req     = cmd_req_reg;
+assign mngt_pri_req = ~init_done_reg;
+assign init_done    = init_done_reg;
+
+always @(posedge clk or posedge reset)
+begin
+       if (reset) begin
+               init_done_reg <= 0;
+               state         <= s_wait200;
+               cmd_idle_reg  <= 0;
+               cmd_req_reg   <= 0;
+               cmd_cmd_reg   <= 'b0;
+               cmd_ba_reg    <= 'b0;
+               cmd_a_reg     <= 'b0;
+       end else begin
+               case (state)
+                       s_wait200: begin
+                               if (~wait200_reg) begin
+                                               state         <= s_init1;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_PRE;   // PRE ALL
+                                               cmd_a_reg[10] <= 1'b1;
+                                       end
+                               end
+                       s_init1: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_init2;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_MRS;   // EMRS
+                                               cmd_ba_reg    <= 2'b01;
+                                               cmd_a_reg     <= `DDR_INIT_EMRS;
+                                       end
+                               end
+                       s_init2: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_init3;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_MRS;   // MRS
+                                               cmd_ba_reg    <= 2'b00;
+                                               cmd_a_reg     <= `DDR_INIT_MRS1;
+                                       end
+                               end
+                       s_init3: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_init4;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_PRE;   // PRE ALL
+                                               cmd_a_reg[10] <= 1'b1;
+                                       end
+                               end
+                       s_init4: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_init5;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_AR;   // AR
+                                       end
+                               end
+                       s_init5: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_init6;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_AR;   // AR
+                                       end
+                               end
+                       s_init6: begin
+                                       if (mngt_ack) begin
+                                               init_done_reg <= 1;
+                                               state         <= s_waitack;
+                                               cmd_req_reg   <= 1;
+                                               cmd_cmd_reg   <= `DDR_CMD_MRS;  // MRS
+                                               cmd_ba_reg    <= 2'b00;
+                                               cmd_a_reg     <= `DDR_INIT_MRS2;
+                                       end
+                               end
+                       s_waitack: begin
+                                       if (mngt_ack) begin
+                                               state         <= s_idle;
+                                               cmd_req_reg   <= 0;
+                                               cmd_cmd_reg   <= 'b0;
+                                               cmd_ba_reg    <= 'b0;
+                                               cmd_a_reg     <= 'b0;
+                                       end
+                               end
+                       s_idle: begin
+                               end
+               endcase ///////////////////////////////////////// INIT STATE MACHINE ///
+       end
+end
+
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_pulse78.v b/src/edu/berkeley/fleet/fpga/mem/ddr_pulse78.v
new file mode 100644 (file)
index 0000000..396576e
--- /dev/null
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+// Wishbone DDR Controller
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//----------------------------------------------------------------------------
+`include "ddr_include.v"
+
+module ddr_pulse78 #(
+       parameter    clk_freq = 50000000
+) (
+       input        clk,
+       input        reset,
+       //
+       output   reg pulse78
+);
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+`define PULSE78_RNG  10:0
+
+parameter pulse78_init = 78 * (clk_freq/10000000);
+
+reg [`PULSE78_RNG] counter;
+
+always @(posedge clk)
+begin
+       if (reset) begin
+               counter <= pulse78_init;
+               pulse78 <= 0;
+       end else begin
+               if (counter == 0) begin
+                       counter <= pulse78_init;
+                       pulse78 <= 1'b1;
+               end else begin
+                       counter <= counter - 1;
+                       pulse78 <= 0;
+               end
+       end
+end
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_rpath.v b/src/edu/berkeley/fleet/fpga/mem/ddr_rpath.v
new file mode 100644 (file)
index 0000000..3286003
--- /dev/null
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+// Wishbone DDR Controller
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//----------------------------------------------------------------------------
+
+`include "ddr_include.v"
+
+module ddr_rpath
+(
+       input                  clk,
+       input                  reset,
+       // sample activate
+       input                  sample,
+       // RDATA async fifo
+       input                  rfifo_clk,
+       output                 rfifo_empty,
+       output [`RFIFO_RNG]    rfifo_dout,
+       input                  rfifo_next,
+       // DDR 
+       input [ `DQ_RNG]       ddr_dq,
+       input [`DQS_RNG]       ddr_dqs
+);
+
+//----------------------------------------------------------------------------
+// RDATA async. fifo
+//----------------------------------------------------------------------------
+
+wire [`RFIFO_RNG]      rfifo_din;
+wire                   rfifo_wr;
+wire                   rfifo_full;
+
+async_fifo #(
+       .DATA_WIDTH( `RFIFO_WIDTH ),
+       .ADDRESS_WIDTH( 3 )
+) rfifo (
+       .Data_out(   rfifo_dout  ),
+       .Empty_out(  rfifo_empty ),
+       .ReadEn_in(  rfifo_next  ),
+       .RClk(       rfifo_clk   ),
+       //
+       .Data_in(    rfifo_din   ),
+       .WriteEn_in( rfifo_wr    ),
+       .Full_out(   rfifo_full  ),
+       .WClk(      ~clk         ),
+       .Clear_in(   reset       )
+);
+
+
+//----------------------------------------------------------------------------
+// Clean up incoming 'sample' signal and generate sample_dq
+//----------------------------------------------------------------------------
+
+// anti-meta-state
+//reg       sample180; 
+//always @(negedge clk) sample180 <= sample;
+wire sample180 = sample;
+
+
+reg       sample_dq;          // authoritive sample flag (after cleanup)
+reg       sample_dq_delayed;  // write to rfifo?
+reg [3:0] sample_count;       // make sure sample_dq is up exactly 
+                              // BURSTLENGTH/2 cycles
+
+always @(posedge clk or posedge reset)
+begin
+       if (reset) begin
+               sample_dq         <= 0;
+               sample_dq_delayed <= 0;
+               sample_count      <= 0;
+       end else begin
+               sample_dq_delayed <= sample_dq;
+               if (sample_count == 0) begin
+                       if (sample180) begin
+                               sample_dq    <= 1;
+                               sample_count <= 1;
+                       end
+               end else if (sample_count == 4) begin
+                       sample_dq    <= 0;
+                       sample_count <= 0;
+               end else
+                       sample_count <= sample_count + 1;
+                       
+       end
+end
+
+//----------------------------------------------------------------------------
+// Sampe DQ and fill RFIFO
+//----------------------------------------------------------------------------
+reg [15:0] ddr_dq_low, ddr_dq_high;
+
+always @(negedge clk )
+begin
+       if (reset)
+               ddr_dq_low <= 'b0;
+       else
+               ddr_dq_low <= ddr_dq;
+end
+
+always @(posedge clk)
+begin
+       if (reset)
+               ddr_dq_high <= 'b0;
+       else
+               ddr_dq_high <= ddr_dq;
+end
+
+assign rfifo_wr  = sample_dq_delayed;
+assign rfifo_din = { ddr_dq_high, ddr_dq_low };
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/ddr_wpath.v b/src/edu/berkeley/fleet/fpga/mem/ddr_wpath.v
new file mode 100644 (file)
index 0000000..f1f1ee3
--- /dev/null
@@ -0,0 +1,286 @@
+//----------------------------------------------------------------------------
+//
+// Wishbone DDR Controller -- fast write data-path
+// 
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//
+//----------------------------------------------------------------------------
+
+`include "ddr_include.v"
+
+module ddr_wpath (
+       input                  clk,
+       input                  clk90,
+       input                  reset,
+       // CBA async fifo
+       input                  cba_clk,
+       input [`CBA_RNG]       cba_din,
+       input                  cba_wr,
+       output                 cba_full,
+       // WDATA async fifo
+       input                  wdata_clk,
+       input [`WFIFO_RNG]     wdata_din,
+       input                  wdata_wr,
+       output                 wdata_full,
+       // sample to rdata
+       output                 sample,
+       // DDR 
+       output                 ddr_clk,
+       output                 ddr_clk_n,
+       output                 ddr_ras_n,
+       output                 ddr_cas_n,
+       output                 ddr_we_n,
+       output [  `A_RNG]      ddr_a,
+       output [ `BA_RNG]      ddr_ba,
+       output [ `DM_RNG]      ddr_dm,
+       output [ `DQ_RNG]      ddr_dq,
+       output [`DQS_RNG]      ddr_dqs,
+       output                 ddr_dqs_oe
+);
+
+wire gnd = 1'b0;
+wire vcc = 1'b1;
+
+//----------------------------------------------------------------------------
+// CBA async. fifo
+//----------------------------------------------------------------------------
+wire [`CBA_RNG]        cba_data;
+wire                   cba_empty;
+wire                   cba_ack;
+
+wire                   cba_avail = ~cba_empty;
+
+async_fifo #(
+       .DATA_WIDTH( `CBA_WIDTH ),
+       .ADDRESS_WIDTH( 3 )
+) cba_fifo (
+       .Data_out(   cba_data  ),
+       .Empty_out(  cba_empty ),
+       .ReadEn_in(  cba_ack   ),
+       .RClk(       clk       ),
+       //
+       .Data_in(    cba_din   ),
+       .WriteEn_in( cba_wr    ),
+       .Full_out(   cba_full  ),
+       .WClk(       cba_clk   ),
+       .Clear_in(   reset     )
+);
+
+//----------------------------------------------------------------------------
+// WDATA async. fifo
+//----------------------------------------------------------------------------
+wire [`WFIFO_RNG]      wdata_data;
+wire                   wdata_empty;
+wire                   wdata_ack;
+
+wire                   wdata_avail = ~wdata_empty;
+
+async_fifo #(
+       .DATA_WIDTH( `WFIFO_WIDTH ),
+       .ADDRESS_WIDTH( 3 )
+) wdata_fifo (
+       .Data_out(   wdata_data  ),
+       .Empty_out(  wdata_empty ),
+       .ReadEn_in(  wdata_ack   ),
+       .RClk(      ~clk90       ),
+       //
+       .Data_in(    wdata_din   ),
+       .WriteEn_in( wdata_wr    ),
+       .Full_out(   wdata_full  ),
+       .WClk(       wdata_clk   ),
+       .Clear_in(   reset       )
+);
+
+
+//----------------------------------------------------------------------------
+// Handle CBA 
+//----------------------------------------------------------------------------
+reg  [3:0]      delay_count;
+
+reg [`CBA_RNG]  ddr_cba;
+wire [`CBA_RNG] CBA_NOP = { `DDR_CMD_NOP, 15'b0 };
+
+assign cba_ack = cba_avail & (delay_count == 0);
+
+wire [`CMD_RNG] cba_cmd = cba_data[(`CBA_WIDTH-1):(`CBA_WIDTH-3)];
+
+always @(posedge clk)
+begin
+       if (reset) begin
+               delay_count <= 0;
+               ddr_cba     <= CBA_NOP;
+       end else begin
+               if (delay_count != 0) begin
+                       delay_count <= delay_count - 1;
+                       ddr_cba     <= CBA_NOP;
+        end
+
+               if (!cba_ack) begin
+                       ddr_cba  <= CBA_NOP;
+               end else begin
+                       ddr_cba <= cba_data;
+
+                       case (cba_cmd)
+                               `DDR_CMD_MRS   : delay_count <= 2;
+                               `DDR_CMD_AR    : delay_count <= 14;
+                               `DDR_CMD_ACT   : delay_count <= 4;
+                               `DDR_CMD_PRE   : delay_count <= 2;
+                               `DDR_CMD_READ  : delay_count <= 6;   // XXX
+                               `DDR_CMD_WRITE : delay_count <= 8;   // XXX
+                       endcase
+               end
+       end
+end
+                       
+
+//----------------------------------------------------------------------------
+// READ-SHIFT-REGISTER
+//----------------------------------------------------------------------------
+reg [0:7] read_shr;
+wire      read_cmd = (cba_cmd == `DDR_CMD_READ) & cba_ack;
+assign    sample   = read_shr[1];
+
+always @(posedge clk)
+begin
+       if (reset)
+               read_shr <= 'b0;
+       else begin
+               if (read_cmd)
+                       read_shr <= { 8'b00011111 };
+               else
+                       read_shr <= { read_shr[1:7], 1'b0 };
+       end
+end
+
+//----------------------------------------------------------------------------
+// WRITE-SHIFT-REGISTER
+//----------------------------------------------------------------------------
+
+reg [0:4] write_shr;
+wire      write_cmd = (cba_cmd == `DDR_CMD_WRITE) & cba_ack;
+
+always @(posedge clk)
+begin
+       if (reset)
+               write_shr <= 'b0;
+       else begin
+               if (write_cmd)
+                       write_shr <= { 5'b11111 };
+               else
+                       write_shr <= { write_shr[1:4], 1'b0 };
+       end
+end
+
+//----------------------------------------------------------------------------
+// DDR_DQS, DDR_DQS_OE
+//----------------------------------------------------------------------------
+genvar i;
+
+reg ddr_dqs_oe_reg;
+assign ddr_dqs_oe = ddr_dqs_oe_reg;
+
+always @(negedge clk)
+begin
+  ddr_dqs_oe_reg <= write_shr[0];
+end
+
+FDDRRSE ddr_clk_reg (
+       .Q(   ddr_clk      ),
+       .C0(  clk90        ),
+       .C1( ~clk90        ),
+       .CE(  vcc          ),
+       .D0(  vcc          ),
+       .D1(  gnd          ),
+       .R(   gnd          ),
+       .S(   gnd          )
+);
+
+FDDRRSE ddr_clk_n_reg (
+       .Q(   ddr_clk_n    ),
+       .C0(  clk90        ),
+       .C1( ~clk90        ),
+       .CE(  vcc          ),
+       .D0(  gnd          ),
+       .D1(  vcc          ),
+       .R(   gnd          ),
+       .S(   gnd          )
+);
+
+
+generate 
+for (i=0; i<`DQS_WIDTH; i=i+1) begin : DQS
+       FDDRRSE ddr_dqs_reg (
+               .Q(   ddr_dqs[i]   ),
+               .C0(  clk          ),
+               .C1( ~clk          ),
+               .CE(  vcc          ),
+               .D0(  write_shr[1] ),
+               .D1(  gnd          ),
+               .R(   gnd          ),
+               .S(   gnd          )
+       );
+end
+endgenerate
+
+
+//----------------------------------------------------------------------------
+// DQ data output
+//----------------------------------------------------------------------------
+wire [`DQ_RNG] buf_d0;        
+wire [`DM_RNG] buf_m0;
+reg  [`DQ_RNG] buf_d1;       // pipleine high word data
+reg  [`DM_RNG] buf_m1;       // pipleine high word mask
+
+assign buf_d0 = wdata_data[`WFIFO_D0_RNG];
+assign buf_m0 = wdata_data[`WFIFO_M0_RNG];
+
+always @(negedge clk90)
+begin
+       buf_d1 <= wdata_data[`WFIFO_D1_RNG];
+       buf_m1 <= wdata_data[`WFIFO_M1_RNG];
+end
+
+assign wdata_ack = write_shr[1];
+
+// generate DDR_DQ register
+generate 
+for (i=0; i<`DQ_WIDTH; i=i+1) begin : DQ_REG
+       FDDRRSE ddr_dq_reg (
+               .Q(   ddr_dq[i]    ),
+               .C0( ~clk90        ),
+               .C1(  clk90        ),
+               .CE(  vcc          ),
+               .D0(  buf_d0[i]    ),
+               .D1(  buf_d1[i]    ),
+               .R(   gnd          ),
+               .S(   gnd          )
+       );
+end
+endgenerate
+
+// generate DDR_DM register
+generate 
+for (i=0; i<`DM_WIDTH; i=i+1) begin : DM_REG
+       FDDRRSE ddr_dm_reg (
+               .Q(   ddr_dm[i]    ),
+               .C0( ~clk90        ),
+               .C1(  clk90        ),
+               .CE(  vcc          ),
+               .D0(  buf_m0[i]    ),
+               .D1(  buf_m1[i]    ),
+               .R(   gnd          ),
+               .S(   gnd          )
+       );
+end
+endgenerate
+
+//----------------------------------------------------------------------------
+// Connect ddr_cba to actual DDR pins
+//----------------------------------------------------------------------------
+assign ddr_a     = ddr_cba[(`A_WIDTH-1):0];
+assign ddr_ba    = ddr_cba[(`A_WIDTH+`BA_WIDTH-1):(`A_WIDTH)];
+assign ddr_ras_n = ddr_cba[(`CBA_WIDTH-1)];
+assign ddr_cas_n = ddr_cba[(`CBA_WIDTH-2)];
+assign ddr_we_n  = ddr_cba[(`CBA_WIDTH-3)];
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/mem/gray_counter.v b/src/edu/berkeley/fleet/fpga/mem/gray_counter.v
new file mode 100644 (file)
index 0000000..ff3b29b
--- /dev/null
@@ -0,0 +1,35 @@
+//==========================================
+// Function : Code Gray counter.
+// Coder    : Alex Claros F.
+// Date     : 15/May/2005.
+//=======================================
+
+`timescale 1ns/1ps
+
+module GrayCounter
+   #(parameter   COUNTER_WIDTH = 2)
+   
+    (output reg  [COUNTER_WIDTH-1:0]    GrayCount_out,  //'Gray' code count output.
+    
+     input wire                         Enable_in,  //Count enable.
+     input wire                         Clear_in,   //Count reset.
+    
+     input wire                         Clk);
+
+    /////////Internal connections & variables///////
+    reg    [COUNTER_WIDTH-1:0]         BinaryCount;
+
+    /////////Code///////////////////////
+    
+    always @ (posedge Clk)
+        if (Clear_in) begin
+            BinaryCount   <= {COUNTER_WIDTH{1'b 0}} + 1;  //Gray count begins @ '1' with
+            GrayCount_out <= {COUNTER_WIDTH{1'b 0}};      // first 'Enable_in'.
+        end
+        else if (Enable_in) begin
+            BinaryCount   <= BinaryCount + 1;
+            GrayCount_out <= {BinaryCount[COUNTER_WIDTH-1],
+                              BinaryCount[COUNTER_WIDTH-2:0] ^ BinaryCount[COUNTER_WIDTH-1:1]};
+        end
+    
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/mem/rotary.v b/src/edu/berkeley/fleet/fpga/mem/rotary.v
new file mode 100644 (file)
index 0000000..83c2349
--- /dev/null
@@ -0,0 +1,70 @@
+//----------------------------------------------------------------------------
+// Decode rotary encoder to clk-syncronous signals
+//
+// (c) Joerg Bornschein (<jb@capsec.org>)
+//----------------------------------------------------------------------------
+
+module rotary (
+       input        clk,
+       input        reset,
+       input [2:0]  rot,
+       //
+       output reg   rot_btn,
+       output reg   rot_event,
+       output reg   rot_left
+);
+
+//----------------------------------------------------------------------------
+// decode rotary encoder
+//----------------------------------------------------------------------------
+reg [1:0] rot_q;
+
+always @(posedge clk)
+begin
+       case (rot[1:0])
+               2'b00: rot_q <= { rot_q[1], 1'b0 };
+               2'b01: rot_q <= { 1'b0, rot_q[0] };
+               2'b10: rot_q <= { 1'b1, rot_q[0] };
+               2'b11: rot_q <= { rot_q[1], 1'b1 };
+       endcase
+end
+
+reg [1:0] rot_q_delayed;
+
+always @(posedge clk)
+begin
+       rot_q_delayed <= rot_q;
+
+       if (rot_q[0] && ~rot_q_delayed[0]) begin
+               rot_event <= 1;
+               rot_left  <= rot_q[1];
+       end else
+               rot_event <= 0;
+end
+
+//----------------------------------------------------------------------------
+// debounce push button (rot[2])
+//----------------------------------------------------------------------------
+reg [2:0]  rot_d;
+reg [15:0] dead_count;
+
+always @(posedge clk)
+begin
+       if (reset) begin
+               rot_btn    <= 0;
+               dead_count <= 0;
+       end else begin
+               rot_btn <= 1'b0;
+               rot_d   <= { rot_d[1:0], rot[2] };
+
+               if (dead_count == 0) begin
+                       if ( rot_d[2:1] == 2'b01 ) begin
+                               rot_btn    <= 1'b1;
+                               dead_count <= dead_count - 1;
+                       end
+               end else
+                       dead_count <= dead_count - 1;
+       end
+end
+
+endmodule
diff --git a/src/edu/berkeley/fleet/fpga/mem/sasc_brg.v b/src/edu/berkeley/fleet/fpga/mem/sasc_brg.v
new file mode 100644 (file)
index 0000000..8dde36c
--- /dev/null
@@ -0,0 +1,163 @@
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+////  Simple Baud Rate Generator                                 ////
+////                                                             ////
+////                                                             ////
+////  Author: Rudolf Usselmann                                   ////
+////          rudi@asics.ws                                      ////
+////                                                             ////
+////                                                             ////
+////  Downloaded from: http://www.opencores.org/cores/sasc/      ////
+////                                                             ////
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+//// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
+////                         www.asics.ws                        ////
+////                         rudi@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: sasc_brg.v,v 1.2 2002/11/08 15:22:49 rudi Exp $
+//
+//  $Date: 2002/11/08 15:22:49 $
+//  $Revision: 1.2 $
+//  $Author: rudi $
+//  $Locker:  $
+//  $State: Exp $
+//
+// Change History:
+//               $Log: sasc_brg.v,v $
+//               Revision 1.2  2002/11/08 15:22:49  rudi
+//
+//               Fixed a typo in brg
+//
+//               Revision 1.1.1.1  2002/09/16 16:16:40  rudi
+//               Initial Checkin
+//
+//
+//
+//
+//
+//
+//
+//
+
+`include "timescale.v"
+
+/*
+       Baud rate Generator
+       ==================
+
+       div0 -  is the first stage divider
+               Set this to the desired number of cycles less two
+       div1 -  is the second stage divider
+               Set this to the actual number of cycles
+
+       Remember you have to generate a baud rate that is 4 higher than what
+       you really want. This is because of the DPLL in the RX section ...
+
+       Example:
+       If your system clock is 50MHz and you want to generate a 9.6 Kbps baud rate:
+       9600*4 = 38400KHz
+       50MHz/38400KHz=1302 or 6*217
+       set div0=4 (6-2) and set div1=217
+
+       100MHz/38400KHz=2604 or 12*217
+       set div0=10 (12-2) and set div1=217
+
+*/
+
+module sasc_brg(clk, rst, div0, div1, sio_ce, sio_ce_x4);
+input          clk;
+input          rst;
+input  [7:0]   div0, div1;
+output         sio_ce, sio_ce_x4;
+
+///////////////////////////////////////////////////////////////////
+//
+// Local Wires and Registers
+//
+
+reg    [7:0]   ps;
+reg            ps_clr;
+reg    [7:0]   br_cnt;
+reg            br_clr;
+reg            sio_ce_x4_r;
+reg    [1:0]   cnt;
+reg            sio_ce, sio_ce_x4;
+reg            sio_ce_r ;
+reg            sio_ce_x4_t;
+
+///////////////////////////////////////////////////////////////////
+//
+// Boud Rate Generator
+//
+
+// -----------------------------------------------------
+// Prescaler
+always @(posedge clk)
+       if(!rst)        ps <= #1 8'h0;
+       else
+       if(ps_clr)      ps <= #1 8'h0;
+       else            ps <= #1 ps + 8'h1;
+
+always @(posedge clk)
+       ps_clr <= #1 (ps == div0);      // Desired number of cycles less 2
+
+// -----------------------------------------------------
+// Oversampled Boud Rate (x4)
+always @(posedge clk)
+       if(!rst)        br_cnt <= #1 8'h0;
+       else
+       if(br_clr)      br_cnt <= #1 8'h0;
+       else
+       if(ps_clr)      br_cnt <= #1 br_cnt + 8'h1;
+
+always @(posedge clk)
+       br_clr <= #1 (br_cnt == div1); // Prciese number of PS cycles
+
+always @(posedge clk)
+       sio_ce_x4_r <= #1 br_clr;
+
+always @(posedge clk)
+       sio_ce_x4_t <= #1 !sio_ce_x4_r & br_clr;
+
+always @(posedge clk)
+       sio_ce_x4 <= #1 sio_ce_x4_t;
+
+// -----------------------------------------------------
+// Actual Boud rate
+always @(posedge clk)
+       if(!rst)                        cnt <= #1 2'h0;
+       else
+       if(!sio_ce_x4_r & br_clr)       cnt <= #1 cnt + 2'h1;
+
+always @(posedge clk)
+       sio_ce_r <= #1 (cnt == 2'h0);
+
+always @(posedge clk)
+       sio_ce <= #1 !sio_ce_r & (cnt == 2'h0);
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/sasc_fifo4.v b/src/edu/berkeley/fleet/fpga/mem/sasc_fifo4.v
new file mode 100644 (file)
index 0000000..59aec78
--- /dev/null
@@ -0,0 +1,138 @@
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+////  FIFO 4 entries deep                                        ////
+////                                                             ////
+////                                                             ////
+////  Author: Rudolf Usselmann                                   ////
+////          rudi@asics.ws                                      ////
+////                                                             ////
+////                                                             ////
+////  Downloaded from: http://www.opencores.org/cores/sasc/      ////
+////                                                             ////
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+//// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
+////                         www.asics.ws                        ////
+////                         rudi@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: sasc_fifo4.v,v 1.1.1.1 2002/09/16 16:16:41 rudi Exp $
+//
+//  $Date: 2002/09/16 16:16:41 $
+//  $Revision: 1.1.1.1 $
+//  $Author: rudi $
+//  $Locker:  $
+//  $State: Exp $
+//
+// Change History:
+//               $Log: sasc_fifo4.v,v $
+//               Revision 1.1.1.1  2002/09/16 16:16:41  rudi
+//               Initial Checkin
+//
+//
+//
+//
+//
+//
+
+`include "timescale.v"
+
+// 4 entry deep fast fifo
+module sasc_fifo4(clk, rst, clr,  din, we, dout, re, full, empty);
+
+input          clk, rst;
+input          clr;
+input   [7:0]  din;
+input          we;
+output  [7:0]  dout;
+input          re;
+output         full, empty;
+
+////////////////////////////////////////////////////////////////////
+//
+// Local Wires
+//
+
+reg     [7:0]  mem[0:3];
+reg     [1:0]   wp;
+reg     [1:0]   rp;
+wire    [1:0]   wp_p1;
+wire    [1:0]   wp_p2;
+wire    [1:0]   rp_p1;
+wire           full, empty;
+reg            gb;
+
+initial wp = 0;
+initial rp = 0;
+initial gb = 0;
+
+////////////////////////////////////////////////////////////////////
+//
+// Misc Logic
+//
+
+always @(posedge clk or negedge rst)
+        if(!rst)       wp <= #1 2'h0;
+        else
+        if(clr)                wp <= #1 2'h0;
+        else
+        if(we)         wp <= #1 wp_p1;
+
+assign wp_p1 = wp + 2'h1;
+assign wp_p2 = wp + 2'h2;
+
+always @(posedge clk or negedge rst)
+        if(!rst)       rp <= #1 2'h0;
+        else
+        if(clr)                rp <= #1 2'h0;
+        else
+        if(re)         rp <= #1 rp_p1;
+
+assign rp_p1 = rp + 2'h1;
+
+// Fifo Output
+assign  dout = mem[ rp ];
+
+// Fifo Input 
+always @(posedge clk)
+        if(we)     mem[ wp ] <= #1 din;
+
+// Status
+assign empty = (wp == rp) & !gb;
+assign full  = (wp == rp) &  gb;
+
+// Guard Bit ...
+always @(posedge clk)
+       if(!rst)                        gb <= #1 1'b0;
+       else
+       if(clr)                         gb <= #1 1'b0;
+       else
+       if((wp_p1 == rp) & we)          gb <= #1 1'b1;
+       else
+       if(re)                          gb <= #1 1'b0;
+
+endmodule
+
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/sasc_top.v b/src/edu/berkeley/fleet/fpga/mem/sasc_top.v
new file mode 100644 (file)
index 0000000..a5dfa77
--- /dev/null
@@ -0,0 +1,323 @@
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+////  Simple Asynchronous Serial Comm. Device                    ////
+////                                                             ////
+////                                                             ////
+////  Author: Rudolf Usselmann                                   ////
+////          rudi@asics.ws                                      ////
+////                                                             ////
+////                                                             ////
+////  Downloaded from: http://www.opencores.org/cores/sasc/      ////
+////                                                             ////
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+//// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
+////                         www.asics.ws                        ////
+////                         rudi@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: sasc_top.v,v 1.2 2006/03/30 02:47:07 rudi Exp $
+//
+//  $Date: 2006/03/30 02:47:07 $
+//  $Revision: 1.2 $
+//  $Author: rudi $
+//  $Locker:  $
+//  $State: Exp $
+//
+// Change History:
+//               $Log: sasc_top.v,v $
+//               Revision 1.2  2006/03/30 02:47:07  rudi
+//               Thanks to Darren O'Connor of SPEC, Inc. for fixing a bug
+//               with the DPLL and data alignment:
+//
+//               You were right that it was a problem with the dpll. I found
+//               that it was possible to get two baud clocks (rx_sio_ce) during
+//               one bit period.  I fixed the problem by delaying the input data
+//               signal with a shift register and using that in the equations
+//               for the "change" variable that controls the DPLL FSM.
+//
+//               Revision 1.1.1.1  2002/09/16 16:16:42  rudi
+//               Initial Checkin
+//
+//
+//
+//
+//
+//
+//
+//
+
+`include "timescale.v"
+
+/*
+Serial IO Interface
+===============================
+RTS I Request To Send
+CTS O Clear to send
+TD  I Transmit Data
+RD  O Receive Data
+*/
+
+module sasc_top(       clk, rst,
+       
+                       // SIO
+                       rxd_i, txd_o, cts_i, rts_o, 
+
+                       // External Baud Rate Generator
+                       sio_ce, sio_ce_x4,
+
+                       // Internal Interface
+                       din_i, dout_o, re_i, we_i, full_o, empty_o,
+                        break_o, flush_i);
+
+input          clk;
+input          rst;
+input          rxd_i;
+output         txd_o;
+input          cts_i;
+output         rts_o; 
+output          break_o;
+input           flush_i;
+reg break_r;
+input          sio_ce;
+input          sio_ce_x4;
+input  [7:0]   din_i;
+output [7:0]   dout_o;
+input          re_i, we_i;
+output         full_o, empty_o;
+
+///////////////////////////////////////////////////////////////////
+//
+// Local Wires and Registers
+//
+
+parameter      START_BIT       = 1'b0,
+               STOP_BIT        = 1'b1,
+               IDLE_BIT        = 1'b1;
+
+wire   [7:0]   txd_p;
+reg            load;
+reg            load_r;
+wire           load_e;
+reg    [9:0]   hold_reg;
+wire           txf_empty;
+reg            txd_o;
+reg            shift_en;
+reg    [3:0]   tx_bit_cnt;
+reg            rxd_s, rxd_r;
+wire           start;
+reg    [3:0]   rx_bit_cnt;
+reg            rx_go;
+reg    [9:0]   rxr;
+reg            rx_valid, rx_valid_r;
+wire           rx_we;
+wire           rxf_full;
+reg            rts_o;
+reg            txf_empty_r;
+reg            shift_en_r;
+reg            rxd_r1, rxd_r2;
+wire           lock_en;
+reg            change;
+reg            rx_sio_ce_d, rx_sio_ce_r1, rx_sio_ce_r2, rx_sio_ce;
+reg    [1:0]   dpll_state, dpll_next_state;
+reg    [5:0]   rxd_dly; //New input delay used to ensure no baud clocks
+                       // occur twice in one baud period
+///////////////////////////////////////////////////////////////////
+//
+// IO Fifo's
+//
+
+sasc_fifo4 tx_fifo(    .clk(           clk             ),
+                       .rst(           rst && !flush_i ),
+                       .clr(           1'b0            ),
+                       .din(           din_i           ),
+                       .we(            we_i            ),
+                       .dout(          txd_p           ),
+                       .re(            load_e          ),
+                       .full(          full_o          ),
+                       .empty(         txf_empty       )
+                       );
+
+sasc_fifo4 rx_fifo(    .clk(           clk             ),
+                       .rst(           rst && !flush_i ),
+                       .clr(           1'b0            ),
+                       .din(           rxr[9:2]        ),
+                       .we(            rx_we           ),
+                       .dout(          dout_o          ),
+                       .re(            re_i            ),
+                       .full(          rxf_full        ),
+                       .empty(         empty_o         )
+                       );
+
+///////////////////////////////////////////////////////////////////
+//
+// Transmit Logic
+//
+always @(posedge clk)
+       if(!rst)        txf_empty_r <= #1 1'b1;
+       else
+       if(sio_ce)      txf_empty_r <= #1 txf_empty;
+
+always @(posedge clk)
+       load <= #1 !txf_empty_r & !shift_en & !cts_i;
+
+always @(posedge clk)
+       load_r <= #1 load;
+
+assign load_e = load & sio_ce;
+
+always @(posedge clk)
+       if(load_e)              hold_reg <= #1 {STOP_BIT, txd_p, START_BIT};
+       else
+       if(shift_en & sio_ce)   hold_reg <= #1 {IDLE_BIT, hold_reg[9:1]};
+
+always @(posedge clk)
+       if(!rst)                                txd_o <= #1 IDLE_BIT;
+       else
+       if(sio_ce)
+               if(shift_en | shift_en_r)       txd_o <= #1 hold_reg[0];
+               else                            txd_o <= #1 IDLE_BIT;
+
+always @(posedge clk)
+        if(!rst)               tx_bit_cnt <= #1 4'h9;
+       else
+       if(load_e)              tx_bit_cnt <= #1 4'h0;
+       else
+       if(shift_en & sio_ce)   tx_bit_cnt <= #1 tx_bit_cnt + 4'h1;
+
+always @(posedge clk)
+       shift_en <= #1 (tx_bit_cnt != 4'h9);
+
+always @(posedge clk)
+       if(!rst)        shift_en_r <= #1 1'b0;
+       else
+       if(sio_ce)      shift_en_r <= #1 shift_en;
+
+///////////////////////////////////////////////////////////////////
+//
+// Recieve Logic
+//
+
+always @(posedge clk)
+begin
+    rxd_dly[5:1] <= #1 rxd_dly[4:0];
+        rxd_dly[0] <= #1rxd_i;
+        rxd_s <= #1rxd_dly[5];  // rxd_s = delay 1
+    rxd_r <= #1 rxd_s;  // rxd_r = delay 2      
+end
+
+
+assign start = (rxd_r == IDLE_BIT) & (rxd_s == START_BIT);
+
+always @(posedge clk)
+        if(!rst)               rx_bit_cnt <= #1 4'ha;
+       else
+       if(!rx_go & start)      rx_bit_cnt <= #1 4'h0;
+       else
+       if(rx_go & rx_sio_ce)   rx_bit_cnt <= #1 rx_bit_cnt + 4'h1;
+
+always @(posedge clk)
+       rx_go <= #1 (rx_bit_cnt != 4'ha);
+
+assign break_o = break_r;
+always @(posedge clk)
+       rx_valid <= #1 (rx_bit_cnt == 4'h9) && (rxd_s == STOP_BIT);
+always @(posedge clk)
+       break_r  <= #1 (rx_bit_cnt == 4'h9) && (rxr[9:0]==10'b0) && (rxd_dly == 5'b0) && (rxd_s == 0) && (rxd_r == 0);
+
+always @(posedge clk)
+       rx_valid_r <= #1 rx_valid;
+
+assign rx_we = !rx_valid_r & rx_valid & !rxf_full;
+
+always @(posedge clk)
+       if(rx_go & rx_sio_ce)   rxr <= {rxd_s, rxr[9:1]};
+
+always @(posedge clk)
+       rts_o <= #1 rxf_full;
+
+///////////////////////////////////////////////////////////////////
+//
+// Reciever DPLL
+//
+
+// Uses 4x baud clock to lock to incoming stream
+
+// Edge detector
+always @(posedge clk)
+       if(sio_ce_x4)   rxd_r1 <= #1 rxd_s;
+
+always @(posedge clk)
+       if(sio_ce_x4)   rxd_r2 <= #1 rxd_r1;
+
+always @(posedge clk)
+    if(!rst)        
+        change <= #1 1'b0;
+    else if ((rxd_dly[1] != rxd_r1) || (rxd_dly[1] != rxd_s))
+        change <= #1 1'b1;
+    else if(sio_ce_x4)
+        change <= #1 1'b0;
+
+// DPLL FSM
+always @(posedge clk or negedge rst)
+       if(!rst)        dpll_state <= #1 2'h1;
+       else
+       if(sio_ce_x4)   dpll_state <= #1 dpll_next_state;
+
+always @(dpll_state or change)
+   begin
+       rx_sio_ce_d = 1'b0;
+       case(dpll_state)
+          2'h0:
+               if(change)      dpll_next_state = 3'h0;
+               else            dpll_next_state = 3'h1;
+          2'h1:begin
+               rx_sio_ce_d = 1'b1;
+               if(change)      dpll_next_state = 3'h3;
+               else            dpll_next_state = 3'h2;
+               end
+          2'h2:
+               if(change)      dpll_next_state = 3'h0;
+               else            dpll_next_state = 3'h3;
+          2'h3:
+               if(change)      dpll_next_state = 3'h0;
+               else            dpll_next_state = 3'h0;
+       endcase
+   end
+
+// Compensate for sync registers at the input - allign sio 
+// clock enable to be in the middle between two bit changes ...
+always @(posedge clk)
+       rx_sio_ce_r1 <= #1 rx_sio_ce_d;
+
+always @(posedge clk)
+       rx_sio_ce_r2 <= #1 rx_sio_ce_r1;
+
+always @(posedge clk)
+       rx_sio_ce <= #1 rx_sio_ce_r1 & !rx_sio_ce_r2;
+
+endmodule
+
+
diff --git a/src/edu/berkeley/fleet/fpga/mem/wb_vga.v b/src/edu/berkeley/fleet/fpga/mem/wb_vga.v
new file mode 100644 (file)
index 0000000..a70b21b
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * WISHBONE VGA framebuffer
+ * Copyright (C) 2008 Sebastien Bourdeauducq - http://lekernel.net
+ * This file is part of Milkymist.
+ *
+ * Milkymist is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2, 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+module wb_vga(
+       /* Clock and Reset signals are shared between the two buses */
+       input wb_clk_i,
+       input wb_rst_i,
+       
+       /* Wishbone master for reading the framebuffer */
+       output [31:0] fbwb_adr_o,
+       output reg fbwb_stb_o,
+       input fbwb_ack_i,
+       input [31:0] fbwb_dat_i,
+
+       /* Wishbone slave for configuration registers */
+       input [31:0] wb_adr_i,
+       input wb_cyc_i,
+       input wb_stb_i,
+       input wb_we_i,
+       output wb_ack_o,
+       output reg [31:0] wb_dat_o,
+       input [31:0] wb_dat_i,
+
+       /* VGA signals */
+       input vga_clk,
+       output vga_psave,
+       output reg vga_hsync,
+       output reg vga_vsync,
+       output vga_sync,
+       output vga_blank,
+       output reg [7:0] vga_r,
+       output reg [7:0] vga_g,
+       output reg [7:0] vga_b,
+       output vga_clkout
+);
+
+/* Internal state */
+
+/* We need to access at least 640*480 = 307200 words.
+ * 2^19 = 524288
+ */
+reg [21:0] fbaddr;
+reg [21:0] fbaddr_next;
+
+reg hactive;
+reg hactive_next;
+reg [9:0] hcounter;
+reg [9:0] hcounter_next;
+
+reg vactive;
+reg vactive_next;
+reg [9:0] vcounter;
+reg [9:0] vcounter_next;
+
+/* Configuration registers */
+
+reg enable;                    // 00 (0)
+reg enablesync;                        // 04 (1)
+
+reg [29:0] fboffset;           // 08 (2)
+reg [29:0] fboffsetsync;       // 0C (3)
+
+reg [9:0] hres;                        // 10 (4)
+reg [8:0] hblank;              // 14 (5)
+reg [8:0] hsyncmin;            // 18 (6)
+reg [8:0] hsyncmax;            // 1C (7)
+
+reg [9:0] vres;                        // 20 (8)
+reg [8:0] vblank;              // 24 (9)
+reg [8:0] vsyncmin;            // 28 (a)
+reg [8:0] vsyncmax;            // 2C (b)
+
+assign wb_ack_o = wb_cyc_i & wb_stb_i;
+
+always @(posedge wb_clk_i or posedge wb_rst_i) begin
+       if(wb_rst_i) begin
+               enable <= 1;
+               enablesync <= 1;
+               
+               fboffset <= 0;
+               fboffsetsync <= 0;
+               
+               hres <= 639;
+               hblank <= 159;
+               hsyncmin <= 48;
+               hsyncmax <= 143;
+               
+               vres <= 479;
+               vblank <= 43;
+               vsyncmin <= 31;
+               vsyncmax <= 32;
+
+       end else begin
+               if(wb_cyc_i & wb_stb_i & wb_we_i) begin
+                       case(wb_adr_i[5:2])
+                               // enable is READ ONLY
+                               4'h1: enablesync <= wb_dat_i[0];
+                               
+                               // fboffset is READ ONLY
+                               4'h3: fboffsetsync <= wb_dat_i[31:2];
+                               
+                               4'h4: hres <= wb_dat_i[9:0];
+                               4'h5: hblank <= wb_dat_i[8:0];
+                               4'h6: hsyncmin <= wb_dat_i[8:0];
+                               4'h7: hsyncmax <= wb_dat_i[8:0];
+                               
+                               4'h8: vres <= wb_dat_i[9:0];
+                               4'h9: vblank <= wb_dat_i[8:0];
+                               4'ha: vsyncmin <= wb_dat_i[8:0];
+                               4'hb: vsyncmax <= wb_dat_i[8:0];
+                       endcase
+               end
+               /* Update synchronized registers */
+               if((~hactive && ~vactive) || ~enable) begin
+                       fboffset <= fboffsetsync;
+                       enable <= enablesync;
+               end
+       end
+end
+
+always @(wb_adr_i
+       or enable or enablesync
+       or fboffset or fboffsetsync 
+       or hres or hblank or hsyncmin or hsyncmax
+       or vres or vblank or vsyncmin or vsyncmax) begin
+       case(wb_adr_i[5:2])
+               4'h0: wb_dat_o <= {31'b0, enable};
+               4'h1: wb_dat_o <= {31'b0, enablesync};
+
+               4'h2: wb_dat_o <= {fboffset, 2'b00};
+               4'h3: wb_dat_o <= {fboffsetsync, 2'b00};
+               
+               4'h4: wb_dat_o <= {22'b0, hres};
+               4'h5: wb_dat_o <= {23'b0, hblank};
+               4'h6: wb_dat_o <= {23'b0, hsyncmin};
+               4'h7: wb_dat_o <= {23'b0, hsyncmax};
+               
+               4'h8: wb_dat_o <= {22'b0, vres};
+               4'h9: wb_dat_o <= {23'b0, vblank};
+               4'ha: wb_dat_o <= {23'b0, vsyncmin};
+               4'hb: wb_dat_o <= {23'b0, vsyncmax};
+               default: wb_dat_o <= 32'hx;
+       endcase
+end
+
+/* FIFO */
+
+wire [25:0] pixelfifo_dout;
+wire pixelfifo_empty;
+wire pixelfifo_next;
+
+reg [25:0] pixelfifo_din;
+wire pixelfifo_full;
+reg pixelfifo_wr;
+
+async_fifo #(
+       .DATA_WIDTH(26),
+       .ADDRESS_WIDTH(4)
+) pixelfifo (
+       .Data_out(pixelfifo_dout),
+       .Empty_out(pixelfifo_empty),
+       .ReadEn_in(pixelfifo_next),
+       .RClk(vga_clk),
+
+       .Data_in(pixelfifo_din),
+       .Full_out(pixelfifo_full),
+       .WriteEn_in(pixelfifo_wr),
+       .WClk(wb_clk_i),
+       
+       .Clear_in(wb_rst_i)
+);
+
+/* Wishbone master interface and Sequencer */
+
+assign fbwb_adr_o = {{8'b0, fbaddr_next} + fboffset, 2'b00};
+
+always @(posedge wb_clk_i or posedge wb_rst_i) begin
+       if(wb_rst_i) begin
+               hactive <= 0;
+               hcounter <= 0;
+               vactive <= 0;
+               vcounter <= 0;
+               fbaddr <= 0;
+       end else begin
+               if(~enable) begin
+                       hactive <= 0;
+                       hcounter <= 0;
+                       vactive <= 0;
+                       vcounter <= 0;
+                       fbaddr <= 0;
+               end else begin
+                       hactive <= hactive_next;
+                       hcounter <= hcounter_next;
+                       vactive <= vactive_next;
+                       vcounter <= vcounter_next;
+                       fbaddr <= fbaddr_next;
+               end
+       end
+end
+
+always @(hactive or hcounter or vactive or vcounter or hblank or hres or vblank or vres or pixelfifo_full or fbwb_stb_o or fbwb_ack_i) begin
+       if(~pixelfifo_full && (~fbwb_stb_o || fbwb_ack_i)) begin
+               if(hcounter == 0) begin
+                       if(hactive) begin
+                               hactive_next <= 0;
+                               hcounter_next <= hblank; /* horizontal back + front porches */
+                               vactive_next <= vactive;
+                               vcounter_next <= vcounter;
+                       end else begin
+                               hactive_next <= 1;
+                               hcounter_next <= hres; /* horizontal active video */
+                               if(vcounter == 0) begin
+                                       if(vactive) begin
+                                               vactive_next <= 0;
+                                               vcounter_next <= vblank; /* vertical back + front porches */
+                                       end else begin
+                                               vactive_next <= 1;
+                                               vcounter_next <= vres; /* vertical active video */
+                                       end
+                               end else begin
+                                       vactive_next <= vactive;
+                                       vcounter_next <= vcounter - 1;
+                               end
+                       end
+               end else begin
+                       hactive_next <= hactive;
+                       hcounter_next <= hcounter - 1;
+                       vactive_next <= vactive;
+                       vcounter_next <= vcounter;
+               end
+               pixelfifo_wr = 1;
+       end else begin
+               hactive_next <= hactive;
+               hcounter_next <= hcounter;
+               vactive_next <= vactive;
+               vcounter_next <= vcounter;
+               pixelfifo_wr = 0;
+       end
+end
+
+always @(hactive or hcounter or vactive or vcounter or hsyncmin or hsyncmax or vsyncmin or vsyncmax) begin
+       /* HSYNC generator (negative logic) */
+       if(~hactive && (hcounter[8:0] >= hsyncmin) && (hcounter[8:0] <= hsyncmax)) begin
+               pixelfifo_din[24] <= 0;
+       end else begin
+               pixelfifo_din[24] <= 1;
+       end
+
+       /* VSYNC generator (negative logic) */
+       if(~vactive && (vcounter[8:0] >= vsyncmin) && (vcounter[8:0] <= vsyncmax)) begin
+               pixelfifo_din[25] <= 0;
+       end else begin
+               pixelfifo_din[25] <= 1;
+       end
+end
+
+always @(hactive or vactive or pixelfifo_full or fbwb_dat_i or fbwb_ack_i or fbaddr) begin
+       /* Image generator */
+       if(hactive && vactive) begin
+               pixelfifo_din[23:0] <= fbwb_dat_i[23:0];
+               if(~pixelfifo_full) begin
+                       fbwb_stb_o <= 1;
+                       if(fbwb_ack_i)
+                               fbaddr_next <= fbaddr + 1;
+                       else
+                               fbaddr_next <= fbaddr;
+               end else begin
+                       fbwb_stb_o <= 0;
+                       fbaddr_next <= fbaddr;
+               end
+       end else begin
+               /* Blank (porches and sync) */
+               pixelfifo_din[23:0] <= 24'h000000;
+               if(~vactive)
+                       fbaddr_next <= 0;
+               else
+                       fbaddr_next <= fbaddr;
+               fbwb_stb_o <= 0;
+       end
+end
+
+/* VGA signal generation */
+
+assign vga_sync = 0;
+assign vga_psave = 1;
+assign vga_blank = 1;
+
+assign vga_clkout = vga_clk;
+
+assign pixelfifo_next = 1;
+
+/* We register everything to avoid glitches on the outputs,
+ * especially on sync signals */
+
+always @(posedge vga_clk) begin
+       vga_vsync <= pixelfifo_dout[25];
+       vga_hsync <= pixelfifo_dout[24];
+       vga_r <= pixelfifo_dout[23:16];
+       vga_g <= pixelfifo_dout[15:8];
+       vga_b <= pixelfifo_dout[7:0];
+end
+
+endmodule
+
diff --git a/src/edu/berkeley/fleet/fpga/ramfifo.inc b/src/edu/berkeley/fleet/fpga/ramfifo.inc
new file mode 100644 (file)
index 0000000..ae7e394
--- /dev/null
@@ -0,0 +1,100 @@
+module `MODULE_NAME(clk, rst, 
+               in_r, in_a_, in_d,
+               out_r_, out_a, out_d_); 
+    input  clk;
+    input  rst; 
+    input  in_r;
+    output in_a_;
+    output out_r_;
+    input  out_a;
+    input  [(`WIDTH-1):0] in_d;
+    output [(`WIDTH-1):0] out_d_;
+
+    reg in_a;
+    reg out_r;
+    assign in_a_ = in_a;
+    assign out_r_ = out_r;
+
+    wire[((1<<(`ADDR_BITS))-1):0] controlx;
+    reg[((1<<(`ADDR_BITS))-1):0] control;
+    initial control = 0;
+
+    genvar i;
+    generate
+      if (`ADDR_BITS > 1) begin: OUT
+      for(i=1; i<=((1<<`ADDR_BITS)-2) ; i=i+1) begin : OUT
+        assign controlx[i] =
+           ( control[i-1] && !control[i]                 ) ? 1 :
+           (                  control[i] && !control[i+1]) ? 0 :
+           control[i];
+      end
+      end
+    endgenerate
+
+    reg[3:0] addr;
+    initial  addr = 4'b1111;
+
+    reg inchead;
+    reg inctail;
+    reg[3:0] count;
+
+    genvar j;
+    generate
+      for(j=0; j<`WIDTH ; j=j+1) begin : OUTX
+         SRL16E SRL16E (.Q (out_d_[j]),
+                        .A0 (addr[0]),
+                        .A1 (addr[1]),
+                        .A2 (addr[2]),
+                        .A3 (addr[3]),
+                        .CE (in_r && !in_a && !control[0] && count==0),
+                        .CLK (clk),
+                        .D (in_d[j]));
+         defparam SRL16E.INIT = 0;
+      end
+    endgenerate
+
+    assign controlx[(1<<`ADDR_BITS)-1] =
+        !control[(1<<`ADDR_BITS)-1] ? control[(1<<`ADDR_BITS)-2] : (!out_r && !out_a) ? 0 : control[(1<<`ADDR_BITS)-1];
+
+    always @(posedge clk) begin 
+        if (rst) begin
+          out_r <= 0;
+          in_a <= 0;
+          control <= 0;
+          addr <= 4'b1111;
+
+        end else if (count!=0) begin
+          count <= count-1;
+
+        end else begin
+
+          count <= `DELAY;
+
+          inchead = 0;
+          inctail = 0;
+          if (!in_r && in_a) in_a <= 0;
+          if (control[0]) begin
+             if (!control[1]) control[0] <= 0;
+          end else if (in_r && !in_a) begin
+            control[0] <= 1;
+            inctail = 1;
+            in_a <= 1;
+          end
+  
+          control[(1<<`ADDR_BITS)-1:1] <= controlx[(1<<`ADDR_BITS)-1:1];
+  
+          if (control[(1<<`ADDR_BITS)-1] && !out_r && !out_a) begin
+            out_r <= 1;
+          end
+          if (out_r && out_a) begin
+            out_r <= 0;
+            inchead = 1;
+          end
+          if (          inchead && !inctail) begin
+            addr <= addr-1;
+          end else if (!inchead &&  inctail) begin
+            addr <= addr+1;
+          end
+      end
+    end
+endmodule 
diff --git a/src/edu/berkeley/fleet/fpga/verilog/Verilog.java b/src/edu/berkeley/fleet/fpga/verilog/Verilog.java
new file mode 100644 (file)
index 0000000..2913416
--- /dev/null
@@ -0,0 +1,766 @@
+package edu.berkeley.fleet.fpga.verilog;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.util.*;
+import edu.berkeley.fleet.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.io.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+
+/*
+
+- ideally: want to merge Fpga.dump() with this... but have to resolve
+  the handling of flushing first.
+
+- eliminate uses of SimpleXXX
+   - force width parameter in remaining uses
+   - re-enable width checking (add zero-extend and sign-extend)
+
+- ideally: make getVerilog() package-private somehow
+
+- change Event constructors from Object[] to Event[]/Action[]
+- change portorder to LinkedHashMap
+
+=> mangle the names given for strings
+=> ensure uniquification of percolated ports
+
+=> later: scan chain
+*/
+
+/**
+ *  Among the benefits are:
+ *    - automatic scan-chain insertion
+ *    - better error-checking (for example, width mismatches) than Verilog provides
+ *    - pin percolation
+ *
+ *  One of the most annoying things about Verilog is that you cannot
+ *  "double-slice" a value; in other words, foo[10:2] is valid
+ *  Verilog, but foo[10:2][4:3] is not; the programmer must write
+ *  foo[4+2:3+2].  This lack of compositionality is the reason for
+ *  most of the complexity in the Value class.
+ */
+public class Verilog {
+
+    public static final int FORWARD_LATENCY = 6;  // must be >=1
+    public static final int REVERSE_LATENCY = 4;  // must be >=3
+
+    public static interface Value {
+        public String  getVerilog();
+        public Value   getBits(int high, int low);
+        public Value   getBits(Mask mask);
+        public Trigger testMask(Mask mask);
+        public Value   invertBits();
+        public int     getWidth();
+    }
+
+    public static class SimpleValue implements Value {
+        public final String s;
+        private final String s0;
+        private final int high;
+        private final int low;
+        private final int width;
+        public SimpleValue(String s) { this(s, -1); }
+        public SimpleValue(String s, int width) {
+            this.s = s;
+            this.s0 = s;
+            this.high = -1;
+            this.low = -1;
+            this.width = width;
+        }
+        public SimpleValue(String s, int high, int low) {
+            this.s = s+"["+high+":"+low+"]";
+            this.s0 = s;
+            this.high = high;
+            this.low = low;
+            this.width = 1+high-low;
+        }
+        public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+        public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+        public Value getBits(int high, int low) {
+            if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low);
+            if (high+this.low > this.high) throw new RuntimeException("out of range");
+            return new SimpleValue(s0, high+this.low, low+this.low);
+        }
+        public String getVerilog() { return s; }
+        public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); }
+        public int getWidth() {
+            if (width==-1) throw new RuntimeException("not implemented");
+            return width;
+        }
+    }
+
+    public static class MuxValue implements Value {
+        private final Trigger sel;
+        private final Value if0;
+        private final Value if1;
+        public MuxValue(Trigger sel, Value if1, Value if0) {
+            this.sel = sel;
+            this.if0 = if0;
+            this.if1 = if1;
+            if (if0.getWidth() != if1.getWidth())
+                throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth());
+        }
+        public int getWidth() { return if0.getWidth(); }
+        public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; }
+        public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); }
+        public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); }
+        public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); }
+        public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+    }
+
+    public static class ConstantValue implements Value {
+        private final BitVector bits;
+        public ConstantValue(BitVector bits) { this.bits = bits; }
+        public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); }
+        public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); }
+        public Value invertBits() {
+            BitVector ret = new BitVector(bits.length());
+            for(int i=0; i<bits.length(); i++) ret.set(i, !bits.get(i));
+            return new ConstantValue(ret);
+        }
+        public String getVerilog() {
+            StringBuffer sb = new StringBuffer();
+            sb.append(bits.length());
+            sb.append("'b");
+            for(int i=bits.length()-1; i>=0; i--)
+                sb.append(bits.get(i) ? '1' : '0');
+            return sb.toString();
+        }
+        public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+        public int getWidth() { return bits.length(); }
+    }
+
+    public static class CatValue implements Value {
+        private final Value[] values;
+        public CatValue(Value[] values) { this.values = values; }
+        public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+        public Value getBits(int high, int low) { throw new RuntimeException(); }
+        public int getWidth() {
+            int ret = 0;
+            for (Value val : values) ret += val.getWidth();
+            return ret;
+        }
+        public String getVerilog() {
+            StringBuffer sb = new StringBuffer();
+            sb.append("{ ");
+            boolean first = true;
+            for(int i=0; i<values.length; i++) {
+                if (values[i]==null) continue;
+                if (!first) sb.append(", ");
+                sb.append(values[i].getVerilog());
+                first = false;
+            }
+            sb.append(" }");
+            return sb.toString();
+        }
+        public Value invertBits() {
+            Value[] newvals = new Value[values.length];
+            for(int i=0; i<values.length; i++)
+                newvals[i] = values[i].invertBits();
+            return new CatValue(newvals);
+        }
+        public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+    }
+
+    public static class LogicValue implements Value {
+        public static enum LogicType { OR, AND };
+        private final Value v1;
+        private final Value v2;
+        private final LogicType tt;
+        public LogicValue(Value v1, LogicType tt, Value v2) {
+            this.v1 = v1;
+            this.v2 = v2;
+            this.tt = tt;
+            // FIXME: check width match
+        }
+        public String  getVerilog() {
+            switch(tt) {
+                case OR:  return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
+                case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
+            }
+            throw new RuntimeException("impossible");
+        }
+        public Value   getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
+        public Value   getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
+        public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
+        public Value   invertBits() { 
+            switch(tt) {
+                case OR:  return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
+                case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
+            }
+            throw new RuntimeException("impossible");
+        }
+        public int     getWidth() { return v1.getWidth(); }
+    }
+
+    public static class TestValue implements Value, Trigger {
+        public static enum TestType { NE, EQ, LT, GT, LE, GE };
+        private final Value v1;
+        private final Value v2;
+        private final TestType tt;
+        public TestValue(Value v1, TestType tt, Value v2) {
+            this.v1 = v1;
+            this.v2 = v2;
+            this.tt = tt;
+            // FIXME: check width match
+        }
+        public String  getVerilogTrigger() { return getVerilog(); }
+        public String  getVerilog() {
+            switch(tt) {
+                case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
+                case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
+                case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
+                case GE: return "("+v1.getVerilog()+">="+v2.getVerilog()+")";
+                case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")";
+                case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")";
+            }
+            throw new RuntimeException("impossible");
+        }
+        public Value   getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); }
+        public Value   getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
+        public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
+        public Trigger invert() { return invertMe(); }
+        public Value   invertBits() { return invertMe(); }
+        private TestValue invertMe() {
+            switch(tt) {
+                case NE: return new TestValue(v1, TestType.EQ, v2);
+                case EQ: return new TestValue(v1, TestType.NE, v2);
+                case LE: return new TestValue(v1, TestType.GT, v2);
+                case GE: return new TestValue(v1, TestType.LT, v2);
+                case LT: return new TestValue(v1, TestType.GE, v2);
+                case GT: return new TestValue(v1, TestType.LE, v2);
+            }
+            throw new RuntimeException("impossible");
+        }
+        public int     getWidth() { return 1; }
+    }
+
+    // Triggers //////////////////////////////////////////////////////////////////////////////
+
+    public static interface Trigger {
+        public String getVerilogTrigger();
+        public Trigger invert();
+    }
+
+    public static class SimpleTrigger implements Trigger {
+        private final String s;
+        public SimpleTrigger(String s) { this.s = s; }
+        public String getVerilogTrigger() { return s; }
+        public Trigger invert() { return new SimpleTrigger("!("+s+")"); }
+    }
+
+    public static class AndTrigger implements Trigger {
+        private final Trigger t1, t2;
+        public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
+        public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; }
+        public Trigger invert() { return new InvertedTrigger(this); }
+    }
+
+    public static class OrTrigger implements Trigger {
+        private final Trigger t1, t2;
+        public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
+        public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; }
+        public Trigger invert() { return new InvertedTrigger(this); }
+    }
+
+    public static class InvertedTrigger implements Trigger {
+        private final Trigger original;
+        public InvertedTrigger(Trigger original) { this.original = original; }
+        public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
+        public Trigger invert() { return original; }
+    }
+
+    public static class ConditionalTrigger implements Trigger {
+        public Trigger condition;
+        public Trigger trigger;
+        public ConditionalTrigger(Trigger condition, Trigger trigger) {
+            this.condition = condition;
+            this.trigger = trigger;
+        }
+        public String getVerilogTrigger() {
+            return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)";
+        }
+        public Trigger invert() { return new InvertedTrigger(this); }
+    }
+
+    // Actions //////////////////////////////////////////////////////////////////////////////
+
+    public static interface Action {
+        public String getVerilogAction();
+    }
+
+    public static class ConditionalAction implements Action {
+        public Trigger condition;
+        public Action action;
+        public ConditionalAction(Trigger condition, Action action) {
+            this.condition = condition;
+            this.action = action;
+        }
+        public String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; }
+    }
+
+    public static class AssignAction implements Action {
+        public Assignable left;
+        public Value right;
+        public AssignAction(Assignable left, Value right) {
+            this.left = left;
+            this.right = right;
+        }
+        public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; }
+    }
+
+    // Assignables //////////////////////////////////////////////////////////////////////////////
+
+    public static interface Assignable {
+        public String getVerilog();
+    }
+
+    public static class SimpleAssignable implements Assignable {
+        public final String s;
+        public SimpleAssignable(String s) { this.s = s; }
+        public String getVerilog() { return s; }
+    }
+
+    // Module Internals //////////////////////////////////////////////////////////////////////////////
+
+    public static class Module {
+        public void dump(String prefix) throws IOException {
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+            dump(pw, true);
+            pw.flush();
+            for(InstantiatedModule m : instantiatedModules)
+                m.module.dump(prefix);
+        }
+        public int id = 0;
+        public final String name;
+        public String getName() { return name; }
+        public Port getPort(String name) { return ports.get(name); }
+
+        // order matters here
+        public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
+
+        // order matters here
+        public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
+        public final ArrayList<Event> events = new ArrayList<Event>();
+
+        // FIXME: always-alphabetical convention?
+        public final HashMap<String,Port> ports = new HashMap<String,Port>();
+        public final ArrayList<String> portorder = new ArrayList<String>();
+        public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
+        public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
+        public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
+        
+        public Module(String name) { this.name = name; }
+
+        public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
+        public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
+
+        // Latches and Wires //////////////////////////////////////////////////////////////////////////////
+
+        public class StateWire {
+            public final String name;
+            public final boolean initiallyFull;
+            public String getName() { return name; }
+            public Trigger isFull()  { return new SimpleTrigger("("+name+"==1)"); }
+            public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
+            public Action  doFill()  { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
+            public Action  doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
+            public String  getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
+            public StateWire(String name) { this(name, false); }
+            public StateWire(String name, boolean initiallyFull) {
+                this.name = name;
+                this.initiallyFull = initiallyFull;
+                statewires.put(name, this);
+            }
+            public void dump(PrintWriter pw) {
+                pw.println("  reg "+name+";");
+                pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
+            }
+        }
+
+        public class Latch implements Assignable, Value {
+            public final String name;
+            public final int width;
+            public final long initial;
+            public Latch(String name, int width) { this(name, width, 0); }
+            public Latch(String name, int width, long initial) {
+                this.width = width;
+                this.name = name;
+                this.initial = initial;
+                latches.put(name, this);
+            }
+            public int getWidth() { return width; }
+            public String getVerilog() { return name; }
+            public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
+            public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+            public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+            public String getResetCode() { return name+"<="+initial+";"; }
+            public void dump(PrintWriter pw) {
+                pw.println("  reg ["+(width-1)+":0] "+name+";");
+                pw.println("  initial "+name+"="+initial+";");
+            }
+            public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }        
+        }
+
+        public class WireValue implements Value {
+            public final String name;
+            public final int width;
+            public final Value assign;
+            public WireValue(String name, int width, Value assign) {
+                this.width = width;
+                this.name = name;
+                this.assign = assign;
+                wires.put(name, this);
+            }
+            public int getWidth() { return width; }
+            public String getVerilog() { return name; }
+            public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
+            public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+            public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+            public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }        
+            public void dump(PrintWriter pw) { pw.println("  wire ["+(width-1)+":0] "+name+";"); }
+            public String getAssignments() { return "  assign "+name+" = "+assign.getVerilog()+";"; }
+        }
+
+        // Ports //////////////////////////////////////////////////////////////////////////////
+
+        public abstract class Port implements Action, Trigger {
+            final String name;
+            final int width;
+            final boolean external;
+            public Port(String name, int width, boolean external) {
+                this.width = width;
+                this.name = name;
+                this.external = external;
+                if (ports.get(name)!=null)
+                    throw new RuntimeException("port "+name+" already exists");
+                ports.put(name, this);
+                if (external)
+                    portorder.add(name);
+            }
+            public String getName() { return name; }
+            public int getWidth() { return width; }
+            public String getVerilog() { return name; }
+            String getAck() { return name+"_a"; }
+            String getReq() { return name+"_r"; }
+            public String isFull() { return "("+getReq()+" && !"+getAck()+")"; }
+            public abstract String getResetCode();
+            public abstract String getInterface();
+            public abstract String getSimpleInterface();
+            public abstract String getDeclaration();
+            public abstract String getAssignments();
+            public abstract String getCleanup();
+            public Trigger invert() { return new InvertedTrigger(this); }
+            public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+        }
+
+        public class SourcePort extends Port implements Value {
+            private SinkPort driven = null;
+            public SourcePort(String name, int width, boolean external) { super(name, width, external); }
+            public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
+            public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+            public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+            public String getVerilogTrigger() { return getReq() + " && !"+getAck(); }
+            public String getVerilogAction() { return getAck() + " <= 1;"; }
+            public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
+            public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
+            public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
+            public String getDeclaration() {
+                StringBuffer sb = new StringBuffer();
+                if (external) {
+                    sb.append("input "  +                           name +"_r;\n");
+                    sb.append("output " +                           name +"_a_;\n");
+                    sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
+                } else {
+                    sb.append("wire "  +                            name +"_r;\n");
+                    sb.append("wire ["+Math.max(0,width-1)+":0]"  + name +";\n");
+                }
+                if (driven!=null) {
+                    sb.append("wire "    +                 name +"_a;\n");
+                } else {
+                    sb.append("reg "    +                  name +"_a;\n");
+                    sb.append("initial " +                 name +"_a = 0;\n");
+                }
+                return sb.toString();
+            }
+            public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
+            public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
+            public String getAssignments() {
+                StringBuffer sb = new StringBuffer();
+                if (external) {
+                    int a = REVERSE_LATENCY - 3;
+                    if (a<0 || a>16) {
+                        throw new RuntimeException("cannot offer latency of " + REVERSE_LATENCY +"-3");
+                    } else if (a==0) {
+                        sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
+                    } else {
+                        a = a-1;  // CLK-to-Q gives us one cycle of latency anyways
+                        sb.append("SRL16E srl16_"+name+"_a\n");
+                        sb.append("              (.Q ("+name+"_a_),\n");
+                        sb.append("               .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .CE (1),\n");
+                        sb.append("               .CLK (clk),\n");
+                        sb.append("               .D ("+name+"_a));\n");
+                    }
+                }
+                return sb.toString();
+            }
+            public void connect(SinkPort driven) {
+                if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
+                if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
+                if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
+                this.driven = driven;
+                driven.controlDriver = this;
+                driven.latchDriver = this;
+                // FIXME
+                // if (getWidth() != driven.getWidth())
+                // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
+            }
+        }
+        
+        public class SinkPort extends Port implements Assignable {
+            SourcePort controlDriver = null;
+            Value latchDriver = null;
+            public SinkPort(String name, int width, boolean external) { super(name, width, external); }
+            public String getVerilogAction() { return getReq() + " <= 1;"; }
+            public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
+            public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
+            public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
+            public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
+            public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
+            public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
+            public void connectControl(SourcePort controlDriver) {
+                if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
+                this.controlDriver = controlDriver;
+            }
+            public void connectValue(Value val) {
+                //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
+                this.latchDriver = val;
+                // FIXME
+                //if (getWidth() != val.getWidth())
+                //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
+            }
+            public String getDeclaration() {
+                StringBuffer sb = new StringBuffer();
+                if (external) {
+                    sb.append("output "  +                           name +"_r_;\n");
+                    sb.append("input "   +                           name +"_a;\n");
+                    sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
+                } else {
+                    sb.append("wire "   +                 name +"_a;\n");
+                }
+                if (controlDriver!=null) {
+                    sb.append("wire "    +                 name +"_r;\n");
+                    sb.append("wire   ["+Math.max(0,width-1)+":0]" + name +";\n");
+                } else {
+                    sb.append("reg "    +                  name +"_r;\n");
+                    sb.append("initial " +                 name +"_r = 0;\n");
+                    if (latchDriver!=null) sb.append("wire   ["+Math.max(0,width-1)+":0]" + name +";\n");
+                    else                   sb.append("reg    ["+Math.max(0,width-1)+":0]" + name +";\n");
+                }
+                return sb.toString();
+            }
+            public String getAssignments() {
+                StringBuffer sb = new StringBuffer();
+                if (external) {
+                    int a = FORWARD_LATENCY - 1;
+                    if (a<0 || a>16) {
+                        throw new RuntimeException("cannot offer latency of " + FORWARD_LATENCY +"-1");
+                    } else if (a==0) {
+                        sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
+                    } else {
+                        a = a-1;  // CLK-to-Q gives us one cycle of latency anyways
+                        sb.append("SRL16E srl16_"+name+"_r\n");
+                        sb.append("              (.Q ("+name+"_r_),\n");
+                        sb.append("               .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .CE (1),\n");
+                        sb.append("               .CLK (clk),\n");
+                        sb.append("               .D ("+name+"_r));\n");
+                    }
+                    sb.append("assign " +                  name +"_ = " + name + ";\n");
+                }
+                if (controlDriver != null) {
+                    sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
+                    sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
+                    if (latchDriver==null)
+                        sb.append("assign " + name +"   = " + controlDriver.name + ";\n");
+                }
+                if (latchDriver != null)
+                    sb.append("assign " + name +"   = " + latchDriver.getVerilog() + ";\n");
+                return sb.toString();
+            }
+        }
+
+        // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
+
+        public static class InstantiatedModule {
+            public final Module module;
+            public final Module thisModule;
+            public final int id;
+            public final HashMap<String,Port> ports = new HashMap<String,Port>();
+            public String getName() { return module.getName()+"_"+id; }
+            public InstantiatedModule(Module thisModule, Module module) {
+                this.thisModule = thisModule;
+                this.module = module;
+                // CRUDE
+                int id = 0;
+                OUTER: while(true) {
+                    for (InstantiatedModule im : thisModule.instantiatedModules)
+                        if (im.getName().equals(module.getName()+"_"+id)) {
+                            id++;
+                            continue OUTER;
+                        }
+                    break;
+                }
+                this.id = id;
+                thisModule.instantiatedModules.add(this);
+                for(String s : module.portorder)
+                    getPort(s);
+            }
+            public void dump(PrintWriter pw) {
+                pw.println("  " + module.getName() + " " + getName() + "(clk, rst ");
+                for(String s : module.portorder)
+                    pw.println(", " + getPort(s).getSimpleInterface());
+                for(PercolatedPort pp : module.percolatedPorts)
+                    pw.println("    , "+pp.name);
+                pw.println("   );");
+            }
+            public Port getPort(String name) {
+                return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
+            }
+            public SinkPort getInputPort(String name) {
+                int width = module.getPort(name).getWidth();
+                SinkPort port = (SinkPort)ports.get(name);
+                if (port == null) {
+                    port = thisModule.new SinkPort(getName()+"_"+name, width, false);
+                    ports.put(name, port);
+                }
+                return port;
+            }
+            public SourcePort getOutputPort(String name) {
+                int width = module.getPort(name).getWidth();
+                SourcePort port = (SourcePort)ports.get(name);
+                if (port == null) {
+                    port = thisModule.new SourcePort(getName()+"_"+name, width, false);
+                    ports.put(name, port);
+                }
+                return port;
+            }
+        }
+
+        public void dump(PrintWriter pw, boolean fix) {
+                if (!fix) throw new RuntimeException();
+            boolean isRoot = name.equals("main");
+            pw.print("module "+name);
+            pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst ");
+            for(String name : portorder) pw.println("    , " + ports.get(name).getInterface());
+            for (InstantiatedModule im : this.instantiatedModules)
+                for(PercolatedPort pp : im.module.percolatedPorts)
+                    if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
+                        pw.println("    , "+pp.name);
+            pw.println("   );");
+            pw.println();
+
+            if (isRoot) {
+                pw.println("  input clk_pin;");
+                pw.println("  input rst_pin;");
+                pw.println("  wire clk;");
+                pw.println("  wire clk_fb;");
+                pw.println("  wire clk_unbuffered;");
+                pw.println("  assign clk_unbuffered = clk_pin;");
+                //pw.println("  assign clk = clk_pin;");
+
+                pw.println("  BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
+                /*
+                pw.println("  DCM");
+                pw.println("   #(");
+                pw.println("      .CLKFX_MULTIPLY(4),");
+                pw.println("      .CLKFX_DIVIDE(8),");
+                pw.println("      .CLKIN_PERIOD(\"10 ns\")");
+                pw.println("    ) mydcm(");
+                pw.println("      .CLKIN (clk_pin),");
+                pw.println("      .CLKFB(clk_fb),");
+                pw.println("      .CLKFX (clk_unbuffered),");
+                pw.println("      .CLK0  (clk_fb)");
+                pw.println("    );");
+                */
+                pw.println("  wire rst;");
+            } else {
+                pw.println("    input clk;");
+                pw.println("    input rst;");
+            }
+
+            for (InstantiatedModule im : this.instantiatedModules)
+                for(PercolatedPort pp : im.module.percolatedPorts) {
+                    if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
+                        pw.print("wire");
+                    else  switch(pp.type) {
+                            case UP:    pw.print("output"); break;
+                            case DOWN:  pw.print("input");  break;
+                            case INOUT: pw.print("inout");  break;
+                        }
+                    pw.print("  ");
+                    if (pp.width > 1)
+                        pw.print("["+(pp.width-1)+":0]");
+                    pw.print(" ");
+                    pw.print(pp.name);
+                    pw.println(";");
+                }
+
+            if (isRoot) {
+                pw.println("  assign rst    = rst_out;");
+                pw.println("  assign rst_in = !rst_pin;");
+            }
+
+            for(String name : ports.keySet()) pw.println("    " + ports.get(name).getDeclaration());
+            for(StateWire sw : statewires.values()) sw.dump(pw);
+            for(Latch l : latches.values()) l.dump(pw);
+            for(WireValue wv : wires.values()) wv.dump(pw);
+            for(String name : ports.keySet()) pw.println("    " + ports.get(name).getAssignments());
+            for(WireValue wv : wires.values()) pw.println("    " + wv.getAssignments());
+            for(InstantiatedModule m : instantiatedModules) m.dump(pw);
+            pw.println("always @(posedge clk) begin");
+            pw.println("  if (rst) begin");
+            for(Latch l : latches.values()) pw.println(l.getResetCode());
+            for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
+            for(Port p : ports.values()) pw.println(p.getResetCode());
+            pw.println("  end else begin");
+            for(Port p : ports.values()) pw.println(p.getCleanup());
+            for(Event a : events) a.dump(pw, fix);
+            pw.println("    begin end");
+            pw.println("    end");
+            pw.println("  end");
+            pw.println("endmodule");
+        }
+
+        public class Event {
+            public Object[]  triggers;
+            public Object[]  actions;
+            public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
+            public Event(Object[] triggers, Object[] actions) {
+                Module.this.events.add(this);
+                this.triggers = triggers;
+                this.actions = actions;
+            }
+            public void dump(PrintWriter pw, boolean fix) {
+                if (!fix) throw new RuntimeException();
+                pw.print("if (1");
+                for(Object o : triggers) {
+                    if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
+                    else                      pw.print(" && " + o);
+                }
+                pw.println(") begin ");
+                for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
+                if (fix) pw.println("end /*else*/ ");
+                else     pw.println("end else ");
+            }
+        }
+    }
+}
diff --git a/src/edu/berkeley/fleet/fpga/zbt/zbt_top.vhd b/src/edu/berkeley/fleet/fpga/zbt/zbt_top.vhd
new file mode 100644 (file)
index 0000000..29115a5
--- /dev/null
@@ -0,0 +1,546 @@
+----------------------------------------------------------------------------------
+-- Company:       VISENGI S.L. (www.visengi.com) - URJC FRAV Group (www.frav.es)
+-- Engineer:      Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com)
+-- 
+-- Create Date:    12:39:50 06-Oct-2008 
+-- Project Name:   ZBT SRAM WISHBONE Controller
+-- Target Devices: Xilinx ML506 board
+-- Tool versions:  Xilinx ISE 9.2i
+-- Description: This is a ZBT SRAM controller which is Wishbone rev B.3 compatible (classic + burst r/w operations).
+--
+-- Dependencies: It may be run on any board/FPGA with a ZBT SRAM pin compatible (or at least in the control signals)
+--          with the one on the ML506 board (ISSI IS61NLP 256kx36 ZBT SRAM)
+--
+--
+-- LICENSE TERMS: (CCPL) Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported.
+--          http://creativecommons.org/licenses/by-nc-sa/3.0/
+--
+--     That is you may use it only in NON-COMMERCIAL projects.
+--     You are required to include in the copyrights/about section 
+--     that your system contains a "ZBT SRAM Controller (C) Victor Lopez Lorenzo under CCPL license"
+--     This holds also in the case where you modify the core, as the resulting core
+--     would be a derived work.
+--     Also, we would like to know if you use this core in a project of yours, just an email will do.
+--
+--    Please take good note of the disclaimer section of the CCPL license, as we don't
+--    take any responsability for anything that this core does.
+----------------------------------------------------------------------------------
+
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+-- WB: MASTER MUST NOT insert wait states!
+-- WB: maximum burst length is 4 (but bursts may follow without wait states in between)
+
+entity zbt_top is
+    Port (  clk : in STD_LOGIC;
+            reset : in STD_LOGIC;
+
+            SRAM_CLK : out STD_LOGIC; --Synchronous Clock (up to 200 MHz)
+
+            --A burst mode pin (MODE) defines the order of the burst sequence. When tied HIGH, the interleaved burst sequence is selected.
+            --When tied LOW, the linear burst sequence is selected.
+            SRAM_MODE : out STD_LOGIC; --Burst Sequence Selection (pulled down on PCB)
+            
+            SRAM_CS_B : out STD_LOGIC; --Synchronous Chip Enable (CE\, pulled up on PCB)
+            
+            --For write cycles following read cycles, the output buffers must be disabled with OE\, otherwise data bus contention will occur
+            SRAM_OE_B : out STD_LOGIC; --Output Enable (OE\, pulled up on PCB)
+            
+            --Write cycles are internally self-timed and are initiated by the rising edge of the clock inputs and when WE\ is LOW.
+            SRAM_FLASH_WE_B : out STD_LOGIC; --Synchronous Read/Write Control Input (pulled up on PCB)
+            
+            --All Read, Write and Deselect cycles are initiated by the ADV input. When the ADV input is HIGH the internal
+            --burst counter is incremented. New external addresses can be loaded when ADV is LOW.
+            SRAM_ADV_LD_B : out STD_LOGIC; --Synchronous Burst Address Advance/Load (pulled down on PCB)
+
+
+            SRAM_BW0 : out STD_LOGIC; --Synchronous Byte Write Enable 0 (active low)
+            SRAM_BW1 : out STD_LOGIC; --Synchronous Byte Write Enable 1 (active low)
+            SRAM_BW2 : out STD_LOGIC; --Synchronous Byte Write Enable 2 (active low)
+            SRAM_BW3 : out STD_LOGIC; --Synchronous Byte Write Enable 3 (active low)
+            
+            --SRAM_FLASH_A0 : out STD_LOGIC; --not connected to SRAM!
+            SRAM_FLASH_A1 : out STD_LOGIC; --Synchronous Address Input 0
+            SRAM_FLASH_A2 : out STD_LOGIC; --Synchronous Address Input 1
+            SRAM_FLASH_A3 : out STD_LOGIC;
+            SRAM_FLASH_A4 : out STD_LOGIC;
+            SRAM_FLASH_A5 : out STD_LOGIC;
+            SRAM_FLASH_A6 : out STD_LOGIC;
+            SRAM_FLASH_A7 : out STD_LOGIC;
+            SRAM_FLASH_A8 : out STD_LOGIC;
+            SRAM_FLASH_A9 : out STD_LOGIC;
+            SRAM_FLASH_A10 : out STD_LOGIC;
+            SRAM_FLASH_A11 : out STD_LOGIC;
+            SRAM_FLASH_A12 : out STD_LOGIC;
+            SRAM_FLASH_A13 : out STD_LOGIC;
+            SRAM_FLASH_A14 : out STD_LOGIC;
+            SRAM_FLASH_A15 : out STD_LOGIC;
+            SRAM_FLASH_A16 : out STD_LOGIC;
+            SRAM_FLASH_A17 : out STD_LOGIC;
+            SRAM_FLASH_A18 : out STD_LOGIC;
+            
+            SRAM_FLASH_D0 : inout STD_LOGIC;
+            SRAM_FLASH_D1 : inout STD_LOGIC;
+            SRAM_FLASH_D2 : inout STD_LOGIC;
+            SRAM_FLASH_D3 : inout STD_LOGIC;
+            SRAM_FLASH_D4 : inout STD_LOGIC;
+            SRAM_FLASH_D5 : inout STD_LOGIC;
+            SRAM_FLASH_D6 : inout STD_LOGIC;
+            SRAM_FLASH_D7 : inout STD_LOGIC;
+            SRAM_FLASH_D8 : inout STD_LOGIC;
+            SRAM_FLASH_D9 : inout STD_LOGIC;
+            SRAM_FLASH_D10 : inout STD_LOGIC;
+            SRAM_FLASH_D11 : inout STD_LOGIC;
+            SRAM_FLASH_D12 : inout STD_LOGIC;
+            SRAM_FLASH_D13 : inout STD_LOGIC;
+            SRAM_FLASH_D14 : inout STD_LOGIC;
+            SRAM_FLASH_D15 : inout STD_LOGIC;
+            SRAM_D16 : inout STD_LOGIC;
+            SRAM_D17 : inout STD_LOGIC;
+            SRAM_D18 : inout STD_LOGIC;
+            SRAM_D19 : inout STD_LOGIC;
+            SRAM_D20 : inout STD_LOGIC;
+            SRAM_D21 : inout STD_LOGIC;
+            SRAM_D22 : inout STD_LOGIC;
+            SRAM_D23 : inout STD_LOGIC;
+            SRAM_D24 : inout STD_LOGIC;
+            SRAM_D25 : inout STD_LOGIC;
+            SRAM_D26 : inout STD_LOGIC;
+            SRAM_D27 : inout STD_LOGIC;
+            SRAM_D28 : inout STD_LOGIC;
+            SRAM_D29 : inout STD_LOGIC;
+            SRAM_D30 : inout STD_LOGIC;
+            SRAM_D31 : inout STD_LOGIC;
+
+            SRAM_DQP0 : inout STD_LOGIC; --Parity Data I/O 0
+            SRAM_DQP1 : inout STD_LOGIC; --Parity Data I/O 1
+            SRAM_DQP2 : inout STD_LOGIC; --Parity Data I/O 2
+            SRAM_DQP3 : inout STD_LOGIC; --Parity Data I/O 3
+            
+           
+
+            wb_adr_i : in std_logic_vector(17 downto 0);
+            wb_we_i : in std_logic;
+            wb_dat_i : in std_logic_vector(35 downto 0);
+            wb_sel_i : in std_logic_vector(3 downto 0);
+            wb_dat_o : out std_logic_vector(35 downto 0);
+            wb_cyc_i : in std_logic;
+            wb_stb_i : in std_logic;
+            wb_cti_i : in std_logic_vector(2 downto 0);
+            wb_bte_i : in std_logic_vector(1 downto 0);
+            wb_ack_o : out std_logic;
+            wb_err_o : out std_logic;
+            wb_tga_i: in std_logic := '0' --'0' to mean last (or single) 4 words burst
+           
+           );
+end zbt_top;
+
+architecture Behavioral of zbt_top is
+   signal ZBT_addr, ZBT_addr2  : std_logic_vector(17 downto 0);
+   signal ZBT_din, ZBT_din2, ZBT_din1 : std_logic_vector(35 downto 0);
+   signal ZBT_dout : std_logic_vector(35 downto 0);
+   signal BW_enable, SRAM_OE_B2 : std_logic;
+   
+   signal State : integer;
+   
+   constant IDLE : integer := 0;
+   constant C1 : integer := 1;
+   constant C2 : integer := 2;
+   constant C3 : integer := 3;
+   constant C4 : integer := 4;
+   constant B1 : integer := 5;
+   constant B2 : integer := 6;
+   constant B3 : integer := 7;
+   constant B4 : integer := 8;
+   constant B5 : integer := 9;
+   constant B6 : integer := 10;
+   constant B4L : integer := 11;
+   constant B5L : integer := 12;
+   constant B6L : integer := 13;
+   constant B0W : integer := 14;
+   constant B1W : integer := 15;
+   constant B2W : integer := 16;
+   constant B3W : integer := 17;
+   constant B4WL : integer := 18;
+   constant B5WL : integer := 19;
+begin
+
+   FSM_State_Control : process (clk, reset)
+   begin
+      if (reset = '1') then
+         State <= IDLE;
+      elsif (clk = '1' and clk'event) then
+         case State is
+            when IDLE =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1') then --start of WB cycle?
+                  if (wb_bte_i /= "00" or wb_cti_i /= "010") then --classic cycle
+                     --(WB rule 4.25, only linear bursts accepted, WB permission 4.40: EOB=single access~=sync.classic cycle, WB rule 4.10: unknown=classic cycles)
+                     --we were in idle state, so any classic cycle, EOB cycle or any cycle with a non linear burst is executed as a classic one
+                     State <= C1;
+                  else --Incrementing burst cycle with linear burst type
+                     assert (wb_bte_i = "00" and wb_cti_i="010") report "Bad else on IDLE state (cti=" & integer'image(conv_integer(wb_cti_i)) & ", bte=" & integer'image(conv_integer(wb_bte_i)) & ")" severity FAILURE;
+                     if (wb_we_i = '0') then --wb burst read?
+                        State <= B1;
+                     else --wb burst write?
+                        State <= B0W;
+                     end if;
+                  end if;
+               else
+                  State <= IDLE;
+               end if;
+            
+            --start single word read/write
+            when C1 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1') then State <= C2; else State <= IDLE; end if;
+            when C2 => --wb_ack <= '1' in this cycle
+               if (wb_cyc_i = '1' and wb_stb_i = '1') then State <= C3; else State <= IDLE; end if;
+            when C3 => --wb_ack = '1' in this cycle
+               State <= C4;
+            when C4 =>
+               State <= IDLE;
+
+               
+            --Burst read
+            when B1 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B2; else State <= IDLE; end if;
+            when B2 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B3; else State <= IDLE; end if;
+            when B3 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then
+                  if (wb_tga_i = '0') then --last burst?
+                     State <= B4L;
+                  else
+                     State <= B4;
+                  end if;
+               else
+                  State <= IDLE;
+               end if;
+            when B4 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B5; else State <= IDLE; end if;
+            when B5 =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B6; else State <= IDLE; end if;
+            when B6 => --go back to B3
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B3; else State <= IDLE; end if;
+            --last burst read
+            when B4L =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B5L; else State <= IDLE; end if;
+            when B5L =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B6L; else State <= IDLE; end if;
+            when B6L =>  --in this cycle wb_cti_i must be 111 because the ZBT has a burst length of 4
+               State <= IDLE;
+               
+            --Burst write   
+            when B0W =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B1W; else State <= IDLE; end if;
+            when B1W =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B2W; else State <= IDLE; end if;
+            when B2W =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_cti_i /= "111") then State <= B3W; else State <= IDLE; end if;
+            when B3W =>
+               if (wb_cyc_i = '1' and wb_stb_i = '1') then --wb_cti should be "111" if it is the last burst
+                  if (wb_tga_i = '0') then --last burst?
+                     State <= B4WL;
+                  else
+                     State <= B0W;
+                  end if;
+               else
+                  State <= IDLE;
+               end if;
+            
+            --last burst write
+            when B4WL => --don't check cti as it was 111 in B3W for the last burst!
+               State <= B5WL;
+            when B5WL =>
+               State <= IDLE;
+
+            when others =>
+               report "Bad state on FSM_State_Control " & integer'image(State) severity FAILURE;
+         end case;
+      end if;
+   end process FSM_State_Control;
+
+
+
+   Wishbone_Slave_Control : process (clk, reset)
+   begin
+      if (reset = '1') then
+         wb_ack_o <= '0';
+         wb_err_o <= '0';
+      elsif (clk = '1' and clk'event) then
+         wb_err_o <= '0';         
+         case State is
+            when IDLE =>
+               if (wb_cyc_i='1' and wb_stb_i='1' and wb_we_i='1' and wb_bte_i="00" and wb_cti_i="010") then --burst write cycle?
+                  wb_ack_o <= '1'; --preack the master to have it give us the next wb_sel_i and wb_dat_i signals
+               else
+                  wb_ack_o <= '0';
+               end if;
+
+            when C1 | C3 | C4 | B1 | B6L | B4WL | B5WL => --in the case of bursts cyc MUST be lowered after cti="111"
+               wb_ack_o <= '0'; --in the case of classic cycles, we have C3 and C4 where ack is lowered, to make the master lower cyc
+
+            when C2 | B2 | B3 | B4 | B5 | B6 | B4L | B5L | B0W | B1W | B2W =>
+               wb_ack_o <= wb_cyc_i and wb_stb_i; --ack should be 1, but it will only go up if cyc and stb are so
+
+            when B3W => --last write burst?
+               wb_ack_o <= wb_tga_i and wb_cyc_i and wb_stb_i; --ack should be 1, but it will only go up if cyc and stb are so (and if it is not the last burst)
+
+            when others =>
+               report "Bad state on WB_Slave_Control " & integer'image(State) severity FAILURE;
+         end case;
+      end if;
+   end process Wishbone_Slave_Control;
+
+   wb_dat_o <= ZBT_dout;
+   
+   ZBT_SRAM_Control : process (clk, reset)
+      variable vBW_enable : std_logic;
+   begin
+      if (reset = '1') then
+         SRAM_ADV_LD_B <= '0';
+         SRAM_CS_B <= '1'; --chip NOT selected
+         SRAM_FLASH_WE_B <= '1'; --DON'T write anything
+         
+         --by default output is not enabled to avoid bus contemption with the wb master
+         SRAM_OE_B2 <= '1'; --output NOT enabled
+         
+         ZBT_addr <= (others => '0');
+         ZBT_addr2 <= (others => '0');
+         
+         ZBT_din2 <= (others => '0');
+         ZBT_din1 <= (others => '0');
+         ZBT_din <= (others => '0');
+         
+         BW_enable <= '0';
+         vBW_enable := '0';
+         SRAM_BW0 <= '1';
+         SRAM_BW1 <= '1';
+         SRAM_BW2 <= '1';
+         SRAM_BW3 <= '1';
+      elsif (clk = '1' and clk'event) then
+         --two stage datain pipeline
+         ZBT_din2 <= wb_dat_i;
+         ZBT_din1 <= ZBT_din2;
+         ZBT_din <= ZBT_din1;
+         
+         --REASON WHY THERE IS A DATAIN PIPELINE:
+         --Based on the ZBT SRAM datasheet:
+         --it doesn't make much sense but the "byte write enables" are not fed to the ZBT
+         --at the same time than the data to be written, so the wb_sel_i lines arrive late
+         --(because they arrive, obviously, at the same time than their associated wb_dat_i lines)
+         --which is 2 cycles later than when they should be fed to the ZBT
+         --the only solution is, on wb writes:
+         -- 1) start wb_acking soon (to have the master give us soon enough the right wb_sel lines for each data word to write)
+         -- 2) make two registers to have a two stage pipeline for the data words in order to feed them to the ZBT at the 3rd cycle
+         -- this means 72 extra FFs for the registers and a more complex wb slave logic (differentiate if read or write)
+         -- there would be the same number of acks but the 2 cycles response latency would happen at the end of the last burst of the wb write
+      
+         case State is
+            when IDLE => --prepare signals for next cycle
+               vBW_enable := '0';
+               SRAM_ADV_LD_B <= '0';
+               if (wb_cyc_i = '1' and wb_stb_i = '1') then
+                  ZBT_addr <= wb_adr_i;
+                  ZBT_addr2 <= wb_adr_i + x"4";
+                  if (wb_bte_i /= "00" or wb_cti_i /= "010") then --classic cycle?
+                     SRAM_CS_B <= '0'; --chip selected
+                     SRAM_OE_B2 <= wb_we_i; --if it's a read -> enable outputs
+                     SRAM_FLASH_WE_B <= not wb_we_i;
+                     vBW_enable := wb_we_i;
+                  else --burst
+                     if (wb_we_i = '0') then --wb burst read?
+                        SRAM_CS_B <= '0'; --chip selected
+                        SRAM_OE_B2 <= wb_we_i; --if it's a read -> enable outputs
+                        SRAM_FLASH_WE_B <= not wb_we_i;
+                     else --wb burst write? start ZBT in B0W but get now ZBT_addr2!
+                        ZBT_addr2 <= wb_adr_i; --important because ZBT_addr2 will be assigned in next cycle (so don't sum 4 to it)
+                        SRAM_CS_B <= '1'; --chip NOT selected
+                        SRAM_OE_B2 <= '1'; --output NOT enabled for next cycle
+                        SRAM_FLASH_WE_B <= '1'; --DON'T write anything
+                     end if;
+                  end if;
+               else
+                  SRAM_CS_B <= '1'; --chip NOT selected
+                  SRAM_OE_B2 <= '1'; --output NOT enabled for next cycle
+                  SRAM_FLASH_WE_B <= '1'; --DON'T write anything
+                  ZBT_addr <= (others => '0');
+                  ZBT_addr2 <= (others => '0');
+               end if;
+               
+               
+            when C1 | C2 =>
+               SRAM_CS_B <= '1'; --chip NOT selected (doesn't affect current op.: don't care in datasheet)
+               SRAM_ADV_LD_B <= '0'; --NOT a burst
+               --SRAM_OE_B2 keep the selected output enable for the current WB operation
+               vBW_enable := '0'; --it only matters for the ADV=0 cycle of the ZBT operation
+               
+            when C3 | C4 =>
+               SRAM_CS_B <= '1'; --chip NOT selected (doesn't affect current op.: don't care in datasheet)
+               SRAM_ADV_LD_B <= '0'; --NOT a burst
+               SRAM_OE_B2 <= '1'; --output NOT enabled for next cycle
+               vBW_enable := '0';
+
+
+
+            when B1 | B2 | B3 | B5 | B6 =>
+               SRAM_ADV_LD_B <= '1';
+               
+            when B4 => --precharge address for next 4 word burst
+               SRAM_ADV_LD_B <= '0';
+               ZBT_addr <= ZBT_addr2;
+               ZBT_addr2 <= ZBT_addr2 + x"4";
+            
+            when B4L | B5L | B6L => --last burst
+               SRAM_ADV_LD_B <= '0';
+               SRAM_CS_B <= '1'; --chip NOT selected
+            
+            
+            when B0W => --a wb write starts here
+               SRAM_ADV_LD_B <= '0'; --first write cycle
+               SRAM_OE_B2 <= '1'; --keep output NOT enabled (it's a write)
+               SRAM_CS_B <= '0'; --chip selected
+               SRAM_FLASH_WE_B <= '0'; --start writing
+               ZBT_addr <= ZBT_addr2;
+               ZBT_addr2 <= ZBT_addr2 + x"4";
+               vBW_enable := '1';
+            
+            when B1W | B2W | B3W =>
+               SRAM_ADV_LD_B <= '1';
+               vBW_enable := '1';
+               
+            when B4WL | B5WL =>
+               SRAM_CS_B <= '1'; --chip NOT selected (don't care in datasheet)
+               SRAM_FLASH_WE_B <= '1'; --DON'T write (don't care in datasheet)
+               SRAM_ADV_LD_B <= '0';
+               vBW_enable := '0';
+            
+            when others =>
+               report "Bad state on ZBT_SRAM_Control " & integer'image(State) severity FAILURE;
+         end case;
+         
+         BW_enable <= vBW_enable;
+         --Byte write enables are active low
+         SRAM_BW0 <= not (wb_sel_i(0) and vBW_enable);
+         SRAM_BW1 <= not (wb_sel_i(1) and vBW_enable);
+         SRAM_BW2 <= not (wb_sel_i(2) and vBW_enable);
+         SRAM_BW3 <= not (wb_sel_i(3) and vBW_enable);         
+      end if;
+   end process ZBT_SRAM_Control;   
+
+
+   
+   SRAM_CLK <= clk;
+   SRAM_MODE <= '0'; --linear bursts
+   SRAM_OE_B <= SRAM_OE_B2; --to let OE_B2 be read to mux the data lines
+
+
+   ---------------------------------
+   --  DATA IN LINES
+   ---------------------------------
+   SRAM_FLASH_D0 <= ZBT_din(0) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D1 <= ZBT_din(1) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D2 <= ZBT_din(2) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D3 <= ZBT_din(3) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D4 <= ZBT_din(4) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D5 <= ZBT_din(5) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D6 <= ZBT_din(6) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D7 <= ZBT_din(7) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D8 <= ZBT_din(8) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D9 <= ZBT_din(9) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D10 <= ZBT_din(10) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D11 <= ZBT_din(11) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D12 <= ZBT_din(12) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D13 <= ZBT_din(13) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D14 <= ZBT_din(14) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_FLASH_D15 <= ZBT_din(15) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D16 <= ZBT_din(16) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D17 <= ZBT_din(17) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D18 <= ZBT_din(18) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D19 <= ZBT_din(19) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D20 <= ZBT_din(20) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D21 <= ZBT_din(21) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D22 <= ZBT_din(22) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D23 <= ZBT_din(23) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D24 <= ZBT_din(24) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D25 <= ZBT_din(25) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D26 <= ZBT_din(26) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D27 <= ZBT_din(27) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D28 <= ZBT_din(28) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D29 <= ZBT_din(29) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D30 <= ZBT_din(30) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_D31 <= ZBT_din(31) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_DQP0 <= ZBT_din(32) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_DQP1 <= ZBT_din(33) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_DQP2 <= ZBT_din(34) when (SRAM_OE_B2 = '1') else 'Z';
+   SRAM_DQP3 <= ZBT_din(35) when (SRAM_OE_B2 = '1') else 'Z';
+   
+
+   ---------------------------------
+   --  DATA OUT LINES
+   ---------------------------------
+   ZBT_dout(0) <= SRAM_FLASH_D0;
+   ZBT_dout(1) <= SRAM_FLASH_D1;
+   ZBT_dout(2) <= SRAM_FLASH_D2;
+   ZBT_dout(3) <= SRAM_FLASH_D3;
+   ZBT_dout(4) <= SRAM_FLASH_D4;
+   ZBT_dout(5) <= SRAM_FLASH_D5;
+   ZBT_dout(6) <= SRAM_FLASH_D6;
+   ZBT_dout(7) <= SRAM_FLASH_D7;
+   ZBT_dout(8) <= SRAM_FLASH_D8;
+   ZBT_dout(9) <= SRAM_FLASH_D9;
+   ZBT_dout(10) <= SRAM_FLASH_D10;
+   ZBT_dout(11) <= SRAM_FLASH_D11;
+   ZBT_dout(12) <= SRAM_FLASH_D12;
+   ZBT_dout(13) <= SRAM_FLASH_D13;
+   ZBT_dout(14) <= SRAM_FLASH_D14;
+   ZBT_dout(15) <= SRAM_FLASH_D15;
+   ZBT_dout(16) <= SRAM_D16;
+   ZBT_dout(17) <= SRAM_D17;
+   ZBT_dout(18) <= SRAM_D18;
+   ZBT_dout(19) <= SRAM_D19;
+   ZBT_dout(20) <= SRAM_D20;
+   ZBT_dout(21) <= SRAM_D21;
+   ZBT_dout(22) <= SRAM_D22;
+   ZBT_dout(23) <= SRAM_D23;
+   ZBT_dout(24) <= SRAM_D24;
+   ZBT_dout(25) <= SRAM_D25;
+   ZBT_dout(26) <= SRAM_D26;
+   ZBT_dout(27) <= SRAM_D27;
+   ZBT_dout(28) <= SRAM_D28;
+   ZBT_dout(29) <= SRAM_D29;
+   ZBT_dout(30) <= SRAM_D30;
+   ZBT_dout(31) <= SRAM_D31;
+   ZBT_dout(32) <= SRAM_DQP0;
+   ZBT_dout(33) <= SRAM_DQP1;
+   ZBT_dout(34) <= SRAM_DQP2;
+   ZBT_dout(35) <= SRAM_DQP3;
+
+   
+   ---------------------------------
+   --  ADDRESS LINES
+   ---------------------------------
+   SRAM_FLASH_A1 <= ZBT_addr(0);
+   SRAM_FLASH_A2 <= ZBT_addr(1);
+   SRAM_FLASH_A3 <= ZBT_addr(2);
+   SRAM_FLASH_A4 <= ZBT_addr(3);
+   SRAM_FLASH_A5 <= ZBT_addr(4);
+   SRAM_FLASH_A6 <= ZBT_addr(5);
+   SRAM_FLASH_A7 <= ZBT_addr(6);
+   SRAM_FLASH_A8 <= ZBT_addr(7);
+   SRAM_FLASH_A9 <= ZBT_addr(8);
+   SRAM_FLASH_A10 <= ZBT_addr(9);
+   SRAM_FLASH_A11 <= ZBT_addr(10);
+   SRAM_FLASH_A12 <= ZBT_addr(11);
+   SRAM_FLASH_A13 <= ZBT_addr(12);
+   SRAM_FLASH_A14 <= ZBT_addr(13);
+   SRAM_FLASH_A15 <= ZBT_addr(14);
+   SRAM_FLASH_A16 <= ZBT_addr(15);
+   SRAM_FLASH_A17 <= ZBT_addr(16);
+   SRAM_FLASH_A18 <= ZBT_addr(17);
+
+end Behavioral;
+
diff --git a/src/edu/berkeley/fleet/interpreter/DebugDock.java b/src/edu/berkeley/fleet/interpreter/DebugDock.java
new file mode 100644 (file)
index 0000000..2ab6fc4
--- /dev/null
@@ -0,0 +1,43 @@
+package edu.berkeley.fleet.interpreter;
+import java.util.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+/** EXPERIMENTAL -- DO NOT RELY ON THIS INTERFACE */
+public class DebugDock {
+    final InterpreterDock dock;
+
+    public DebugDock(Dock d) {
+        dock = (InterpreterDock)d;
+    }
+
+    public Dock getDock()                       { return dock; }
+    public int getOLC()                         { return dock.olc; }
+    public int getILC()                         { return dock.ilc; }
+    public Instruction getExecuting()           { return dock.instructions.peek(); }
+    public Queue<Instruction> getInstructions() { return dock.instructions; }
+    public boolean getDataReadyForShip()        { return dock.dataReadyForShip; }
+    public boolean getReadyForDataFromShip()    { return dock.readyForDataFromShip;}
+    public long getDataFromShip()               { return dock.dataFromShip; }
+    public boolean getTorpedoWaiting()          { return dock.torpedoWaiting; }
+    public boolean isHatchOpen()                { return !dock.requeueStageInCirculatingState; }
+    public boolean getFlagA()                   { return dock.flag_a; }
+    public boolean getFlagB()                   { return dock.flag_b; }
+    public boolean getFlagC()                   { return dock.flag_c; }
+    public BitVector getDataLatch()             { return dock.dataLatch; }
+    public Queue<BitVector> getDataDestPackets() {
+        Queue<BitVector> values = new LinkedList<BitVector>();
+        for (Packet p : dock.dataPackets)
+            if (!p.isToken())
+                values.add(p.getValue());
+        return values;
+    }
+    public Queue<Instruction> getEpilogue() {
+        throw new RuntimeException("this method has been removed");
+    }
+    public Queue<Instruction> getInstructionsInFabric() {
+        throw new RuntimeException("this method has been removed");
+    }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/Interpreter.java b/src/edu/berkeley/fleet/interpreter/Interpreter.java
new file mode 100644 (file)
index 0000000..e58eb3d
--- /dev/null
@@ -0,0 +1,236 @@
+package edu.berkeley.fleet.interpreter;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.util.ANSI;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.assembler.*;
+import edu.berkeley.fleet.util.*;
+
+public class Interpreter extends FleetTwoFleet {
+
+    /** used to allocate serial numbers; see InterpreterDestination for further detail */
+    int maxAllocatedDestinationSerialNumber = 0;
+
+    private InterpreterShip debugShip = null;
+    private BlockingQueue<BitVector> debugStream = new LinkedBlockingQueue<BitVector>();
+    private LinkedHashMap<String,InterpreterShip> ships = new LinkedHashMap<String,InterpreterShip>();
+    public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
+    public Ship getShip(String type, int ordinal) {
+        for(Ship s : this)
+            if (s.getType().equals(type))
+                if (ordinal-- <= 0)
+                    return s;
+        return null;
+    }
+
+    /** do not use this; it is going to go away */
+    public Interpreter() { this(true); }
+    public Interpreter(boolean logging) {
+        this(new String[] {
+                "Debug",
+                "Memory",
+                "Memory",
+                "Memory",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Fifo",
+                "Fifo",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Lut3",
+                "CarrySaveAdder",
+                "Rotator",
+            }, logging);
+    }
+
+    public Interpreter(String[] ships, boolean logging) {
+        int i=0;
+        Log.quiet = !logging;
+        for(String s : ships) {
+            createShip(ships[i], ships[i]+"_"+i);
+            i++;
+        }
+    }
+
+    private Ship createShip(String shipType, String shipname) {
+        try {
+            if (ships.get(shipname)!=null) return ships.get(shipname);
+            Class c = Class.forName("edu.berkeley.fleet.interpreter."+shipType);
+            Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class });
+            String src = "/ships/" + shipType + ".ship";
+            InputStream is = getClass().getResourceAsStream(src);
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            ShipDescription sd = new ShipDescription(this, shipType, br);
+            InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname, sd });
+            ships.put(shipname, ret);
+            if (shipType.equals("Debug") && debugShip == null)
+                debugShip = ret;
+            return ret;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    void debug(long d) { debug(new BitVector(getWordWidth()).set(d)); }
+    void debug(BitVector data) {
+        try {
+            if (debugStream != null) debugStream.put(data);
+            else Log.println(ANSI.invert("   DEBUG: got a datum: " +  data+ANSI.clreol()));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // Instruction Encoding /////////////////////////////////////////////////////////////////////////
+
+    public BitVector getDestAddr(Path path) {
+        long ret = ((InterpreterDestination)path.getDestination()).getSerialNumber();
+        BitVector sig = path.getSignal();
+        BitVector bv = new BitVector(DISPATCH_PATH.valmaskwidth+1);
+        bv.set(ret);
+        if (sig != null) {
+            if (sig.length() > 1) throw new RuntimeException("signal was " + sig.length() + " bits long!");
+            if (sig.length() > 0 && sig.get(0)) bv.set(bv.length()-1,true);
+        }
+        return bv;
+    }
+
+
+    // ShipDescription //////////////////////////////////////////////////////////////////////////////
+
+    public void expand(ShipDescription sd) {
+        try {
+            String filename = sd.getName();
+            //String filename = (sd.getName().charAt(0)+"").toUpperCase() + sd.getName().substring(1).toLowerCase();
+            File outf = new File("build/java/edu/berkeley/fleet/interpreter/"+filename+".java");
+            new File(outf.getParent()).mkdirs();
+            System.err.println("writing to " + outf);
+            FileOutputStream out = new FileOutputStream(outf);
+            PrintWriter pw = new PrintWriter(out);
+
+            pw.println("package edu.berkeley.fleet.interpreter;");
+            pw.println("import edu.berkeley.sbp.util.ANSI;");
+            pw.println("import edu.berkeley.fleet.api.*;");
+            pw.println("import edu.berkeley.fleet.two.*;");
+            pw.println("import edu.berkeley.fleet.*;");
+            pw.println("import java.util.*;");
+            pw.println("import java.io.*;");
+            pw.println("");
+            pw.println("public class "+filename+" extends InterpreterShip {");
+            pw.println("");
+            pw.println("    public "+filename+"(Interpreter fleet, String name, ShipDescription sd) {");
+            pw.println("       super(fleet, sd);");
+            pw.println("    }");
+            pw.println("");
+            for(DockDescription b : sd) {
+                String name = b.getName();
+                pw.print("    InterpreterDock box_");
+                pw.print(name);
+                pw.print(" = new InterpreterDock(this, shipDescription.getDockDescription(\""+name+"\"));");
+            }
+            pw.println("");
+            pw.println(sd.getSection("fleeterpreter"));
+            pw.println("}");
+            pw.flush();
+            pw.close();
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    // Run //////////////////////////////////////////////////////////////////////////////
+
+    public FleetProcess run(final Instruction[] instructions) {
+        InterpreterProcess ip = initialize(instructions);
+        new Thread(ip).start();
+        return ip;
+    }
+
+    public InterpreterProcess initialize(Instruction[] instr) {
+        return new InterpreterProcess(instr);
+    }
+
+    public class InterpreterProcess extends FleetProcess implements Runnable {
+        private Instruction[] instructions;
+        public synchronized void sendWord(Destination d, BitVector word) {
+            InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, new BitVector(1));
+            ((InterpreterDestination)d).
+                addDataFromFabric(new Packet(path, word, false));
+        }
+        public synchronized void sendToken(Destination d) {
+            InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, new BitVector(1));
+            ((InterpreterDestination)d).
+                addDataFromFabric(new Packet(path, new BitVector(getWordWidth()), true));
+        }
+        public InterpreterProcess(Instruction[] instructions) {
+            this.instructions = instructions;
+            for(Instruction i : instructions)
+                sendInstruction(i);
+        }
+        public Fleet getFleet() { return Interpreter.this; }
+        public synchronized void sendInstruction(Instruction i) {
+            Log.dispatch(i);
+            long il = writeInstruction(i, debugShip.getDock("in"));
+            Path path = debugShip.getDock("in").getPath(i.dock.getInstructionDestination(), null);
+            new Packet((InterpreterPath)path, new BitVector(getWordWidth()).set(il), false).send();
+        }
+        public Dock getDebugInputDock() { return debugShip.getDock("in"); }
+        public BitVector recvWord() {
+            try {
+                return debugStream.take();
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
+        protected void _terminate() { }
+        public void run() {
+            try {
+                while(!isTerminated()) {
+                    flush();
+                }
+                for(InterpreterShip ship : ships.values())
+                    ship.reset();
+                debugStream.clear();
+            } catch (Exception e) {
+                if (isTerminated()) return;
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void flush() {
+            // FIXME: should this run until we detect some sort of "quiescence"?  OTOH that might never happen.
+            for(InterpreterShip ship : ships.values())
+                for(int j=0; j<10; j++)
+                    if (!isTerminated())
+                        synchronized(this) {
+                            ship._service();
+                        }
+        }
+
+        public synchronized void step(Dock d) {
+            ((InterpreterDock)d).service();
+        }
+        
+        public synchronized void step(Ship s) {
+            ((InterpreterShip)s).service();
+        }
+
+    }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java b/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java
new file mode 100644 (file)
index 0000000..df86579
--- /dev/null
@@ -0,0 +1,28 @@
+package edu.berkeley.fleet.interpreter;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+
+abstract class InterpreterDestination extends Destination {
+
+    public InterpreterDestination(InterpreterDock d) {
+        super(d);
+        synchronized(d.getInterpreter()) {
+            this.serialNumber = d.getInterpreter().maxAllocatedDestinationSerialNumber++;
+        }
+    }
+
+    /** adds the included datum to the port from the switch fabric side */
+    public abstract void addDataFromFabric(Packet packet);
+    public abstract String toString();
+
+    /**
+     *  The Fleet instruction encoding mechanism assumes that each
+     *  source->dest path can be turned into a bitstring, and that the
+     *  bitstring gives sufficient information to route the packet.
+     *  Therefore, the interpreter assigns a "serial number" to every
+     *  InterpreterDestination in a fleet and uses the serial number
+     *  of the destination as the path.
+     */
+    private int serialNumber;
+    int getSerialNumber() { return serialNumber; }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterDock.java b/src/edu/berkeley/fleet/interpreter/InterpreterDock.java
new file mode 100644 (file)
index 0000000..40e66b0
--- /dev/null
@@ -0,0 +1,276 @@
+package edu.berkeley.fleet.interpreter;
+import java.util.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+
+/** anything that has a source (instruction horn) address on the switch fabric */
+class InterpreterDock extends FleetTwoDock {
+
+    // Dock State //////////////////////////////////////////////////////////////////////////////
+    
+    boolean         flag_a = false;
+    boolean         flag_b = false;
+    boolean         flag_c = false;
+    boolean         flag_d = false;
+    int             ilc    = 1;
+    int             olc    = 1;
+    final BitVector dataLatch = new BitVector(getShip().getFleet().getWordWidth());
+    InterpreterPath pathLatch = null;
+    boolean         requeueStageInCirculatingState = false;
+    boolean         requeueStageHasTailInstruction = false;
+    boolean         torpedoWaiting = false;
+    boolean         flushing = false;
+
+    Queue<Instruction> instructions = new LinkedList<Instruction>();
+    Queue<Packet> dataPackets = new LinkedList<Packet>();
+
+    // HACK
+    private Queue<Instruction> instructionsBackedUpIntoSwitchFabric = new LinkedList<Instruction>();
+
+    boolean dataReadyForShip = false;
+    boolean readyForDataFromShip = true;
+    long dataFromShip;
+    boolean flagCFromShip;
+
+    protected void reset() {
+        ilc = 1;
+        olc = 1;
+        flag_a = false;
+        flag_b = false;
+        flag_c = false;
+        flag_d = false;
+        dataLatch.set(0);
+        pathLatch = null;
+        requeueStageInCirculatingState = false;
+        requeueStageHasTailInstruction = false;
+        instructions.clear();
+        dataPackets.clear();
+        instructionsBackedUpIntoSwitchFabric.clear();
+        dataReadyForShip = false;
+        readyForDataFromShip = true;
+        torpedoWaiting = false;
+        flushing = false;
+    }
+
+    // Destinations //////////////////////////////////////////////////////////////////////////////
+
+    /** includes the epilogue fifo */
+    public InterpreterDestination instructionDestination = new InterpreterDestination(this) {
+            public String toString() { return getDock()+":i"; }
+            public void addDataFromFabric(Packet p) {
+                if (p.isToken()) {
+                    if (instructionsBackedUpIntoSwitchFabric.size()!=0)
+                        throw new RuntimeException("torpedo arrived while instructions were backed up into switch fabric");
+                    if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
+                    torpedoWaiting = true;
+                    return;
+                }
+
+                Instruction inst =
+                    getInterpreter().decodeInstruction(p.getValue(),
+                                                       InterpreterDock.this /* this is wrong, but harmless */);
+                addInstruction(inst);
+            }
+        };
+    public InterpreterDestination dataDestination = new InterpreterDestination(this) {
+            public String toString() { return getDock()+""; }
+            public void addDataFromFabric(Packet packet) { dataPackets.add(packet); }
+        };
+
+    InterpreterDock(InterpreterShip ship, DockDescription bbd) {
+        super(ship, bbd);
+        ship.docks.put(bbd.getName(), this);
+    }
+
+    public Path getPath(Destination d, BitVector signal) { return new InterpreterPath(this, (InterpreterDestination)d, signal); }
+    public Destination getInstructionDestination() { return instructionDestination; }
+    public Destination getDataDestination() { return dataDestination; }
+    public int getInstructionFifoSize() { return Integer.MAX_VALUE; }
+    public Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
+
+    boolean trace = false;
+
+    private void addInstruction(Instruction inst) {
+        if (requeueStageInCirculatingState || requeueStageHasTailInstruction) {
+            // GROSS HACK
+            instructionsBackedUpIntoSwitchFabric.add(inst);
+            return;
+        }
+        if (inst instanceof Instruction.Tail) {
+            requeueStageHasTailInstruction = true;
+            return;
+        }
+        instructions.add(inst);
+    }
+    
+    protected final void service() {
+
+        if (dataReadyForShip || flushing) return;
+        if (instructions.size()==0) return;
+
+        if (instructions.peek() instanceof Instruction.Head) {
+            if (requeueStageInCirculatingState) { instructions.remove(); return; }
+            if (!requeueStageHasTailInstruction) return;
+            requeueStageHasTailInstruction = false;
+            requeueStageInCirculatingState = true;
+            instructions.remove();
+            return;
+        }
+
+        // in the while..false idiom block below, use "break" to
+        // consume the instruction at instructions.peek(), or "return"
+        // to leave it and retry on the next call.
+        do {
+            if (!instructions.peek().predicate.evaluate(flag_a, flag_b, flag_c, flag_d))
+                break;
+
+            if (instructions.peek() instanceof Instruction.Move) {
+                Instruction.Move move = (Instruction.Move)instructions.peek();
+
+                if (ilc==0) { ilc = 1; break; }
+
+                if (move.interruptible && torpedoWaiting) {
+                    torpedoWaiting = false;
+                    ilc = 1;
+                    flag_d = true;
+                    break;
+                }
+
+                if (move.dataIn  && !isInputDock() && readyForDataFromShip)  return;
+                if (move.dataIn  &&  isInputDock() && dataPackets.size()==0) return;
+                if (move.tokenIn &&                   dataPackets.size()==0) return;
+
+                if (move.tokenIn) {
+                    Packet p = dataPackets.remove();
+                    flag_c = p.getSignal().get(0);
+                }
+                if (move.dataIn) {
+                    BitVector bv = null;
+                    if (isInputDock()) {
+                        Packet p = dataPackets.remove();
+                        bv = new BitVector(p.getValue());
+                        flag_c = p.getSignal().get(0);
+                    } else {
+                        bv = new BitVector(getInterpreter().getWordWidth()).set(dataFromShip);
+                        readyForDataFromShip = true;
+                        if (move.latchData) flag_c = flagCFromShip;
+                    }
+                    if (move.latchData) dataLatch.set(bv);
+                    if (move.latchPath) {
+                        BitVector bvp = ((FleetTwoFleet)getShip().getFleet()).DISPATCH_PATH.getvalAsBitVector(bv);
+                        pathLatch = (InterpreterPath)getInterpreter().getPathByAddr(this, bvp);
+                    }
+                }
+                
+                if (move.path != null) pathLatch = (InterpreterPath)move.path;
+                
+                if (move.dataOut && isInputDock())  dataReadyForShip = true;
+                if (move.dataOut && !isInputDock()) new Packet(pathLatch, new BitVector(dataLatch), false).send();
+                if (move.tokenOut)                  new Packet(pathLatch, new BitVector(getInterpreter().getWordWidth()), true).send();
+                
+                if (ilc==1)  break;
+                if (ilc!=-1) ilc--;
+                return;
+
+            } else if (instructions.peek() instanceof Instruction.Abort) {
+                requeueStageInCirculatingState = false;
+                // HACK
+                while (instructionsBackedUpIntoSwitchFabric.size()!=0) {
+                    Instruction i = instructionsBackedUpIntoSwitchFabric.remove();
+                    addInstruction(i);
+                    instructionsBackedUpIntoSwitchFabric.clear();
+                }
+                break;
+
+            } else if (instructions.peek() instanceof Instruction.Flush) {
+                flushing = true;
+                break;
+
+            } else if (instructions.peek() instanceof Instruction.Shift) {
+                Instruction.Shift shift = (Instruction.Shift)instructions.peek();
+                for(int i=dataLatch.length()-1; i>=getShip().getFleet().getShiftWidth(); i--)
+                    dataLatch.set(i, dataLatch.get(i-getShip().getFleet().getShiftWidth()));
+                BitVector shift_immediate = shift.immediate.getBitVector();
+                for(int i=getShip().getFleet().getShiftWidth()-1; i>=0; i--)
+                    dataLatch.set(i, shift_immediate.get(i));
+                break;
+
+            } else if (instructions.peek() instanceof Instruction.Set) {
+                Instruction.Set set = (Instruction.Set)instructions.peek();
+                switch(set.dest) {
+                    case DataLatch: dataLatch.setAndSignExtend(set.immediate);
+                    break;
+                    case InnerLoopCounter:
+                        switch(set.source) {
+                            case Infinity:  ilc = -1; break;
+                            case Immediate: ilc = (int)set.immediate; break;
+                            case DataLatch:
+                                ilc = 0;
+                                for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_ILC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+                                    if (dataLatch.get(i))
+                                        ilc |= (1 << i);
+                                break;
+                            default: throw new RuntimeException("impossible");
+                        }
+                        break;
+                    case OuterLoopCounter:
+                        switch(set.source) {
+                            case Decrement: olc = Math.max(0,olc-1); break;
+                            case Immediate: olc = (int)set.immediate; break;
+                            case DataLatch:
+                                olc = 0;
+                                for(int i=0; i<((FleetTwoFleet)getShip().getFleet()).SET_OLC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+                                    if (dataLatch.get(i))
+                                        olc |= (1 << i);
+                                break;
+                            default: throw new RuntimeException("impossible");
+                        }
+                        flag_d = olc==0;
+                        break;
+                        
+                    case Flags: {
+                        boolean new_flag_a = set.newFlagA.evaluate(flag_a, flag_b, flag_c, flag_d);
+                        boolean new_flag_b = set.newFlagB.evaluate(flag_a, flag_b, flag_c, flag_d);
+                        flag_a = new_flag_a;
+                        flag_b = new_flag_b;
+                        break;
+                    }
+                    default: throw new RuntimeException("FIXME!");
+                }
+            } else {
+                throw new RuntimeException("unimplemented instruction: " + instructions.peek());
+            }
+        } while(false);
+
+        if (requeueStageInCirculatingState)
+            instructions.add(instructions.peek());
+        instructions.remove();
+        return;
+    }
+
+    // Interface for use by Subclasses ///////////////////////////////////////////////////////////////////////
+
+    // all the methods below convert 64-bit longs to/from
+    // getWordWidth()-bit BitVectors by truncation and sign-extension.
+
+    protected boolean dataReadyForShip() { return dataReadyForShip; }
+    protected final boolean readyForDataFromShip() { return readyForDataFromShip; }
+    protected long removeDataForShip() {
+        long val = peekDataForShip();
+        dataReadyForShip = false;
+        return val;
+    }
+    protected long peekDataForShip() {
+        if (!dataReadyForShip)
+            throw new RuntimeException("peekDataForShip() invoked when dataReadyForShip()==false");
+        return dataLatch.toLong();
+    }
+    protected void addDataFromShip(long data) { addDataFromShip(data, false); }
+    protected void addDataFromShip(long data, boolean pending_flag_c) {
+        if (!readyForDataFromShip())
+            throw new RuntimeException("addDataFromShip() invoked when readyForDataFromShip()");
+        readyForDataFromShip = false;
+        dataFromShip = data;
+        flagCFromShip = pending_flag_c;
+    }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterPath.java b/src/edu/berkeley/fleet/interpreter/InterpreterPath.java
new file mode 100644 (file)
index 0000000..08bf3b5
--- /dev/null
@@ -0,0 +1,26 @@
+package edu.berkeley.fleet.interpreter;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import java.util.*;
+
+class InterpreterPath extends FleetTwoPath {
+
+    private final InterpreterDock source;
+    private final InterpreterDestination dest;
+    private final BitVector signal;
+
+    public InterpreterPath(InterpreterDock source,
+                           InterpreterDestination dest,
+                           BitVector signal) {
+        this.source = source;
+        this.dest = dest;
+        this.signal = signal;
+    }
+
+    public Dock        getSource() { return source; }
+    public Destination getDestination() { return dest; }
+    public int         getBufferingAmount() { return Integer.MAX_VALUE; }
+    public int         getLatencyMetric() { return 0; }
+    public BitVector   getSignal() { return signal; }
+
+}
diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterShip.java b/src/edu/berkeley/fleet/interpreter/InterpreterShip.java
new file mode 100644 (file)
index 0000000..033b33b
--- /dev/null
@@ -0,0 +1,66 @@
+package edu.berkeley.fleet.interpreter;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import java.util.*;
+import java.io.*;
+
+/** a ship, which belongs to a fleet and which may have many docks */
+abstract class InterpreterShip extends FleetTwoShip {
+        
+    LinkedHashMap<String,InterpreterDock> docks = new LinkedHashMap<String,InterpreterDock>();
+
+    /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
+    public InterpreterShip(Interpreter fleet, ShipDescription sd) {
+        super(fleet, sd);
+    }
+
+    public Iterator<Dock> iterator() {
+        return (Iterator<Dock>)(Object)docks.values().iterator();
+    }
+
+    /**
+     *  Override this method, check inboxes for the data you need, and
+     *  if you find it, deposit results in an outbox; we'll take care
+     *  of the rest.
+     */
+    public abstract void service();
+
+    public final void _service() {
+
+        // service all the docks
+        for(InterpreterDock p : docks.values()) p.service();
+
+        // flushing logic (must come between dock servicing and subclass)
+        boolean someflushing = false;
+        boolean allflushing = true;
+        boolean someempty = false;
+        for(InterpreterDock d : docks.values()) {
+            if (!d.isInputDock()) continue;
+            if (d.flushing) someflushing = true;
+            else allflushing = false;
+            if (!d.flushing && !d.dataReadyForShip) someempty = true;
+        }
+        if (allflushing) {
+            for(InterpreterDock d : docks.values())
+                if (d.isInputDock())
+                    d.flushing = false;
+            return;
+        } else if (someflushing && !someempty) {
+            for(InterpreterDock d : docks.values())
+                if (d.isInputDock() && !d.flushing && d.dataReadyForShip) {
+                    System.out.println("FLUSH AT " + this);
+                    d.dataReadyForShip = false;
+                }
+        }
+
+        // now pass control to the subclass
+        service();
+    }
+
+    public void reset() {
+        for(InterpreterDock p : docks.values())
+            p.reset();
+    }
+
+    public Interpreter getInterpreter() { return (Interpreter)getFleet(); }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/Log.java b/src/edu/berkeley/fleet/interpreter/Log.java
new file mode 100644 (file)
index 0000000..a83d15c
--- /dev/null
@@ -0,0 +1,64 @@
+package edu.berkeley.fleet.interpreter;
+import edu.berkeley.sbp.util.ANSI;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+
+public class Log {
+
+    public static boolean ansi_color = true;
+    public static PrintWriter log = new PrintWriter(new OutputStreamWriter(System.out));
+    public static boolean quiet = false;
+
+    public static void print(Object o) {
+        if (log==null || quiet) return;
+        try {
+            log.print(o);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+    public static void println() { println(""); }
+    public static void println(Object o) {
+        if (log==null || quiet) return;
+        try {
+            log.println(o);
+            log.flush();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /*
+    public static void dispatch(Dispatchable d) {
+        println(ANSI.green("dispatch: " + indent(d+"", "          ")));
+    }
+    */
+    public static void dispatch(Instruction d) {
+        println(ANSI.green("dispatch: " + indent(d+"", "          ")));
+    }
+
+    public static void data(String data, Dock source, Destination dest) {
+        println(("    data: ") + indent(ANSI.purple(data) +
+                                        (source==null ? "" :
+                                         (" : " + source))+(" -> "+ANSI.purple(""+dest)), "          "));
+    }
+
+    public static void token(Dock source, Destination dest) {
+        println(ANSI.purple("   token: ") + (source + " -> " + ANSI.purple(dest+"")));
+    }
+
+    public static String clreol() { return ""; }
+    public static void error(Object o) { println(ANSI.red(o)); }
+
+    public static String indent(String s, String indent) {
+        StringBuffer ret = new StringBuffer();
+        for(int i=0; i<s.length(); i++) {
+            char c = s.charAt(i);
+            if (!(c=='\n' && i==s.length()-1))
+                ret.append(c);
+            if (c=='\n' && i<s.length()-1)
+                ret.append(indent);
+        }
+        return ret.toString();
+    }
+}
diff --git a/src/edu/berkeley/fleet/interpreter/Packet.java b/src/edu/berkeley/fleet/interpreter/Packet.java
new file mode 100644 (file)
index 0000000..5f44da2
--- /dev/null
@@ -0,0 +1,42 @@
+package edu.berkeley.fleet.interpreter;
+import edu.berkeley.fleet.api.*;
+
+class Packet {
+
+    private final InterpreterPath path;
+    private final BitVector value;
+    private final boolean isToken;
+
+    public Packet(InterpreterPath path, BitVector value, boolean isToken) {
+        this.value = value;
+        this.path = path;
+        this.isToken = isToken;
+        this.value.setImmutable();
+    }
+
+    public void send() {
+        if (isToken) {
+            Log.token(path.getSource(), path.getDestination());
+        } else {
+            Log.data(value+"", path.getSource(), path.getDestination());
+        }
+        ((InterpreterDestination)path.getDestination()).addDataFromFabric(this);
+    }
+
+    public Destination getDestination() {
+        return path.getDestination();
+    }
+
+    public BitVector getSignal() {
+        return path.getSignal();
+    }
+
+    public BitVector getValue() {
+        return value;
+    }
+
+    public boolean isToken() {
+        return isToken;
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/loops/CleanupUtils.java b/src/edu/berkeley/fleet/loops/CleanupUtils.java
new file mode 100644 (file)
index 0000000..770ae38
--- /dev/null
@@ -0,0 +1,96 @@
+package edu.berkeley.fleet.loops;
+import edu.berkeley.fleet.loops.*;
+import java.util.concurrent.Semaphore;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import edu.berkeley.fleet.api.Instruction.Set.SetDest;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+public class CleanupUtils {
+
+    /**
+     *  Verifies that the switch fabric and all instruction rings are empty.
+     */
+    public static void verifyClean(FleetProcess fp) {
+        Ship debug   = fp.getFleet().getShip("Debug", 0);
+        Dock debugIn = debug.getDock("in");
+
+        CodeBag ctx;
+        LoopFactory lf;
+
+        ctx = new CodeBag(fp.getFleet());
+        lf = ctx.loopFactory(debugIn, 1);
+        lf.literal(12);
+        lf.deliver();
+        lf.literal(5);
+        lf.deliver();
+        ctx.dispatch(fp);
+        fp.flush();
+
+        System.out.println("checking debug.in");
+        if (fp.recvWord().toLong() != 12) throw new RuntimeException("debug dock not properly initialized");
+        if (fp.recvWord().toLong() != 5)  throw new RuntimeException("debug dock not properly initialized");
+
+        long k = 0;
+        for(Ship ship : fp.getFleet())
+            if (!"Debug".equals(ship.getType()))
+                for (Dock dock : ship) {
+                    System.out.print("checking " + dock + "                     ");
+
+                    k = (k + 23) % 65535;
+                    ctx = new CodeBag(fp.getFleet());
+
+                    boolean reverse = (k%2)==0;
+
+                    lf = ctx.loopFactory(debugIn, 4);
+                    lf.recvToken();
+                    lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+                    lf.setPredicate(Predicate.NotFlagA);
+                    lf.literal(k);
+                    lf.setPredicate(Predicate.FlagA);
+                    lf.literal(k+1);
+                    lf.setPredicate(null);
+                    lf.deliver();
+
+                    lf = ctx.loopFactory(dock, 1);
+                    lf.sendToken(debugIn.getDataDestination(), new BitVector(1).set(reverse ? 1 : 0));
+                    lf.sendToken(debugIn.getDataDestination(), new BitVector(1).set(reverse ? 0 : 1));
+                    lf.sendToken(dock.getDataDestination(), new BitVector(1).set(reverse ? 1 : 0));
+                    lf.sendToken(dock.getDataDestination(), new BitVector(1).set(reverse ? 0 : 1));
+                    lf = lf.makeNext(2, true);
+
+                    // if a torpedo was lying in wait, the problem will be manifest as a "freezup"
+                    lf.abortLoopIfTorpedoPresent();
+
+                    lf.recvToken();
+                    lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
+                    lf.setPredicate(Predicate.NotFlagA);
+                    lf.sendToken(debugIn.getDataDestination(), new BitVector(1).set(0));
+                    lf.setPredicate(Predicate.FlagA);
+                    lf.sendToken(debugIn.getDataDestination(), new BitVector(1).set(1));
+                    lf.setPredicate(null);
+
+                    ctx.dispatch(fp);
+                    fp.flush();
+
+                    long kk;
+                    for(int i=0; i<4; i++) {
+                        kk = fp.recvWord().toLong();
+                        System.out.print("\rchecking " + dock + " (got "+(i+1)+")");
+                        if (kk != ((reverse ^ (i%2!=0)) ? k+1 : k)) {
+                            System.out.println();
+                            throw new RuntimeException(dock+" not properly initialized ("+(i+1)+")");
+                        }
+                    }
+                    System.out.println();
+                }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/loops/CodeBag.java b/src/edu/berkeley/fleet/loops/CodeBag.java
new file mode 100644 (file)
index 0000000..de14c71
--- /dev/null
@@ -0,0 +1,155 @@
+package edu.berkeley.fleet.loops;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+
+
+// QUESTION: does each dock mentioned by a context have a linear chain
+// of loops, or can it branch?
+
+//    - or should we use "sub-contexts" for that
+//        - advantage: it lets us convey the fact that a bunch of loops are dispatched together
+//    - should loops have an "invoke context" opcode?
+
+
+// FIXME: implement CodeBag compression
+
+/**
+ *  A CodeBag is a collection of Loops which obey these rules:
+ *
+ *    - A CodeBag has exclusive control of all docks mentioned by any of its Loops.
+ *    - A CodeBag includes a "starting loop" for every dock it mentions.
+ *    - When a CodeBag is spawned, it starts the "starting loop" on all of its docks.
+ *    - A loop may or may not have a successor.
+ *    - Control may transfer only two ways:
+ *        - If a loop has a successor, control will transfer to the successor when the loop finishes.
+ *        - A loop may explicitly transfer control to another loop via abortAndInvoke().  The
+ *          invoked loop must belong to the same Dock and the same CodeBag.
+ *    - A CodeBag finishes when all of its docks have finished executing a loop with no successor.
+ *
+ *  Definitions:
+ *    - A Move instruction is a blocking instruction if either its   tokenIn or dataIn bits are set.
+ *    - All other instructions  are non-blocking.
+ *    - A dock is quiescent if its instruction ring is empty.
+ *    - A dock is pre-quiescent if 
+ *        - all instructions which remain in the target dock's instruction
+ *          fifo are nonblocking instructions,
+ *        - either the docks' OLC=0 or all instructions which remain
+ *          in its instruction fifo are one-shot instructions
+ *        - after executing these remaining instructions, the dock's hatch is open
+ */
+
+/*
+ *                          SF         works       works @diff    ok for non   size    ships
+ * Dispatch Method       Crossings     @inbox?       docks?       tail call?   limit   consumed
+ * ------------------------------------------------------------------------------------------
+ * 
+ * Inline                    0           Y              N             N        Small  None
+ * 
+ * Inline literals           1           N              Y             Y        Tiny   None
+ *  w/ "dispatch"
+ * 
+ * Send CBD to               2+          N              Y             Y        None   None (mem ship)
+ * memory ship
+ * 
+ * Send token to             3+          Y              Y             Y        None   One Output Dock
+ * assistant outbox first
+ * 
+ * Release from FIFO         2           Y              Y             Y        Med    1x FIFO, but can be shared
+ * 
+ */
+
+public class CodeBag {
+
+    public final Fleet fleet;
+
+    private Program program = null;
+    private BitVector descriptor = null;
+    public DeferredBitVector getDescriptor() {
+        return new DeferredBitVector() {
+            public BitVector getBitVector() {
+                if (program==null) throw new RuntimeException();
+                seal();
+                return descriptor;
+            } };
+    }
+
+    LinkedHashMap<Dock,LoopFactory> startupLoopFactories = new LinkedHashMap<Dock,LoopFactory>();
+    ArrayList<LoopFactory> loopFactories = new ArrayList<LoopFactory>();
+
+    // FIXME: currently not used
+    private boolean sealed = false;
+    public boolean isSealed() { return sealed; }
+    public void seal() {
+        if (sealed) return;
+        for(LoopFactory lf : loopFactories) lf.flush_pending();
+        sealed = true;
+        if (program!=null) descriptor = program.addInstructions(emit());
+    }
+
+    public CodeBag(Fleet fleet) { this(fleet, null); }
+    public CodeBag(Program prog) { this(prog.fleet, prog); }
+    public CodeBag(Fleet fleet, Program prog) {
+        this.fleet = fleet;
+        this.program = prog;
+    }
+
+    public LoopFactory loopFactory(Dock dock, int count) { return loopFactory(dock, count, count==0); }
+    public LoopFactory loopFactory(Dock dock, int count, boolean torpedoable) {
+        LoopFactory ret = startupLoopFactories.get(dock);
+        if (ret == null) return new LoopFactory(this, dock, count, torpedoable);
+        while (ret.getNext()!=null)
+            ret = ret.getNext();
+        return ret.makeNext(count, torpedoable);
+    }
+
+    boolean autoflush = false;
+    public void setAutoflush(boolean a) { this.autoflush = a; }
+    public boolean getAutoflush() { return autoflush; }
+
+    public void emit(ArrayList<Instruction> ic) {
+        seal();
+        for(LoopFactory lf : startupLoopFactories.values())
+            lf.emit(ic);
+    }
+
+    private LoopFactory hack = null;
+    public void sendTorpedo(Dock dock) {
+        if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
+        hack.sendToken(dock.getInstructionDestination());
+    }
+    public void sendWord(DeferredBitVector bv, Destination dest) {
+        // problem: this isn't actually atomic -- two uncoordinated
+        // actors might invoke these commands at the same time
+        if (hack==null) hack = loopFactory(fleet.getShip("Timer",0).getDock("out"), 1);
+        hack.literal(bv);
+        hack.sendWord(dest);
+    }
+
+    public Instruction[] emit() {
+        ArrayList<Instruction> ic = new ArrayList<Instruction>();
+        emit(ic);
+        return (Instruction[])ic.toArray(new Instruction[0]);
+    }
+
+    public void dispatch(FleetProcess fp) { dispatch(fp, false); }
+    public void dispatch(FleetProcess fp, boolean flushWhenDone) {
+        ArrayList<Instruction> ai;
+        emit(ai = new ArrayList<Instruction>());
+        for(Instruction ins : ai)
+            fp.sendInstruction(ins);
+        if (flushWhenDone) fp.flush();
+    }
+
+    public void append(CodeBag ctx) {
+        if (sealed) throw new RuntimeException("already sealed");
+        // how to handle ship pools?
+        throw new RuntimeException("not implemented");
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/loops/LoopFactory.java b/src/edu/berkeley/fleet/loops/LoopFactory.java
new file mode 100644 (file)
index 0000000..5bdfc2a
--- /dev/null
@@ -0,0 +1,426 @@
+package edu.berkeley.fleet.loops;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+
+/**
+ *
+ *  A helper class for building loops of instructions.
+ *
+ *  This class abstracts away:
+ *    - The maximum size of a loop
+ *    - The maximum length of a "one shot" instruction sequence
+ *    - The looping/oneshot bit
+ *    - The outer loop counter
+ *    - The inner loop counter (opportunities to use it are auto-detected)
+ *
+ *  It also performs various optimizations and provides a more
+ *  convenient way of managing the predicate/interruptible fields.
+ *
+ *  To get the most compact coding, the components of a Move should be
+ *  performed in this order when possible, with no intervening commands:
+ *
+ *    1. recvToken()
+ *    2. recv()/collect()
+ *    3. sendToken()
+ *    4. deliver()/send()
+ *
+ */
+public class LoopFactory {
+
+    public final Dock dock;
+    public final String friendlyName;
+    public final int count;
+    public final boolean torpedoable;
+
+    private final CodeBag ctx;
+    private LoopFactory next = null;
+    private ArrayList<Instruction> instructions = new ArrayList<Instruction>();
+
+    /**
+     *  Creates a new loop.
+     *   @arg dock         the dock at which to execute the instructions
+     *   @arg friendlyName a descriptive string for debugging the compiler
+     *   @arg prev         a loop for which this is the successor loop (if any)
+     *   @arg count        the number of times to execute this loop; <tt>0</tt> means continue until torpedoed
+     */
+    LoopFactory(CodeBag ctx, Dock dock, int count) {
+        this(ctx, dock, count, count==0, dock.toString(), null);
+    }
+    LoopFactory(CodeBag ctx, Dock dock, int count, boolean torpedoable) {
+        this(ctx, dock, count, torpedoable, dock.toString(), null);
+    }
+    LoopFactory(CodeBag ctx, Dock dock, int count, String friendlyName) {
+        this(ctx, dock, count, count==0, friendlyName);
+    }
+    LoopFactory(CodeBag ctx, Dock dock, int count, boolean torpedoable, String friendlyName) {
+        this(ctx, dock, count, torpedoable, friendlyName, null);
+    }
+    private LoopFactory(CodeBag ctx, Dock dock, int count, boolean torpedoable, String friendlyName, LoopFactory prev) {
+        this.ctx = ctx;
+        this.dock = dock;
+        this.count = count;
+        if (count==0 && !torpedoable)
+            throw new RuntimeException("count==0 loops must be torpedoable");
+        this.torpedoable = torpedoable;
+        this.friendlyName = friendlyName;
+        ctx.loopFactories.add(this);
+        if (ctx.startupLoopFactories.get(dock) == null)
+            ctx.startupLoopFactories.put(dock, this);
+        if (prev != null) {
+            if (prev.getNext() != null) throw new RuntimeException();
+            prev.setNext(this);
+        }
+    }
+
+    public LoopFactory makeNext(int new_count) { return makeNext(new_count, null); }
+    public LoopFactory makeNext(int new_count, String newFriendlyName) { return makeNext(new_count, new_count==0, newFriendlyName); }
+    public LoopFactory makeNext(int new_count, boolean newTorpedoable) { return makeNext(new_count, newTorpedoable, null); }
+    public LoopFactory makeNext(int new_count, boolean newTorpedoable, String newFriendlyName) {
+        if (next != null) throw new RuntimeException("loop already has a successor");
+        return new LoopFactory(ctx, dock, new_count, newTorpedoable, newFriendlyName, this);
+    }
+    public LoopFactory getNext() { return next; }
+    private void setNext(LoopFactory next) {
+        if (this.next != null) throw new RuntimeException("attempt to setNext() twice");
+        if (ctx.isSealed()) throw new RuntimeException("context already sealed");
+        this.next = next;
+    }
+
+
+    // Building Loops //////////////////////////////////////////////////////////////////////////////
+
+    Predicate   predicate = Predicate.Default;
+    boolean     pending_interruptible = false;
+    boolean     pending_recvToken = false;
+    boolean     pending_recvOrCollect = false;
+    boolean     pending_latchData = false;
+    boolean     pending_latchPath = false;
+    boolean     pending_sendToken = false;
+    Path        pending_path = null;
+
+    private void addInstruction(Instruction inst) {
+        if (ctx.isSealed()) throw new RuntimeException("context already sealed");
+        instructions.add(inst);
+    }
+
+    void flush_pending() { flush_pending(false); }
+    void flush_pending(boolean pending_dataOut) {
+        if (!pending_recvToken &&
+            !pending_recvOrCollect &&
+            !pending_sendToken &&
+            !pending_dataOut) {
+            /*
+            if (pending_interruptible)
+                throw new RuntimeException("abortLoopIfTorpedoPresent() must be followed immediately by a Move (in LoopFactory for dock " + dock + ")");
+            */
+        } else {
+            addInstruction(new Move(dock,
+                                      predicate,
+                                      pending_interruptible,
+                                      pending_path==null ? null : pending_path,
+                                      pending_recvToken,
+                                      pending_recvOrCollect,
+                                      pending_latchData,
+                                      pending_latchPath,
+                                      pending_dataOut,
+                                      pending_sendToken));
+        }
+        pending_interruptible = false;
+        pending_recvToken = false;
+        pending_recvOrCollect = false;
+        pending_latchData = false;
+        pending_latchPath = false;
+        pending_sendToken = false;
+        pending_path = null;
+    }
+
+    public void interruptibleNop() {
+        flush_pending();
+        addInstruction(new Move(dock,
+                                  predicate,
+                                  true,
+                                  null,
+                                  false,
+                                  false,
+                                  false,
+                                  false,
+                                  false,
+                                  false));
+    }
+
+    /** sets the predicate which will be applied to subsequent instructions, or null for the default predicate */
+    public void setPredicate(Predicate p) {
+        if (p==null) p = Predicate.Default;
+        if (predicate==p) return;
+        flush_pending();
+        predicate = p;
+    }
+
+    /** must be followed immediately by a move-based instruction */
+    public void abortLoopIfTorpedoPresent() {
+        flush_pending();
+        if (!torpedoable) 
+            throw new RuntimeException("invocation of abortLoopIfTorpedoPresent() in a non-torpedoable LoopFactory");
+        pending_interruptible = true;
+    }
+
+    /** [either] */
+    public void recvToken() {
+        if (pending_recvToken || pending_recvOrCollect || pending_sendToken) flush_pending();
+        pending_recvToken = true;
+    }
+
+    /** [inboxes only] */
+    public void recv(boolean latchData, boolean latchPath) {
+        if (!dock.isInputDock()) throw new RuntimeException("recv() may only be used at input docks");
+        if (pending_recvOrCollect || pending_sendToken) flush_pending();
+        pending_recvOrCollect = true;
+        pending_latchData = latchData;
+        pending_latchPath = latchPath;
+    }
+
+    /** [outboxes only], will fuse with previous instruction if it was a recvToken() */
+    public void collect(boolean latchData, boolean latchPath) {
+        if (!dock.isOutputDock()) throw new RuntimeException("collect() may only be used at output docks");
+        if (pending_recvOrCollect || pending_sendToken) flush_pending();
+        pending_recvOrCollect = true;
+        pending_latchData = latchData;
+        pending_latchPath = latchPath;
+    }
+
+    /** [either], will fuse with previous instruction if it was a recvToken(), recv(), or collect() */
+    public void sendToken(Destination dest) { sendToken(dest, null); }
+    public void sendToken(Destination dest, BitVector signal) {
+        if (pending_sendToken) flush_pending();
+        pending_path = dock.getPath(dest, signal);
+        pending_sendToken = true;
+    }
+    public void sendToken(Dock dock) { sendToken(dock.getDataDestination()); }
+    public void sendToken(Dock dock, BitVector signal) { sendToken(dock.getDataDestination(), signal); }
+
+    public void sendTorpedo(Dock dock) { sendToken(dock.getInstructionDestination()); }
+
+    /** [inboxes only], will fuse with previous instruction if it was a sendToken() */
+    public void deliver() {
+        if (!dock.isInputDock()) throw new RuntimeException("deliver() may only be used at input docks");
+        flush_pending(true);
+    }
+
+    /** [inboxes only], will fuse with previous instruction if it was a sendToken() */
+    public void flush() {
+        if (!dock.isInputDock()) throw new RuntimeException("flush() may only be used at input docks");
+        flush_pending();
+        addInstruction(new Instruction.Flush(dock, predicate));
+    }
+
+    /** [outboxes only], will fuse with previous instruction if it was a sendToken() */
+    public void sendWord(Destination dest) { sendWord(dest, null); }
+    public void sendWord(Destination dest, BitVector signal) {
+        if (!dock.isOutputDock()) throw new RuntimeException("sendWord() may only be used at output docks");
+        if (pending_sendToken) flush_pending();
+        pending_path = dock.getPath(dest, signal);
+        flush_pending(true);
+    }
+    public void sendWord(Dock dock) { sendWord(dock.getDataDestination()); }
+    public void sendWord(Dock dock, BitVector signal) { sendWord(dock.getDataDestination(), signal); }
+    public void sendPacket() { sendWord((Destination)null); }
+
+    public void literal(String constantName) {
+        literal(dock.getConstant(constantName));
+    }
+
+    /** sets the data latch to a literal value */
+    public void literal(final DeferredBitVector literal) {
+        flush_pending();
+        if (literal instanceof BitVector) {
+            BitVector bv = (BitVector)literal;
+            boolean can_use_set = true;
+            for(int i=ctx.fleet.getSetWidth(); i<bv.length(); i++)
+                if (bv.get(i)!=bv.get(ctx.fleet.getSetWidth()-1)) {
+                    can_use_set = false;
+                    break;
+                }
+            if (can_use_set) {
+                addInstruction(new Instruction.Set(dock, predicate, SetDest.DataLatch, bv.toLong()));
+                return;
+            }
+        }
+
+        int counter = 0;
+        while(counter < dock.getShip().getFleet().getWordWidth()) counter += ctx.fleet.getShiftWidth();
+        while(counter > 0) {
+            final int counter_f = counter;
+            DeferredBitVector temp = new DeferredBitVector() {
+                    public BitVector getBitVector() {
+                        BitVector bv = literal.getBitVector();
+                        BitVector ret = new BitVector(dock.getShip().getFleet().getShiftWidth());
+                        for(int i=counter_f-1; i>=counter_f-ctx.fleet.getShiftWidth(); i--)
+                            if (i<bv.length())
+                                ret.set(i-(counter_f-ctx.fleet.getShiftWidth()), bv.get(i));
+                        return ret;
+                    }
+                };
+            Shift shift = new Shift(dock, predicate, temp);
+            addInstruction(shift);
+            counter -= ctx.fleet.getShiftWidth();
+        }
+    }
+
+    /** sets the data latch to a literal value */
+    public void literal(long literal) {
+        literal(new BitVector(ctx.fleet.getWordWidth()).set(literal));
+    }
+
+    /** sets the data latch to a code bag descriptor */
+    public void literal(CodeBag cb) {
+        literal(cb.getDescriptor());
+    }
+
+    /** sets the flags */
+    public void setFlags(Instruction.Set.FlagFunction newFlagA, Instruction.Set.FlagFunction newFlagB) {
+        flush_pending();
+        addInstruction(new Instruction.Set(dock,
+                                             predicate,
+                                             newFlagA,
+                                             newFlagB));
+    }
+
+    /** abort the loop immediately (if predicate is met) and invoke the successor loop */
+    public void abort() {
+        flush_pending();
+        addInstruction(new Instruction.Set(dock,
+                                             predicate,
+                                             SetDest.OuterLoopCounter,
+                                             0));
+    }
+
+    // Emitting Code //////////////////////////////////////////////////////////////////////////////
+
+    void optimize() {
+        flush_pending();
+        // FEATURE: find sequences of >2 adjacent identical instructions, replace with use of ILC
+        //          (requires Instruction.equals() be implemented)
+        // FEATURE: consider doing loop unrolling if two copies of the loop fit in the instruction buffer...
+        // FEATURE: clever instruction re-oredering?
+    }
+
+    /**
+     *  The code emitted by this method makes the following assumptions:
+     *
+     *   - The instructions emitted are dispatched in order
+     *   - At the time of dispatch, the dock must be pre-quiescent.
+     *
+     */
+    public void emit(ArrayList<Instruction> ic) {
+        emit(ic, dock.getInstructionFifoSize());
+    }
+    private void emit(ArrayList<Instruction> ic, int capacity) {
+        flush_pending();
+        optimize();
+
+        // the number of instructions after and including the first blocking instruction
+        int numInstructionsNotIncludingNonblockingPrefix = 0;
+        int loopSize = 0;
+        boolean blockingInstructionEncountered = false;
+
+        // Set the OLC (it might previously have been zero)
+        ic.add(new Set(dock, Predicate.IgnoreFlagD, SetDest.OuterLoopCounter, count==0 ? 1 : count));
+
+        boolean olc_loop = count!=1;
+        /*
+        if (count != 1 &&
+            (count==0 || count <= 63) &&
+            instructions.size()==1 &&
+            (instructions.get(0) instanceof Instruction.Move)) {
+            olc_loop = false;
+            if (count==0)
+                ic.add(new Instruction.Set(dock, Predicate.Default,
+                                           SetDest.InnerLoopCounter, SetSource.Infinity));
+            else
+                ic.add(new Instruction.Set(dock, Predicate.Default,
+                                           SetDest.InnerLoopCounter, count));
+        }
+        */
+
+        if (olc_loop) {
+            ic.add(new Instruction.Head(dock));
+        }
+
+        boolean firstTime = true;
+        while(true) {
+            for(Instruction i : instructions) {
+                if (!firstTime && i.predicate==Predicate.FlagD) continue;
+                if (i instanceof Move && (((Move)i).tokenIn || ((Move)i).dataIn))
+                    blockingInstructionEncountered = true;
+                if (blockingInstructionEncountered)
+                    numInstructionsNotIncludingNonblockingPrefix++;
+                loopSize++;
+                ic.add(i);
+            }
+            if (count!=0) break;
+            if (instructions.size()+loopSize+3 > capacity) break;
+            firstTime = false;
+            break;
+            //System.out.println("packing the loop!");
+        }
+
+        if (!olc_loop) {
+            if (numInstructionsNotIncludingNonblockingPrefix > capacity)
+                throw new RuntimeException("instruction sequence is too long for instruction fifo at " + dock);
+        } else {
+            if (count != 0) {
+                ic.add(new Instruction.Set(dock, Predicate.Default, SetDest.OuterLoopCounter, SetSource.Decrement));
+                if (blockingInstructionEncountered)
+                    numInstructionsNotIncludingNonblockingPrefix++;
+                loopSize++;
+            }
+        }
+        if (olc_loop) {
+            ic.add(new Instruction.Abort(dock, Predicate.FlagD));
+            loopSize++;
+        }
+        if (ctx.autoflush && next==null && dock.isInputDock()) {
+            ic.add(new Instruction.Flush(dock, Predicate.FlagD));
+            loopSize++;
+        }
+
+        // FIXME: need to somehow deal with count!=0 loops that are
+        // torpedoable; they need to wait for a torpedo to arrive
+        // after exhausting their count.
+
+        if (olc_loop) {
+            ic.add(new Instruction.Tail(dock));
+            if (loopSize > capacity)
+                throw new RuntimeException("instruction loop is too long for instruction fifo at " + dock);
+        }
+
+        if (next != null) {
+            if (!olc_loop) {
+                next.emit(ic, capacity - numInstructionsNotIncludingNonblockingPrefix);
+            } else {
+                //next.emit(ic, capacity - loopSize);
+                throw new RuntimeException("no support for successor loops when count!=1 yet");
+            }
+        }
+    }
+
+    void warn(String warning) {
+        System.err.println("warning: " + warning);
+    }
+
+    // Helpers //////////////////////////////////////////////////////////////////////////////
+
+    public void recvWord() { recv(true, false); }
+    public void recvPath() { recv(false, true); }
+    public void recvPacket() { recv(true, true); }
+    public void collectWord() { collect(true, false); }
+    public void collectPath() { collect(false, true); }
+    public void collectPacket() { collect(true, true); }
+
+}
diff --git a/src/edu/berkeley/fleet/loops/MemoryUtils.java b/src/edu/berkeley/fleet/loops/MemoryUtils.java
new file mode 100644 (file)
index 0000000..7a92a32
--- /dev/null
@@ -0,0 +1,331 @@
+package edu.berkeley.fleet.loops;
+import edu.berkeley.fleet.loops.*;
+import java.util.concurrent.Semaphore;
+import java.util.*;
+import java.net.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.api.Instruction.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import edu.berkeley.fleet.api.Instruction.Set.*;
+import edu.berkeley.fleet.api.Instruction.Set.SetDest;
+import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+public class MemoryUtils {
+
+    public static void readMem(FleetProcess fp,
+                               ShipPool pool,
+                               Ship memory,
+                               long offset,
+                               BitVector[] vals) throws RuntimeException {
+        doMem(true, fp, pool, memory, offset, vals);
+    }
+
+    public static void writeMem(FleetProcess fp,
+                               ShipPool pool,
+                                Ship memory,
+                                long offset,
+                                long[] vals) throws RuntimeException {
+        doMem(false, fp, pool, memory, offset, long2bv(fp.getFleet(), vals));
+    }
+
+    public static void writeMem(FleetProcess fp,
+                               ShipPool pool,
+                                Ship memory,
+                                long offset,
+                                BitVector[] vals) throws RuntimeException {
+        doMem(false, fp, pool, memory, offset, vals);
+    }
+
+    /*
+    public static void clearMem(FleetProcess fp,
+                                Ship memory,
+                                ShipPool pool,
+                                long offset,
+                                long count) throws RuntimeException {
+        if (fp.getFleet() != memory.getFleet())
+            throw new RuntimeException("Fleet mismatch");
+
+        Ship counter1 = pool.allocateShip("Counter");
+        Ship counter2 = pool.allocateShip("Counter");
+        //Ship alu      = pool.allocateShip("Alu");
+
+        final Dock debugIn     = fp.getDebugInputDock();
+
+        CodeBag ctx = new CodeBag(fp.getFleet());
+        LoopFactory lf;
+
+        lf = ctx.loopFactory(counter1.getDock("inOp"), 1);
+        lf.literal(counter1.getDock("inOp").getConstant("COUNT"));
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter1.getDock("in1"), 1);
+        lf.literal(count);
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter1.getDock("in2"), 1);
+        lf.literal(1);
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter1.getDock("out"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvToken();
+        lf.collect();
+        lf.send(memory.getDock("inAddrWrite").getDataDestination());
+
+        lf = ctx.loopFactory(memory.getDock("inDataWrite"), 0);
+        lf.literal(0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.deliver();
+
+        lf = ctx.loopFactory(memory.getDock("inAddrWrite"), 1);
+        lf.sendToken(counter1.getDock("out").getDataDestination());
+        lf = lf.makeNext(0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvWord();
+        lf.deliver();
+        lf.sendToken(counter1.getDock("out").getDataDestination());
+
+        lf = ctx.loopFactory(memory.getDock("out"), 0);
+        lf.recvToken();
+        lf.recvWord();
+        lf.send(counter2.getDock("in2").getDataDestination());
+
+        lf = ctx.loopFactory(counter2.getDock("inOp"), 1);
+        lf.literal(counter2.getDock("inOp").getConstant("DROP_C1_V2"));
+        lf.deliver();
+        lf.literal(counter2.getDock("inOp").getConstant("PASS_C1_V2"));
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter2.getDock("in2"), 0);
+        lf.recvWord();
+        lf.deliver();
+
+        fp.sendToken(counter1.getDock("out").getInstructionDestination());
+        fp.sendToken(memory.getDock("inDataWrite").getInstructionDestination());
+        fp.sendToken(memory.getDock("inAddrWrite").getInstructionDestination());
+        fp.sendToken(memory.getDock("out").getInstructionDestination());
+        fp.sendToken(counter2.getDock("in2").getInstructionDestination());
+        
+        lf = ctx.loopFactory(counter2.getDock("in1"), 1);
+        lf.literal(count-1);
+        lf.deliver();
+        lf.literal(1);
+        lf.deliver();
+        
+        lf = ctx.loopFactory(counter2.getDock("out"), 1);
+        lf.collect();
+        lf.send(debugIn.getDataDestination());
+
+        pool.releaseShip(counter1);
+        pool.releaseShip(counter2);
+        //pool.releaseShip(alu);
+    }
+    */
+
+    public static void doMem(final boolean read,
+                             final FleetProcess fp,
+                             final ShipPool pool,
+                             final Ship memory,
+                             final long offset,
+                             final BitVector[] vals) throws RuntimeException {
+        if (fp.getFleet() != memory.getFleet())
+            throw new RuntimeException("Fleet mismatch");
+
+        final Dock inAddrWrite = memory.getDock("inAddrWrite");
+        final Dock inDataWrite = memory.getDock("inDataWrite");
+        final Dock inAddrRead  = memory.getDock("inAddrRead");
+        final Dock out         = memory.getDock("out");
+        final Dock debugIn     = read ? fp.getDebugInputDock() : null;
+        if (debugIn!=null) pool.allocateShip(debugIn.getShip());
+
+        Ship counter = pool.allocateShip("Counter");
+        Dock counter_in1  = counter.getDock("in1");
+        Dock counter_in2  = counter.getDock("in2");
+        Dock counter_inOp = counter.getDock("inOp");
+        Dock counter_out  = counter.getDock("out");
+
+        Ship alu = pool.allocateShip("Alu");
+
+        CodeBag ctx = new CodeBag(fp.getFleet());
+        LoopFactory lf;
+        if (read) {
+            lf = ctx.loopFactory(inAddrRead, 0);
+            lf.abortLoopIfTorpedoPresent();
+            lf.sendToken(counter_out);
+            lf.recvWord();
+            lf.deliver();
+        } else {
+            lf = ctx.loopFactory(inAddrWrite, 0);
+            lf.sendToken(counter_out);
+            lf.abortLoopIfTorpedoPresent();
+            lf.recvWord();
+            lf.deliver();
+            lf = ctx.loopFactory(inDataWrite, 0);
+            lf.abortLoopIfTorpedoPresent();
+            lf.recvWord();
+            lf.deliver();
+        }
+
+        lf = ctx.loopFactory(counter_in1, 1);
+        lf.literal(vals.length);
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter_in2, 1);
+        lf.literal(1);
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter_inOp, 1);
+        lf.literal("COUNT");
+        lf.deliver();
+
+        lf = ctx.loopFactory(counter_out, 0);
+        lf.recvToken();
+        lf.abortLoopIfTorpedoPresent();
+        lf.collectWord();
+        lf.sendWord(alu.getDock("in1"));
+        lf.sendToken(alu.getDock("in2"));
+        lf.sendToken(alu.getDock("inOp"));
+
+        lf = ctx.loopFactory(alu.getDock("in1"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvWord();
+        lf.deliver();
+
+        lf = ctx.loopFactory(alu.getDock("in2"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvToken();
+        lf.literal(offset);
+        lf.deliver();
+
+        lf = ctx.loopFactory(alu.getDock("inOp"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvToken();
+        lf.literal("ADD");
+        lf.deliver();
+
+        lf = ctx.loopFactory(alu.getDock("out"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.collectWord();
+        lf.sendWord(read ? inAddrRead : inAddrWrite);
+
+        lf = ctx.loopFactory(out, 0);
+        if (read) lf.recvToken();
+        lf.abortLoopIfTorpedoPresent();
+        lf.collectWord();
+        if (read) lf.sendWord(debugIn.getDataDestination());
+
+        if (read) {
+            lf = ctx.loopFactory(debugIn, 0);
+            lf.sendToken(out);
+            lf.abortLoopIfTorpedoPresent();
+            lf.recvWord();
+            lf.deliver();
+        }
+
+        ctx.dispatch(fp);
+
+        for(int i=vals.length-1; i>=0; i--) {
+            if (!read)
+                fp.sendWord(inDataWrite.getDataDestination(), vals[i]);
+            if (read) {
+                BitVector outv = fp.recvWord();
+                vals[i] = outv;
+            }
+            int pct = (int)Math.ceil(100.0*((double)(vals.length-1-i)/((double)(vals.length-1))));
+            String status = i + "/" + (vals.length-1) + "= " + pct + "%";
+            if (read) System.out.print("\rread from address: " + status + ", got " + vals[i] + " = " + vals[i].toLong()+"           ");
+            else      System.out.print("\rwrote to address: " + status +"           ");
+        }
+        fp.flush();
+
+        if (read) {
+            fp.sendToken(inAddrRead.getInstructionDestination());
+            fp.sendToken(debugIn.getInstructionDestination());
+        } else {
+            fp.sendToken(inAddrWrite.getInstructionDestination());
+            fp.sendToken(inDataWrite.getInstructionDestination());
+        }
+        fp.sendToken(alu.getDock("in1").getInstructionDestination());
+        fp.sendToken(alu.getDock("in2").getInstructionDestination());
+        fp.sendToken(alu.getDock("inOp").getInstructionDestination());
+        fp.sendToken(alu.getDock("out").getInstructionDestination());
+        fp.sendToken(counter_out.getInstructionDestination());
+        fp.sendToken(out.getInstructionDestination());
+        System.out.println();
+
+        pool.releaseShip(alu);
+        pool.releaseShip(counter);
+        if (read) pool.releaseShip(debugIn.getShip());
+    }
+
+    private static BitVector[] long2bv(Fleet fleet, long[] initialValues) {
+        BitVector[] bv = new BitVector[initialValues.length];
+        for(int i=0; i<initialValues.length; i++)
+            bv[i] = new BitVector(fleet.getWordWidth()).set(initialValues[i]);
+        return bv;
+    }
+
+    public static void putMemoryShipInDispatchMode(FleetProcess fp, Ship memoryShip) {
+        CodeBag ctx = new CodeBag(fp.getFleet());
+        LoopFactory lf;
+
+        lf = ctx.loopFactory(memoryShip.getDock("out"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.collectPacket();
+        lf.sendPacket();
+
+        lf = ctx.loopFactory(memoryShip.getDock("inCBD"), 0);
+        lf.abortLoopIfTorpedoPresent();
+        lf.recvWord();
+        lf.deliver();
+
+        ctx.dispatch(fp);
+    }
+
+    public static void removeMemoryShipFromDispatchMode(FleetProcess fp, Ship memoryShip) {
+        fp.sendToken(memoryShip.getDock("out").getInstructionDestination());
+        fp.sendToken(memoryShip.getDock("inCBD").getInstructionDestination());
+    }
+
+    public static void main(String[] s) throws Exception {
+        Random random = new Random(System.currentTimeMillis());
+        Fleet fleet = new Fpga();
+        FleetProcess fp = fleet.run(new Instruction[0]);
+        //Ship memory = fleet.getShip("DDR2",0);
+        Ship memory = fleet.getShip("Dvi",0);
+        //Ship memory = fleet.getShip("Memory",0);
+
+        //int size = (548 * 478) / 2;
+        int size = 2048;
+
+        BitVector[] vals  = new BitVector[size];
+        BitVector[] vals2 = new BitVector[size];
+
+        for(int i=0; i<vals.length; i++) {
+            vals[i] = new BitVector(fleet.getWordWidth()).set(random.nextLong());
+            for(int j=36; j<vals[i].length(); j++)
+                vals[i].set(j, false);
+            vals[i].set(1, false);
+        }
+
+        BitVector bv = new BitVector(fleet.getWordWidth());
+        /*
+        for(int i=0; i<bv.length(); i++) bv.set(i, true);
+        for(int i=0; i<vals.length; i++)
+            vals[i] = bv;
+        */
+        ShipPool pool = new ShipPool(fleet);
+        writeMem(fp, pool, memory, 0, vals);
+        readMem(fp, pool, memory, 0, vals2);
+        int fails = 0;
+        for(int i=0; i<vals.length; i++)
+            if (!vals[i].equals(vals2[i])) {
+                System.out.println("disagreement!  on index " + i + "\n  "+vals[i]+"\n  "+vals2[i]);
+                fails++;
+            }
+        System.out.println("done! ("+fails+" failures)");
+    }
+}
diff --git a/src/edu/berkeley/fleet/loops/Program.java b/src/edu/berkeley/fleet/loops/Program.java
new file mode 100644 (file)
index 0000000..bd30f30
--- /dev/null
@@ -0,0 +1,152 @@
+package edu.berkeley.fleet.loops;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+import java.net.*;
+import java.io.*;
+
+/**
+ *  A program is a collection of CodeBags resident in a particular Memory.
+ *
+ *  FIXME: should every Program have an associated ShipPool?
+ */
+public class Program {
+
+    public final Fleet fleet;
+    public final Ship memoryShip;
+
+    private CodeBag end = null;
+
+    private long leastUnallocatedAddress;
+    private long startAddress;
+
+    private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+    private ArrayList<Instruction> all_instructions = new ArrayList<Instruction>();
+    
+    public Program(Ship memoryShip) { this(memoryShip, 0); }
+    public Program(Ship memoryShip, long startAddress) {
+        this.fleet = memoryShip.getFleet();
+        this.memoryShip = memoryShip;
+        this.startAddress = startAddress;
+        this.leastUnallocatedAddress = startAddress;
+    }
+
+    public Destination getCBDDestination() {
+        return memoryShip.getDock("inCBD").getDataDestination();
+    }
+
+    public long run(FleetProcess fp, CodeBag run, ShipPool pool) {
+        Ship timer    = pool.allocateShip("Timer");
+        Ship debug    = pool.allocateShip("Debug");
+        Dock debugIn  = debug.getDock("in");
+        
+        LoopFactory lf;
+
+        CodeBag start = new CodeBag(fleet, this);
+        lf = start.loopFactory(timer.getDock("out"), 1);
+        lf.collectWord();
+        lf.sendWord(debugIn.getDataDestination());
+        lf = start.loopFactory(debugIn, 1);
+        lf.recvWord();
+        lf.deliver();
+        lf.recvWord();
+        lf.deliver();
+        start.sendWord(run.getDescriptor(), getCBDDestination());
+
+        CodeBag done  = end;
+        lf = done.loopFactory(timer.getDock("out"), 1);
+        lf.collectWord();
+        lf.sendWord(debugIn.getDataDestination());
+       
+        start.seal();
+        done.seal();
+        
+        install(fp, pool);
+        
+        MemoryUtils.putMemoryShipInDispatchMode(fp, memoryShip);
+        fp.sendWord(getCBDDestination(), start.getDescriptor().getBitVector());
+        fp.flush();
+        long now = System.currentTimeMillis();
+        System.out.println("waiting for timestamps to come back...");
+        BitVector bv1 = fp.recvWord();
+        System.out.println();
+        System.out.println("got start time (bv="+bv1+" = "+bv1.toLong()+")");
+        BitVector bv2 = fp.recvWord();
+        System.out.println("got end time (bv="+bv2+" = "+bv2.toLong()+")");
+        long ret = (bv2.toLong()-bv1.toLong());
+        long simtime = (System.currentTimeMillis()-now)/1000;
+        System.out.println("total run time = " + ret + " gate delays, " + (ret/40) + "ns (simulation time="+simtime+"sec)");
+        MemoryUtils.removeMemoryShipFromDispatchMode(fp, memoryShip);
+
+        return ret;
+    }
+
+    public void dump(String file) {
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos));
+            for(int i=0; i<codeBags.size(); i++)
+                for(Instruction in : codeBags.get(i).emit())
+                    pw.println(in);
+            pw.flush();
+            pw.close();
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    public CodeBag getEndProgramCodeBag() {
+        if (end != null) return end;
+        end = new CodeBag(fleet, this);
+        return end;
+    }
+
+    /** the provided pool should be a sibling of the one which holds this Program's instructions */
+    public void install(FleetProcess fp, ShipPool pool) {
+        for(int i=0; i<codeBags.size(); i++)
+            codeBags.get(i).emit();
+        BitVector[] bvs = new BitVector[(int)(leastUnallocatedAddress-startAddress)];
+        for(int i=0; i<bvs.length; i++) {
+            bvs[i] = fleet.encodeInstruction(all_instructions.get(i), memoryShip.getDock("out"));
+        }
+        MemoryUtils.writeMem(fp, pool, memoryShip, startAddress, bvs);
+    }
+
+    BitVector addInstructions(Instruction[] instructions) {
+
+        // CodeBags are "daisy chained" to eliminate any possibility
+        // of cloggage at the inCBD port as a result of more CBD's
+        // being dispatched than the maximum number that fit in the
+        // data fifo at that dock.
+
+        int MAX_BAG_SIZE = (1<<6)-1;
+
+        // FUZZ is an estimate of the number of instructions required
+        // to dispatch a code bag descriptor
+        int FUZZ = 4;
+
+        if (instructions.length <= MAX_BAG_SIZE) {
+            BitVector descriptor = new BitVector(fleet.getWordWidth());
+            descriptor.set( (leastUnallocatedAddress<<6) | instructions.length );
+            leastUnallocatedAddress += instructions.length;
+            for(Instruction i : instructions)
+                all_instructions.add(i);
+            return descriptor;
+        }
+
+        System.out.println("warning: code bag size is "+instructions.length+
+                           ", which exceeds maximum of "+MAX_BAG_SIZE+
+                           "; breaking into multiple bags");
+        
+        Instruction[] rest = new Instruction[instructions.length - (MAX_BAG_SIZE-FUZZ)];
+        System.arraycopy(instructions, MAX_BAG_SIZE-FUZZ, rest, 0, rest.length);
+        
+        DeferredBitVector restbag = addInstructions(rest);
+        CodeBag ctx = new CodeBag(fleet);
+        ctx.sendWord(restbag, getCBDDestination());
+        Instruction[] fuzz = ctx.emit();
+        if (fuzz.length > FUZZ) throw new RuntimeException("FUZZ="+FUZZ+", fuzz.length="+fuzz.length);
+        Instruction[] self = new Instruction[fuzz.length+MAX_BAG_SIZE-FUZZ];
+        System.arraycopy(instructions, 0, self, 0, MAX_BAG_SIZE-FUZZ);
+        System.arraycopy(fuzz, 0, self, MAX_BAG_SIZE-FUZZ, fuzz.length);
+        return addInstructions(self);
+    }
+
+}
\ No newline at end of file
diff --git a/src/edu/berkeley/fleet/loops/ShipPool.java b/src/edu/berkeley/fleet/loops/ShipPool.java
new file mode 100644 (file)
index 0000000..23b9a04
--- /dev/null
@@ -0,0 +1,64 @@
+package edu.berkeley.fleet.loops;
+import java.util.*;
+import edu.berkeley.fleet.api.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+
+/**
+ *  A ShipPool keeps track of ships which have been "allocated" and
+ *  are in use.  ShipPools may be arranged in a hierarchy; allocating
+ *  a ship in one pool will allocate it in all ancestors.
+ */
+public class ShipPool implements Iterable<Ship> {
+
+    public final Fleet fleet;
+    public final ShipPool ancestor;
+
+    private HashSet<Ship> allocatedShips = new HashSet<Ship>();
+
+    public ShipPool(Fleet fleet) { this(fleet, null); }
+    public ShipPool(ShipPool ancestor) { this(ancestor.fleet, ancestor); }
+    public ShipPool(Fleet fleet, ShipPool ancestor) {
+        this.fleet = fleet;
+        this.ancestor = ancestor;
+    }
+
+    public Iterator<Ship> iterator() { return allocatedShips.iterator(); }
+
+    public void allocateShip(Ship ship) {
+        if (allocatedShips.contains(ship))
+            throw new RuntimeException("already allocated!");
+        allocatedShips.add(ship);
+    }
+
+    /** allocate a ship */
+    public Ship allocateShip(String type) {
+        Ship ship = null;
+        if (ancestor != null) {
+            ship = ancestor.allocateShip(type);
+        } else {
+            for(int i=0; ; i++) {
+                ship = fleet.getShip(type, i);
+                if (ship==null)
+                    throw new RuntimeException("no more ships of type " + type);
+                if (!allocatedShips.contains(ship)) break;
+            }
+        }
+        allocatedShips.add(ship);
+        return ship;
+    }
+
+    /** release an allocated ship */
+    public void releaseShip(Ship ship) {
+        if (!allocatedShips.contains(ship))
+            throw new RuntimeException("ship " + ship + " released but was not allocated");
+        allocatedShips.remove(ship);
+        if (ancestor != null) ancestor.releaseShip(ship);
+    }
+
+    public void releaseAll() {
+        HashSet<Ship> toRelease = new HashSet<Ship>();
+        toRelease.addAll(allocatedShips);
+        for (Ship ship : toRelease)
+            releaseShip(ship);
+    }
+}
diff --git a/src/edu/berkeley/fleet/marina/MarinaDestination.java b/src/edu/berkeley/fleet/marina/MarinaDestination.java
new file mode 100644 (file)
index 0000000..8e1d032
--- /dev/null
@@ -0,0 +1,22 @@
+package edu.berkeley.fleet.marina;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+
+public class MarinaDestination extends Destination {
+
+    private final BitVector bv;
+    private final MarinaFleet marina;
+
+    public MarinaDestination(MarinaFleet marina, BitVector bv) {
+        super(marina.onlyDock);
+        this.marina = marina;
+        bv.setImmutable();
+        this.bv = bv;
+    }
+
+    public String toString() {
+        return bv.toString();
+    }
+
+}
+
diff --git a/src/edu/berkeley/fleet/marina/MarinaDock.java b/src/edu/berkeley/fleet/marina/MarinaDock.java
new file mode 100644 (file)
index 0000000..059a420
--- /dev/null
@@ -0,0 +1,28 @@
+package edu.berkeley.fleet.marina;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+
+public class MarinaDock extends FleetTwoDock {
+
+    public Destination getDataDestination() { return null; }
+    public Destination getInstructionDestination() { return null; }
+    public int         getInstructionFifoSize() { return 0; }
+    public Path getPath(Destination d,BitVector bv) { return null; }
+
+    private boolean isInput;
+    public boolean isInputDock() { return isInput; }
+    public boolean isOutputDock() { return !isInput; }
+
+    public MarinaDock(MarinaShip ship, boolean isInput) {
+        super(ship, null);
+        this.isInput = isInput;
+        ship.addDock(this);
+    }
+
+    public String getName() { return "fakedock"; }
+    public BitVector getDockConstant(String s) {
+        throw new RuntimeException("not supported");
+    }
+
+}
+
diff --git a/src/edu/berkeley/fleet/marina/MarinaFleet.java b/src/edu/berkeley/fleet/marina/MarinaFleet.java
new file mode 100644 (file)
index 0000000..192e9b6
--- /dev/null
@@ -0,0 +1,43 @@
+package edu.berkeley.fleet.marina;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.*;
+import java.util.*;
+
+public class MarinaFleet extends FleetTwoFleet {
+
+    MarinaShip fakeShip = new MarinaShip(this);
+    MarinaDock onlyDock = new MarinaDock(fakeShip, true);
+
+    public MarinaFleet() {
+        // use "internal encoding"
+        super(true);
+    }
+
+    public BitVector   encodeInstruction(Dock dispatchFrom, Instruction instruction) {
+        return encodeInstruction(instruction, dispatchFrom);
+    }
+
+    public Iterator<Ship> iterator() {
+        HashSet hs = new HashSet<Ship>();
+        hs.add(fakeShip);
+        return hs.iterator();
+    }
+
+    public Ship getShip(String type, int ordinal) {
+        throw new RuntimeException("not implemented");
+    }
+
+    public FleetProcess run(Instruction[] instructions) {
+        throw new RuntimeException("not implemented");
+    }
+
+    public BitVector getDestAddr(Path path) {
+        if (path==null) return new BitVector(0);
+        return ((MarinaPath)path).bv;
+    }
+
+    public Dock getOnlyInputDock() {
+        return onlyDock;
+    }
+}
diff --git a/src/edu/berkeley/fleet/marina/MarinaPath.java b/src/edu/berkeley/fleet/marina/MarinaPath.java
new file mode 100644 (file)
index 0000000..84cb47f
--- /dev/null
@@ -0,0 +1,39 @@
+package edu.berkeley.fleet.marina;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+
+public class MarinaPath extends FleetTwoPath {
+
+    public static final int SIGNAL_BIT_INDEX = 13;
+
+    private final MarinaFleet marina;
+    final BitVector bv;
+
+    public MarinaPath(MarinaFleet marina, BitVector bv) {
+        this.marina = marina;
+        this.bv = bv;
+        bv.setImmutable();
+    }
+
+    public String toString() { return "MarinaPath("+bv+")"; }
+
+    public BitVector getSignal() {
+        BitVector ret = new BitVector(1);
+        ret.set(0, bv.get(SIGNAL_BIT_INDEX));
+        return ret;
+    }
+    
+    public Dock getSource() { return marina.onlyDock; }
+    public Destination getDestination() {
+        BitVector bvd = new BitVector(bv.length()-1);
+        int j=0;
+        for(int i=0; i<bv.length(); i++)
+            if (i!=SIGNAL_BIT_INDEX)
+                bvd.set(j++, bv.get(i));
+        return new MarinaDestination(marina, bvd);
+    }
+    public int getBufferingAmount() { return 1; }
+    public int getLatencyMetric() { return 0; }
+
+}
+
diff --git a/src/edu/berkeley/fleet/marina/MarinaShip.java b/src/edu/berkeley/fleet/marina/MarinaShip.java
new file mode 100644 (file)
index 0000000..c2b8aad
--- /dev/null
@@ -0,0 +1,23 @@
+package edu.berkeley.fleet.marina;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import java.util.*;
+
+public class MarinaShip extends FleetTwoShip {
+
+    private HashSet<MarinaDock> docks = new HashSet<MarinaDock>();
+
+    public Iterator<Dock> iterator() { return (Iterator<Dock>)(Object)docks.iterator(); }
+
+    private MarinaFleet fleet;
+
+    /*package*/ void addDock(MarinaDock dock) { docks.add(dock); }
+
+    public MarinaShip(MarinaFleet fleet) {
+        super(fleet, null);
+        this.fleet = fleet;
+    }
+
+    public String getType() { return "MarinaShip"; }
+}
+
diff --git a/src/edu/berkeley/fleet/two/DockDescription.java b/src/edu/berkeley/fleet/two/DockDescription.java
new file mode 100644 (file)
index 0000000..d3646b8
--- /dev/null
@@ -0,0 +1,43 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** NOT YET FINALIZED: A description of a dock on a ship */
+public class DockDescription {
+
+    private final ShipDescription ship;
+    private final String name;
+    private final boolean inbox;
+    private final boolean left;
+    private final boolean isDockless;
+    private final HashMap<String,BitVector> constants = new HashMap<String,BitVector>();
+
+    DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) {
+        this(ship, name, left, inbox, false);
+    }
+    DockDescription(ShipDescription ship, String name, boolean left, boolean inbox, boolean isDockless) {
+        this.left = left;
+        this.ship = ship;
+        this.name = name;
+        this.inbox = inbox;
+        this.isDockless = isDockless;
+    }
+
+    public String  getName() { return name; }
+    public boolean isInputDock() { return inbox; }
+    public boolean isOutputDock() { return !inbox; }
+    public boolean isDockless() { return isDockless; }
+
+    /** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */
+    boolean isLeft() { return left; }
+
+    /** Searches the dock-specific constants first, then ship-wide constants */
+    public BitVector getConstant(String name) {
+        BitVector ret = constants.get(name);
+        if (ret == null) ret = ship.getConstant(name);
+        return ret;
+    }
+
+    void addConstant(String s, BitVector c) { constants.put(s, c); }
+}
diff --git a/src/edu/berkeley/fleet/two/FleetTwoDock.java b/src/edu/berkeley/fleet/two/FleetTwoDock.java
new file mode 100644 (file)
index 0000000..e4b3148
--- /dev/null
@@ -0,0 +1,30 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+
+/** A dock on a ship */
+public abstract class FleetTwoDock extends Dock {
+
+    private final DockDescription dockDescription;
+
+    public FleetTwoDock(Ship ship, DockDescription dockDescription) {
+        super(ship);
+        this.dockDescription = dockDescription;
+    }
+
+    public String getName() { return dockDescription.getName(); }
+
+    public BitVector getDockConstant(String s) { return dockDescription.getConstant(s); }
+
+    public boolean isInputDock() { return dockDescription.isInputDock(); }
+
+    public boolean isOutputDock() { return !dockDescription.isInputDock(); }
+
+    public BitVector getConstant(String constantName) {
+        BitVector bv = dockDescription.getConstant(constantName);
+        if (bv==null)
+            throw new RuntimeException("unknown constant \""+constantName+"\" on dock " + this);
+        return bv;
+    }
+
+}            
diff --git a/src/edu/berkeley/fleet/two/FleetTwoFleet.java b/src/edu/berkeley/fleet/two/FleetTwoFleet.java
new file mode 100644 (file)
index 0000000..7936ad0
--- /dev/null
@@ -0,0 +1,473 @@
+package edu.berkeley.fleet.two;
+import java.io.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.util.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Instruction.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+
+/** common subclass for the "FleetTwo" generation of processors, all 37-bit wide, with AM33 encoding */
+public abstract class FleetTwoFleet extends Fleet {
+
+    private final boolean hack = "true".equals(System.getProperty("inverted-dc-bit-hack", "false"));
+
+    public final Mask PACKET_TOKEN;
+    public final Mask PACKET_IS_TOKEN;
+    public final Mask PACKET_DATA;
+    public final Mask PACKET_SIGNAL;
+    public final Mask PACKET_DEST;
+
+    public final Mask CBD_SIZE;
+    public final Mask CBD_OFFSET;
+
+    public final Mask WHOLE_WORD;
+    public final Mask DISPATCH_PATH;
+    public final Mask DISPATCH_INSTR;
+    public final Mask NOT_INTERRUPTIBLE;
+    public final Mask IS_INTERRUPTIBLE;
+    public final Mask P;
+    public final Mask P_NOT_A;
+    public final Mask P_A;
+    public final Mask P_NOT_B;
+    public final Mask P_B;
+    public final Mask P_UNUSED;
+    public final Mask P_OLC_ZERO;
+    public final Mask P_OLC_NONZERO;
+    public final Mask P_ALWAYS;
+
+    public final Mask SHIFT;
+
+    public final Mask TAIL;
+    public final Mask HEAD;
+    public final Mask ABORT;
+
+    public final Mask MOVE;
+    public final Mask TI;
+    public final Mask DI;
+    public final Mask FLUSH;
+    public final Mask DC;
+    public final Mask DO;
+    public final Mask TO;
+    public final Mask PATH_IMMEDIATE;
+    public final Mask PATH_DATA;
+    public final Mask PATH_NOCHANGE;
+
+    public final Mask SET_OLC_FROM_IMMEDIATE;
+    public final Mask SET_OLC_FROM_DATA_LATCH;
+    public final Mask SET_OLC_FROM_OLC_MINUS_ONE;
+
+    public final Mask SET_ILC_FROM_IMMEDIATE;
+    public final Mask SET_ILC_FROM_INFINITY;
+    public final Mask SET_ILC_FROM_DATA_LATCH;
+
+    public final Mask SET_IMMEDIATE;
+    public final Mask SET_IMMEDIATE_EXTEND;
+
+    public final Mask SET_FLAGS;
+    public final Mask SET_FLAGS_A;
+    public final Mask SET_FLAGS_B;
+    public final Mask SET_FLAGS_VALUE_A;
+    public final Mask SET_FLAGS_VALUE_NOT_A;
+    public final Mask SET_FLAGS_VALUE_B;
+    public final Mask SET_FLAGS_VALUE_NOT_B;
+    public final Mask SET_FLAGS_VALUE_C;
+    public final Mask SET_FLAGS_VALUE_NOT_C;
+
+    public final int  WIDTH_WORD;
+    public final int  WIDTH_PACKET;
+
+    public final int DataLatch_WIDTH;
+    private final long mask;
+
+    public FleetTwoFleet() { this(false); }
+
+    public FleetTwoFleet(boolean useInternalEncoding) {
+        PACKET_TOKEN               = new Mask("v.................................................");
+        PACKET_IS_TOKEN            = new Mask("1.................................................");
+        PACKET_DATA                = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............");
+        PACKET_SIGNAL              = new Mask("......................................v...........");
+        PACKET_DEST                = new Mask(".......................................vvvvvvvvvvv");
+
+        CBD_SIZE                   = new Mask("...............................vvvvvv");
+        CBD_OFFSET                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......");
+
+        WHOLE_WORD                 = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
+
+        if (useInternalEncoding) {
+
+            DISPATCH_PATH              = new Mask("v....................................");
+            DISPATCH_INSTR             = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
+            P                          = new Mask(".vvvvvv..............................");
+            P_NOT_A                    = new Mask(".010001..............................");
+            P_A                        = new Mask(".010010..............................");
+            P_NOT_B                    = new Mask(".010100..............................");
+            P_B                        = new Mask(".011000..............................");
+            P_UNUSED                   = new Mask(".111111..............................");
+            P_OLC_ZERO                 = new Mask(".100000..............................");
+            P_OLC_NONZERO              = new Mask(".010000..............................");
+            P_ALWAYS                   = new Mask(".000000..............................");
+
+            HEAD                       = new Mask(".......1.............................");
+            ABORT                      = new Mask("........1......1.........000100000001");
+            TAIL                       = new Mask(".........1...........................");
+
+            // actually "is interruptible"
+            NOT_INTERRUPTIBLE          = new Mask("...........0....0....................");
+            IS_INTERRUPTIBLE           = new Mask("...........1....1....................");
+
+            SHIFT                      = new Mask("..........1......1vvvvvvvvvvvvvvvvvvv");
+            SET_IMMEDIATE              = new Mask("..........1......0.....vvvvvvvvvvvvvv");
+            SET_IMMEDIATE_EXTEND       = new Mask("..........1......0....v..............");
+            MOVE                       = new Mask("............1........................");
+            TI                         = new Mask("............1.....1..................");
+            DI                         = new Mask("............1......1.................");
+            FLUSH                      = new Mask("..........1......0.....011...........");
+            DC                         = new Mask("............1.......1................");
+            DO                         = new Mask("............1........1...............");
+            TO                         = new Mask("............1.........1..............");
+            PATH_IMMEDIATE             = new Mask("............1..........1vvvvvvvvvvvvv");
+            PATH_DATA                  = new Mask("............1..........00............");
+            PATH_NOCHANGE              = new Mask("............1..........01............");
+
+            SET_OLC_FROM_OLC_MINUS_ONE = new Mask(".............1..1....................");
+            SET_OLC_FROM_DATA_LATCH    = new Mask("..............1.11...................");
+            SET_OLC_FROM_IMMEDIATE     = new Mask("..............1.10.............vvvvvv");
+
+            SET_ILC_FROM_DATA_LATCH    = new Mask("..............1.01...................");
+            SET_ILC_FROM_IMMEDIATE     = new Mask("..............1.00...........0.vvvvvv");
+            SET_ILC_FROM_INFINITY      = new Mask("..............1.0............1.......");
+
+            SET_FLAGS                  = new Mask("...............1.....................");
+            SET_FLAGS_A                = new Mask("...............1...............vvvvvv");
+            SET_FLAGS_B                = new Mask("...............1.........vvvvvv......");
+
+            SET_FLAGS_VALUE_A          = new Mask(".....1");
+            SET_FLAGS_VALUE_NOT_A      = new Mask("....1.");
+            SET_FLAGS_VALUE_B          = new Mask("...1..");
+            SET_FLAGS_VALUE_NOT_B      = new Mask("..1...");
+            SET_FLAGS_VALUE_C          = new Mask(".1....");
+            SET_FLAGS_VALUE_NOT_C      = new Mask("1.....");
+
+        } else {
+            DISPATCH_PATH              = new Mask("vvvvvvvvvvv..........................");
+            DISPATCH_INSTR             = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv");
+            NOT_INTERRUPTIBLE          = new Mask("...........1.........................");
+            IS_INTERRUPTIBLE           = new Mask("...........0.........................");
+            P                          = new Mask(".............vvv.....................");
+            P_NOT_A                    = new Mask(".............000.....................");
+            P_A                        = new Mask(".............001.....................");
+            P_NOT_B                    = new Mask(".............010.....................");
+            P_B                        = new Mask(".............011.....................");
+            P_UNUSED                   = new Mask(".............100.....................");
+            P_OLC_ZERO                 = new Mask(".............101.....................");
+            P_OLC_NONZERO              = new Mask(".............110.....................");
+            P_ALWAYS                   = new Mask(".............111.....................");
+
+            SHIFT                      = new Mask("................00vvvvvvvvvvvvvvvvvvv");
+
+            ABORT                      = new Mask("................1100.................");  // note: has a predicate!
+
+            HEAD                       = new Mask("................1110.................");
+            TAIL                       = new Mask("................1111.................");
+
+            MOVE                       = new Mask("................01...................");
+            TI                         = new Mask("................011..................");
+            DI                         = new Mask("................01.1.................");
+            FLUSH                      = new Mask("................01.01................");
+            DC                         = new Mask("................01.11................");
+            DO                         = new Mask("................01...1...............");
+            TO                         = new Mask("................01....1..............");
+            PATH_IMMEDIATE             = new Mask("................01.....1vvvvvvvvvvvvv");
+            PATH_DATA                  = new Mask("................01.....01............");
+            PATH_NOCHANGE              = new Mask("................01.....00............");
+
+            SET_OLC_FROM_IMMEDIATE     = new Mask("................101000100......vvvvvv");
+            SET_OLC_FROM_DATA_LATCH    = new Mask("................101000010............");
+            SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............");
+
+            SET_ILC_FROM_IMMEDIATE     = new Mask("................10010010......0vvvvvv");
+            SET_ILC_FROM_INFINITY      = new Mask("................10010010......1......");
+            SET_ILC_FROM_DATA_LATCH    = new Mask("................10010001.............");
+
+            SET_IMMEDIATE              = new Mask("................100010.vvvvvvvvvvvvvv");
+            SET_IMMEDIATE_EXTEND       = new Mask("................100010v..............");
+
+            SET_FLAGS                  = new Mask("................100001...............");
+            SET_FLAGS_A                = new Mask("................100001...vvvvvv......");
+            SET_FLAGS_B                = new Mask("................100001.........vvvvvv");
+
+            SET_FLAGS_VALUE_A          = new Mask("1.....");
+            SET_FLAGS_VALUE_NOT_A      = new Mask(".1....");
+            SET_FLAGS_VALUE_B          = new Mask("..1...");
+            SET_FLAGS_VALUE_NOT_B      = new Mask("...1..");
+            SET_FLAGS_VALUE_C          = new Mask("....1.");
+            SET_FLAGS_VALUE_NOT_C      = new Mask(".....1");
+        }
+
+        WIDTH_WORD                 = PACKET_DATA.valmaskwidth;
+        WIDTH_PACKET               = PACKET_TOKEN.width;
+        DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1;  // FIXME: this is an abstraction breakage
+        mask  = ~(-1L << DataLatch_WIDTH);
+    }
+
+    // Misc //////////////////////////////////////////////////////////////////////////////
+
+    public boolean isSmallEnoughToFit(long immediate) {
+        if ((immediate & ~mask) == 0)   return true;
+        if ((immediate |  mask) == -1L) return true;
+        return false;
+    }
+
+    public boolean isSmallEnoughToFit(BitVector immediate) {
+        boolean b = immediate.get((int)DataLatch_WIDTH);
+        for(int i=DataLatch_WIDTH+1; i<immediate.length(); i++)
+            if (immediate.get(i) != b) return false;
+        return true;
+    }
+
+    public int getWordWidth() { return 37; }
+
+    //////////////////////////////////////////////////////////////////////////////
+
+    /** get the bits describing this box's location on the DESTINATION HORN */
+    protected abstract BitVector getDestAddr(Path box);
+
+    private static final BitVector SIGNAL_ZERO = new BitVector(1);
+    private static final BitVector SIGNAL_ONE  = new BitVector(1).set(0,true);
+
+    /** decode a path, given the starting point and the bits that comprise it */
+    public Path getPathByAddr(Dock source, BitVector dest) {
+        for(Ship ship : this)
+            for(Dock bb : ship) {
+                for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) {
+                    for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) {
+                        Path p = (Path)source.getPath(d, signal);
+                        if (getDestAddr(p).equalsZeroExtended(dest)) return p;
+                    }
+                }
+            }
+        return null;
+    }
+
+    public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) {
+        return readInstruction(instruction.toLong(), dispatchFrom);
+    }
+
+    public BitVector   encodeInstruction(Instruction instr, Dock dispatchFrom) {
+        return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom));
+    }
+
+    public int getShiftWidth() { return SHIFT.valmaskwidth; }
+    public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; }
+
+    // FIXME: should use BitVector here
+    public Instruction readInstruction(long inst, Dock dispatchFrom) {
+        Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock();
+
+        if (TAIL.get(inst))   return new Tail(dock);
+        if (HEAD.get(inst))   return new Head(dock);
+
+        Predicate predicate = Default;
+        if (P_ALWAYS.get(inst)) predicate = IgnoreFlagD;
+        if (P_OLC_NONZERO.get(inst))    predicate = Default;
+        if (P_OLC_ZERO.get(inst))    predicate = FlagD;
+        if (P_A.get(inst))      predicate = FlagA;
+        if (P_B.get(inst))      predicate = FlagB;
+        if (P_NOT_A.get(inst))  predicate = NotFlagA;
+        if (P_NOT_B.get(inst))  predicate = NotFlagB;
+
+        if (FLUSH.get(inst))
+            return new Flush(dock, predicate);
+        if (ABORT.get(inst))
+            return new Abort(dock, predicate);
+        if (SHIFT.get(inst))                return new Shift(dock, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst)));
+        if (SET_IMMEDIATE.get(inst)) {
+            boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0;
+            long immediate = SET_IMMEDIATE.getval(inst);
+            if (extend) immediate |= (-1L << DataLatch_WIDTH);
+            return new Set(dock, predicate, SetDest.DataLatch, (immediate));
+        }
+
+        if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst))
+            return new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.Decrement);
+        if (SET_OLC_FROM_IMMEDIATE.get(inst))
+            return new Set(dock, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst)));
+        if (SET_ILC_FROM_IMMEDIATE.get(inst))
+            return new Set(dock, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst)));
+        if (SET_OLC_FROM_DATA_LATCH.get(inst))
+            return new Set(dock, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch);
+        if (SET_ILC_FROM_DATA_LATCH.get(inst))
+            return new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch);
+        if (SET_ILC_FROM_INFINITY.get(inst))
+            return new Set(dock, predicate, SetDest.InnerLoopCounter, SetSource.Infinity);
+        if (SET_FLAGS.get(inst)) {
+            long flag_a = SET_FLAGS_A.getval(inst);
+            long flag_b = SET_FLAGS_B.getval(inst);
+            FlagFunction ap = FlagFunction.ZERO;
+            FlagFunction bp = FlagFunction.ZERO;
+            if (SET_FLAGS_VALUE_A    .get(flag_a)) ap = ap.add(FlagA    );
+            if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA );
+            if (SET_FLAGS_VALUE_B    .get(flag_a)) ap = ap.add(FlagB    );
+            if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB );
+            if (SET_FLAGS_VALUE_C    .get(flag_a)) ap = ap.add(FlagC    );
+            if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC );
+            if (SET_FLAGS_VALUE_A    .get(flag_b)) bp = bp.add(FlagA    );
+            if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA );
+            if (SET_FLAGS_VALUE_B    .get(flag_b)) bp = bp.add(FlagB    );
+            if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB );
+            if (SET_FLAGS_VALUE_C    .get(flag_b)) bp = bp.add(FlagC    );
+            if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC );
+            return new Set(dock,  predicate, ap, bp);
+        }
+        if (MOVE.get(inst))
+            return new Move(dock,
+                            predicate,
+                            !NOT_INTERRUPTIBLE.get(inst),
+                            PATH_DATA.get(inst)?null:getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)),
+                            TI.get(inst),
+                            DI.get(inst),
+                            hack?(!DC.get(inst)):DC.get(inst),
+                            PATH_DATA.get(inst),
+                            DO.get(inst),
+                            TO.get(inst)
+                            );
+        throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16));
+    }
+
+    // FIXME: should use BitVector here
+    public long writeInstruction(Instruction d, Dock dispatchFrom) {
+        long instr = 0;
+
+        if (d.dock != null) {
+            BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null));
+            BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth);
+            for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
+                bv2.set(i, bv.get(i));
+            instr = DISPATCH_PATH.setval(instr, bv2);
+        }
+
+        boolean dl = false;
+        Instruction pi = d;
+        switch(pi.predicate) {
+            case IgnoreFlagD:         instr = P_ALWAYS.set(instr); break;
+            case FlagD:         instr = P_OLC_ZERO.set(instr); break;
+            case Default: instr = P_OLC_NONZERO.set(instr); break;
+            case FlagA:      instr = P_A.set(instr);      break;
+            case FlagB:      instr = P_B.set(instr);      break;
+            case NotFlagA:  instr = P_NOT_A.set(instr);      break;
+            case NotFlagB:  instr = P_NOT_B.set(instr);      break;
+            default: throw new RuntimeException("error!");
+        }
+
+        if (d instanceof Tail) {
+            instr = TAIL.set(instr);
+
+        } else if (d instanceof Head) {
+            instr = HEAD.set(instr);
+
+        } else if (d instanceof Shift) {
+            Shift shift = (Shift)d;
+            instr = SHIFT.set(instr);
+            instr = SHIFT.setval(instr, shift.immediate.getBitVector());
+
+        } else if (d instanceof Flush) {
+            instr = FLUSH.set(instr);
+
+        } else if (d instanceof Abort) {
+            instr = ABORT.set(instr);
+
+        } else if (d instanceof Set) {
+            Set s = (Set)d;
+            switch(s.dest) {
+                case InnerLoopCounter:
+                    switch(s.source) {
+                        case DataLatch:
+                            instr = SET_ILC_FROM_DATA_LATCH.set(instr);
+                            break;
+                        case Immediate:
+                            instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
+                            break;
+                        case Infinity:
+                            instr = SET_ILC_FROM_INFINITY.set(instr);
+                            break;
+                    }
+                    break;
+                case OuterLoopCounter:
+                    switch(s.source) {
+                        case Decrement:
+                            instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
+                            break;
+                        case DataLatch:
+                            instr = SET_OLC_FROM_DATA_LATCH.set(instr);
+                            break;
+                        case Immediate:
+                            instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
+                            break;
+                    }
+                    break;
+                case Flags: {
+                    instr = SET_FLAGS.set(instr);
+                    instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
+                    instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
+                    break;
+                }
+                case DataLatch: {
+                    instr = SET_IMMEDIATE.set(instr);
+                    instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
+                    instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
+                    break;
+                }
+            }
+
+        } else if (d instanceof Move) {
+            Move inst = (Move)d;
+            instr  = MOVE.set(instr);
+            if (inst.tokenIn)                    instr = TI.set(instr);
+            if (inst.dataIn)                     instr = DI.set(instr);
+            if (hack) {
+                if (!inst.latchData)                 instr = DC.set(instr);
+                System.err.println("WARNING: employing inverted-Dc-bit hack -- DO NOT FORGET TO DISABLE THIS WHEN THE NETLIST GETS UPDATED!");
+            } else {
+                if (inst.latchData)                  instr = DC.set(instr);
+            }
+            if (inst.dataOut)                    instr = DO.set(instr);
+            if (inst.tokenOut)                   instr = TO.set(instr);
+            if (!inst.interruptible)             instr = NOT_INTERRUPTIBLE.set(instr);
+            else                                 instr = IS_INTERRUPTIBLE.set(instr);
+
+            if (inst.latchPath)                  instr = PATH_DATA.set(instr);
+            else if (inst.path!=null) {
+                instr  = PATH_IMMEDIATE.set(instr);
+                BitVector bv  = getDestAddr(inst.path);
+                BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
+                for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
+                    bv2.set(i, bv.get(i));
+                instr  = PATH_IMMEDIATE.setval(instr, bv2);
+            } else {
+                instr  = PATH_NOCHANGE.set(instr);
+            }
+
+        } else {
+            throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
+
+        }
+        return instr;
+    }
+
+    private long flagFunctionToLong(FlagFunction ff) {
+        long ret = 0;
+        for(Predicate p : ff)
+            switch(p) {
+                case FlagA    : ret = SET_FLAGS_VALUE_A    .set(ret); break;
+                case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break;
+                case FlagB    : ret = SET_FLAGS_VALUE_B    .set(ret); break;
+                case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break;
+                case FlagC    : ret = SET_FLAGS_VALUE_C    .set(ret); break;
+                case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break;
+                default: throw new RuntimeException();
+            }
+        return ret;
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/two/FleetTwoPath.java b/src/edu/berkeley/fleet/two/FleetTwoPath.java
new file mode 100644 (file)
index 0000000..67065d9
--- /dev/null
@@ -0,0 +1,11 @@
+package edu.berkeley.fleet.two;
+import java.util.*;
+import edu.berkeley.fleet.api.Path;
+
+/**
+ *  Represents a path through the switch fabric, from a Dock (source)
+ *  to a Destination, plus an optional "signal" value.
+ */
+public abstract class FleetTwoPath extends Path {
+
+}            
diff --git a/src/edu/berkeley/fleet/two/FleetTwoShip.java b/src/edu/berkeley/fleet/two/FleetTwoShip.java
new file mode 100644 (file)
index 0000000..d8d008e
--- /dev/null
@@ -0,0 +1,40 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+
+/** A ship in a Fleet; each ship consists of a collection of <tt>Dock</tt>s */
+public abstract class FleetTwoShip extends Ship {
+
+    protected final ShipDescription shipDescription;
+
+    public FleetTwoShip(Fleet fleet, ShipDescription shipDescription) {
+        super(fleet);
+        this.shipDescription = shipDescription;
+    }
+
+    /** returns the type of the ship ("Fetch", "ALU", etc) */
+    public String getType() { return shipDescription.getName(); }
+
+    public Dock getDock(String s) {
+        for(Dock b : this)
+            if (b.getName().equals(s))
+                return b;
+        throw new RuntimeException("unknown port \""+getType()+"."+s+"\"");
+    }
+
+    public int getOrdinal() {
+        int ord = 0;
+        for(Ship s : getFleet()) {
+            if (s==this) return ord;
+            if (s.getType() != null && s.getType().equals(getType())) ord++;
+        }
+        throw new RuntimeException("inconsistency: Ship does not belong to its own Fleet!");
+    }
+
+    public BitVector getConstant(String constantName) {
+        BitVector bv = shipDescription.getConstant(constantName);
+        if (bv==null)
+            throw new RuntimeException("unknown constant \""+constantName+"\" on ship " + this);
+        return bv;
+    }
+}
diff --git a/src/edu/berkeley/fleet/two/PercolatedPort.java b/src/edu/berkeley/fleet/two/PercolatedPort.java
new file mode 100644 (file)
index 0000000..d2fd257
--- /dev/null
@@ -0,0 +1,17 @@
+package edu.berkeley.fleet.two;
+
+/**
+ *  A PercolatedPort is a connection to a top-level pin; it is
+ *  propagated up or down the hierarchy
+ */
+public class PercolatedPort {
+    public static enum PortType { UP, DOWN, INOUT };
+    public final String name;
+    public final int width;
+    public final PortType type;
+    public PercolatedPort(String name, int width, PortType type) {
+        this.name = name;
+        this.width = width;
+        this.type = type;
+    }
+}
diff --git a/src/edu/berkeley/fleet/two/ShipDescription.java b/src/edu/berkeley/fleet/two/ShipDescription.java
new file mode 100644 (file)
index 0000000..6752e70
--- /dev/null
@@ -0,0 +1,210 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** NOT YET FINALIZED: A description (specification) of a ship */
+public class ShipDescription implements Iterable<DockDescription> {
+
+    private Fleet fleet;
+    private String name;
+    private LinkedHashMap<String,DockDescription> docks         = new LinkedHashMap<String,DockDescription>();
+    private LinkedHashMap<String,DockDescription> ports = new LinkedHashMap<String,DockDescription>();
+    private HashMap<String,String>                sections      = new HashMap<String,String>();
+    private HashMap<String,BitVector>              constants     = new HashMap<String,BitVector>();
+
+    public String getName() { return name; }
+    public String getSection(String sectionName) { return sections.get(sectionName); }
+    public DockDescription getDockDescription(String name) { return docks.get(name); }
+    public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+    public Iterable<DockDescription> ports() {
+        return ports.values();
+    }
+
+    public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
+
+    public ShipDescription(Fleet fleet, String name, BufferedReader r) throws IOException {
+        if (name.endsWith(".ship")) name = name.substring(0, name.length()-".ship".length());
+        this.name = name;
+        this.fleet = fleet;
+        String sectionName = null;
+        StringBuffer sb = new StringBuffer();
+        while(true) {
+            String s = r.readLine();
+            if (s==null || s.startsWith("==")) {
+                if (sectionName != null) sections.put(sectionName, sb.toString());
+                if (s==null) break;
+                sb = new StringBuffer();
+                sectionName = s.trim();
+                while(sectionName.startsWith("="))
+                    sectionName = sectionName.substring(1);
+                while(sectionName.endsWith("="))
+                    sectionName = sectionName.substring(0, sectionName.length()-1);
+                sectionName = sectionName.trim().toLowerCase();
+                continue;
+            }
+            sb.append(s+"\n");
+        }
+        for(String s : sections.keySet())
+            processSection(s);
+    }
+
+    public BitVector getConstant(String name) {
+        BitVector c = constants.get(name);
+        if (c==null) throw new RuntimeException("unknown constant " + name);
+        return c;
+    }
+
+    private void processSection(String section) throws IOException {
+        if (section.equals("")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.trim().length()==0) continue;
+                String key = s.substring(0, s.indexOf(':')).trim();
+                String val = s.substring(s.indexOf(':')+1).trim();
+                if (key.toLowerCase().equals("ship"))
+                    name = val.trim();
+            }
+        } else if (section.equals("constants")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.indexOf(':')==-1) continue;
+                String key = s.substring(0, s.indexOf(':')).trim();
+                if (key.startsWith("constant")) {
+                    String constname = key.substring("constant".length()+1).trim();
+                    String val       = s.substring(s.indexOf(':')+1).trim();
+                    constants.put(constname, new BitVector(fleet.getWordWidth()).set(Integer.parseInt(val)));
+                }
+            }
+        } else if (section.equals("ports")) {
+            BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+            boolean rightSide = false;
+            DockDescription p = null;
+            for(String s = br.readLine(); s != null; s = br.readLine()) {
+                if (s.trim().length()==0) { rightSide = true; continue; }
+
+                String key = s.substring(0, s.indexOf(':')).trim();
+                boolean inbox = false;
+                boolean dockless = false;
+                key = key.replaceAll("  +", " ");
+                if      (key.equals("data in"))   { inbox = true;  }
+                else if (key.equals("data out"))  { inbox = false; }
+                else if (key.equals("in"))        { inbox = true;  }
+                else if (key.equals("dockless out")) { inbox = false; dockless = true; }
+                else if (key.equals("out"))       { inbox = false; }
+                else if (key.startsWith("percolate")) { 
+                    key = s;
+                    key = key.substring("percolate".length()+1).trim();
+                    PercolatedPort.PortType type = null;
+                    if (key.startsWith("up")) type = PercolatedPort.PortType.UP;
+                    if (key.startsWith("down")) type = PercolatedPort.PortType.DOWN;
+                    if (key.startsWith("inout")) type = PercolatedPort.PortType.INOUT;
+                    key = key.substring(key.indexOf(':')+1).trim();
+                    String name = key.substring(0, key.indexOf(' '));
+                    int width = Integer.parseInt(key.substring(key.indexOf(' ')).trim());
+                    percolatedPorts.add(new PercolatedPort(name, width, type));
+                    continue;
+                }
+                else if (key.startsWith("constant")) {
+                    String constname = key.substring("constant".length()+1).trim();
+                    String val       = s.substring(s.indexOf(':')+1).trim();
+                    p.addConstant(constname, new BitVector(fleet.getWordWidth()).set(Integer.parseInt(val)));
+                    continue;
+                } else if (key.startsWith("shortcut to")) {
+                    continue;
+                }
+                else throw new RuntimeException("unknown port type: \""+key+"\"");
+
+                p = null;
+                String val = s.substring(s.indexOf(':')+1).trim();
+                String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val;
+                String dest    = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1)  : "";
+                p = docks.get(boxname);
+                if (p==null) {
+                    p = new DockDescription(this, boxname, !rightSide, inbox, dockless);
+                    ports.put(boxname, p);
+                    if (!dockless) docks.put(boxname, p);
+                }
+            }
+        }
+    }
+
+    public void printTeX(PrintWriter pw) throws Exception {
+        ShipDescription sd = this;
+        pw.println("\\pagebreak");
+        pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}");
+        pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}");
+        String tex = sd.getSection("tex");
+        /*
+        for(DockDescription bbd : sd) {
+            pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n");
+        }
+        */
+        int boxGap = 5;
+        int boxHeight = 25;
+        int boxWidth = 75;
+
+        int leftSize = 0;
+        int rightSize = 0;
+        for(DockDescription bbd : sd)
+            if (bbd.isLeft()) leftSize += (boxHeight+boxGap);
+            else              rightSize += (boxHeight+boxGap);
+
+        int totalHeight = Math.max(leftSize, rightSize);
+        int shipWidth = (int)(boxWidth * 1.5);
+        int totalWidth = boxGap*2 + boxWidth*2 + shipWidth;
+
+        pw.println("");
+        pw.println("\\begin{center}");
+        pw.println("\\begin{empfile}["+sd.getName()+"]");
+        pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")");
+        pw.println("  beginfig(1)");
+        pw.println("      pickup pencircle scaled 1pt;");
+        pw.println("      draw "+
+                   "("+((totalWidth-shipWidth)/2)+","+0+")--"+
+                   "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+
+                   "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+
+                   "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+
+                   "("+((totalWidth-shipWidth)/2)+","+0+");");
+        int left = 0;
+        int right = 0;
+        for(DockDescription bbd : sd) {
+            int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right));
+            int half = (totalWidth-shipWidth)/2;
+            int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5);
+            int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth);
+            if (bbd.isInputDock()) {
+                int p1x = p1;
+                p1 = p3;
+                p3 = p1x;
+            }
+            boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock()));
+            int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2));
+            if (bbd.isLeft()) left += (boxHeight+boxGap);
+            else              right += (boxHeight+boxGap);
+            if (goo) {
+                pw.println("      label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));");
+            } else {
+                pw.println("      label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));");
+            }
+            pw.println("      draw "+
+                       "  ("+p1+","+ypos+")--"+
+                       "  ("+p2+","+ypos+")--"+
+                       "  ("+p3+","+(ypos-(boxHeight/2))+")--"+
+                       "  ("+p2+","+(ypos-boxHeight)+")--"+
+                       "  ("+p1+","+(ypos-boxHeight)+")--"+
+                       "  ("+p1+","+ypos+");");
+            if (bbd.isLeft()) leftSize += boxHeight;
+            else              rightSize += boxHeight;
+        }
+        pw.println("  endfig;");
+        pw.println("\\end{emp}");
+        pw.println("\\end{empfile}");
+        pw.println("\\end{center}");
+        pw.println("");
+
+        if (tex!=null)
+            pw.println(tex);
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/util/BitManipulations.java b/src/edu/berkeley/fleet/util/BitManipulations.java
new file mode 100644 (file)
index 0000000..3ce48c3
--- /dev/null
@@ -0,0 +1,51 @@
+package edu.berkeley.fleet.util;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.*;
+import java.io.*;
+
+/** useful functions for manipulating bit fields within longs */
+public class BitManipulations {
+    public static boolean getBit(int bit, long val) { return ((val & (1L << bit)) != 0); }
+    public static long getSignedField(int highBit, int lowBit, long val) {
+        long ret = getField(highBit, lowBit, val);
+        if ((ret & (1L << ((highBit-lowBit)+1-1))) != 0)
+            ret |= 0xffffffffffffffffL << ((highBit-lowBit)+1);
+        return ret;
+    }
+    public static int getIntField(int highBit, int lowBit, long val) {
+        if (highBit-lowBit+1 > 32) throw new RuntimeException("too big!");
+        return (int)getField(highBit, lowBit, val);
+    }
+    public static long getField(int highBit, int lowBit, long val) {
+        long mask = 0xffffffffffffffffL;
+        mask = mask << ((highBit-lowBit)+1);
+        mask = ~mask;
+        mask = mask << lowBit;
+        long ret = val & mask;
+        ret = ret >> lowBit;
+        return ret;
+    }
+    public static long setField(int highBit, int lowBit, long val, long target) {
+        return (target & ~putField(highBit, lowBit, ~(-1L<<(1+highBit-lowBit)))) | putField(highBit, lowBit, val);
+    }
+    public static long doPutField(int highBit, int lowBit, long val) {
+        long mask = 0xffffffffffffffffL;
+        mask = mask << (highBit-lowBit+1);
+        mask = ~mask;
+        val = val & mask;
+        val = val << lowBit;
+        return val;
+    }
+    public static long putField(int highBit, int lowBit, long val) {
+        if (val < 0 || val >= (1L << (highBit-lowBit+1)))
+            throw new RuntimeException("bitfield width exceeded");
+        return doPutField(highBit, lowBit, val);
+    }
+    public static long putSignedField(int highBit, int lowBit, long val) {
+        if (val <= (-1L * (1L << (highBit-lowBit+1-1))))
+            throw new RuntimeException("bitfield width exceeded");
+        if (val >= (      (1L << (highBit-lowBit+1-1))))
+            throw new RuntimeException("bitfield width exceeded");
+        return doPutField(highBit, lowBit, val);
+    }
+}
diff --git a/src/edu/berkeley/fleet/util/BitMask.java b/src/edu/berkeley/fleet/util/BitMask.java
new file mode 100644 (file)
index 0000000..b07cc7a
--- /dev/null
@@ -0,0 +1,34 @@
+package edu.berkeley.fleet.util;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.*;
+import java.io.*;
+
+/** A bit mask assigns 1, 0, or dont-care to each bit position */
+public class BitMask {
+
+    public final BitVector zeroes;
+    public final BitVector ones;
+
+    public BitMask(BitVector zeroes, BitVector ones) {
+        if (ones.length() != zeroes.length())
+            throw new RuntimeException("attempt to invoke BitMask with different-size "+
+                                       "BitVectors: ones="+ones+", zeroes="+zeroes);
+        ones.setImmutable();
+        zeroes.setImmutable();
+        this.ones = ones;
+        this.zeroes = zeroes;
+    }
+
+    public BitVector apply(BitVector bv) {
+        return ones.or(bv).and(zeroes.not());
+    }
+
+    public boolean test(BitVector bv) {
+        throw new RuntimeException("not implemented");
+    }
+
+    public BitMask invert() {
+        return new BitMask(ones, zeroes);
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/util/Mask.java b/src/edu/berkeley/fleet/util/Mask.java
new file mode 100644 (file)
index 0000000..f252430
--- /dev/null
@@ -0,0 +1,131 @@
+package edu.berkeley.fleet.util;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.*;
+import java.io.*;
+
+public class Mask {
+
+    private final String str;
+
+    public final long mask;
+    public final long val;
+    public final long valmask;
+    public final int valmaskmin;
+    public final int valmaskmax;
+    public final int valmaskwidth;
+    public final int allmax;
+    public final int width;
+
+    public String verilog(String var) {
+        // FIXME: throw an exception if this is called when no 1-bits or 0-bits were specified (ie only v-bits)
+
+        StringBuffer sb = new StringBuffer();
+        sb.append("{");
+        boolean first = true;
+        int count = 0;
+        for(int i=63; i>=0; i--) {
+            if ((mask & (1L << i)) == 0) continue;
+            if (!first) sb.append(",");
+            first = false;
+            sb.append(var+"["+i+"]");
+            count++;
+        }
+        sb.append("}=="+count+"'b");
+        for(int i=63; i>=0; i--) {
+            if ((mask & (1L << i)) == 0) continue;
+            sb.append( (val & (1L << i))==0 ? "0" : "1" );
+        }
+        return "("+sb.toString()+")";
+        //return "(("+var+" & "+allmax+"'b"+Long.toString(mask,2)+")=="+allmax+"'b"+Long.toString(val,2)+")";
+    }
+
+    public long getval(long in) {
+        return (in & valmask) >>> valmaskmin;
+    }
+    public BitVector getvalAsBitVector(long in) {
+        // FIXME
+        return new BitVector(getWidth()).set(getval(in));
+    }
+    public BitVector getvalAsBitVector(BitVector in) {
+        // FIXME
+        return new BitVector(getWidth()).set(getval(in.toLong()));
+    }
+    public long getval(BitVector targ) {
+        long in = 0;
+        for(int i=0; i<targ.length(); i++)
+            if (targ.get(i))
+                in |= (1L << i);
+        return (in & valmask) >>> valmaskmin;
+    }
+    public long setval(long in, BitVector targ) {
+        long ret = in;
+        if (targ.length() != (1+valmaskmax-valmaskmin))
+            throw new RuntimeException("size mismatch trying to do "+this+".setval("+targ+")");
+        for(int i=valmaskmin; i<=valmaskmax; i++)
+            if (targ.get(i-valmaskmin))
+                ret |= (1L << i);
+            else
+                ret &= ~(1L << i);
+        return ret;
+    }
+    public long setval(long in, long targ) {
+        if (((targ << valmaskmin) & ~valmask) != 0) throw new RuntimeException("setval() with argument bigger than mask field");
+        return (in & ~valmask) | ((targ << valmaskmin) & valmask);
+    }
+    public long set(long in) {
+        return (in & ~mask) | val;
+    }
+    public boolean get(long in) {
+        return (in & mask) == val;
+    }
+
+    public String toString() {
+        return str;
+    }
+
+    public int getWidth() {
+        int ret = 0;
+        long m = 1;
+        for(int i=0; i<64; i++) {
+            if ((valmask & m)!=0) ret++;
+            m = m << 1;
+        }
+        return ret;
+    }
+
+    public Mask(String s) {
+        this.str = s;
+        long mask = 0;
+        long valmask = 0;
+        long val = 0;
+        int valmaskmin = Integer.MAX_VALUE;
+        int valmaskmax = 0;
+        int allmax = 0;
+        this.width = s.length();
+        for(int i=0; i<s.length(); i++) {
+            char c = s.charAt(s.length()-1-i);
+            switch(c) {
+                case '.': break;
+                case '0': mask |= (1L<<i); val |= (0L<<i); break;
+                case '1': mask |= (1L<<i); val |= (1L<<i); break;
+                case 'v': valmask |= (1L<<i); valmaskmin = Math.min(valmaskmin,i); valmaskmax = Math.max(valmaskmax,i); break;
+                default: throw new Error(""+c);
+            }
+            if (c!='.') allmax = Math.max(allmax,i);
+        }
+        this.mask = mask;
+        this.val = val;
+        this.valmask = valmask;
+        this.valmaskmin = valmaskmin;
+        this.valmaskmax = valmaskmax;
+        this.allmax = allmax+1;
+        this.valmaskwidth = 1 + valmaskmax - valmaskmin;
+    }
+
+    public static long signExtend(long input, int wordWidth) {
+        if ((input & (1L << (wordWidth-1)))!=0)
+            input |= (-1L) << wordWidth;
+        return input;
+    }
+
+}
diff --git a/tests/codebags/fun-with-codebags.fleet b/tests/codebags/fun-with-codebags.fleet
new file mode 100644 (file)
index 0000000..50d7b3d
--- /dev/null
@@ -0,0 +1,17 @@
+#expect 3
+
+#ship debug  : Debug
+#ship memory : Memory
+
+memory.out:
+ set ilc=*;  collect packet, send;
+
+memory.inCBD: set word= {
+    memory.inCBD: set word= {
+        memory.inCBD: set word= {
+            debug.in:
+              set word= 3;
+              deliver;
+          }; deliver;
+      }; deliver;
+  }; deliver;
diff --git a/tests/codebags/fun-with-codebags2.fleet b/tests/codebags/fun-with-codebags2.fleet
new file mode 100644 (file)
index 0000000..60dda0c
--- /dev/null
@@ -0,0 +1,26 @@
+// expected output
+#expect 12
+#expect 13
+#expect 14
+
+// ships required in order to run this code
+#ship debug          : Debug
+#ship memory         : Memory
+
+// instructions not in any codebag are part of the "root codebag"
+// which is dispatched when the code is loaded
+
+memory.out:
+  set ilc=*;
+  collect packet, send;
+
+memory.inCBD:
+  set word=BOB;
+  deliver;
+
+BOB: {
+  debug.in:
+    set word=12; deliver;
+    set word=13; deliver;
+    set word=14; deliver;
+}
diff --git a/tests/codebags/torpedoing-loops.fleet b/tests/codebags/torpedoing-loops.fleet
new file mode 100644 (file)
index 0000000..e4f0542
--- /dev/null
@@ -0,0 +1,42 @@
+#expect 5
+#expect 5
+#expect 3
+
+#ship debug  : Debug
+#ship memory : Memory
+#ship fifo   : Fifo
+
+debug.in:
+  [*] set olc=1;
+  set word=5;
+  head;
+    send token to fifo.out;
+    [T] recv token;
+    deliver;
+    [d] abort;
+    [d] send token to memory.inCBD;
+  tail;
+
+fifo.out:
+  [*] set olc=3;
+  head;
+    recv token;
+    set olc--;
+    send token to debug.in;
+    [d] abort;
+    [d] send token to debug.in:i;
+  tail;
+
+memory.out:
+ set ilc=*;
+ collect packet, send;
+
+memory.inCBD:
+  set word={
+    debug.in:
+      [*] set olc=1;
+      set word=3;
+      deliver;
+  };
+  recv token;
+  deliver;
diff --git a/tests/colliding-tokens.test b/tests/colliding-tokens.test
new file mode 100644 (file)
index 0000000..682d781
--- /dev/null
@@ -0,0 +1,19 @@
+#expect 2
+#expect 2
+#expect 2
+#expect 2
+
+#ship debug        : Debug
+#ship alu          : Alu
+
+// attempts to get tokens to "collide" in the switch fabric
+
+debug.in:
+  set word= 2;
+  set ilc=*;  recv token, deliver;
+
+alu.inOp: set word=Alu.inOp[ADD]; deliver; send token to debug.in;
+alu.in1:  deliver; send token to debug.in;
+alu.in2:  deliver; send token to debug.in;
+alu.out:  collect; send token to debug.in;
+
diff --git a/tests/dock/literal-at-pump.fleet b/tests/dock/literal-at-pump.fleet
new file mode 100644 (file)
index 0000000..b6cc4de
--- /dev/null
@@ -0,0 +1,3 @@
+#expect 21
+#ship debug : Debug
+debug.in: set word= 21; deliver;
diff --git a/tests/dock/one-instruction-loop.fleet b/tests/dock/one-instruction-loop.fleet
new file mode 100644 (file)
index 0000000..434fdfc
--- /dev/null
@@ -0,0 +1,22 @@
+
+// This test case ensures that a single-instruction loop works
+// properly.  The two instructions after the tail will get "clogged"
+// in the switch fabric until the hatch opens, but that's okay.
+
+#ship debug : Debug
+#ship fifo : Fifo
+
+#expect 5
+#expect 4
+
+debug.in:
+  set word=5;
+  deliver;
+  set olc=4;
+  head;
+  set olc--;
+  [d] abort;
+  [d] set word=4;
+  [d] deliver;
+  tail;
+
diff --git a/tests/dock/predicate-olc-equals-zero.fleet b/tests/dock/predicate-olc-equals-zero.fleet
new file mode 100644 (file)
index 0000000..2d91740
--- /dev/null
@@ -0,0 +1,19 @@
+#expect 5
+#expect 5
+#expect 5
+#expect 4
+
+#ship debug : Debug
+
+debug.in:
+  set word=5;
+  set flags a=0, b=0;
+  set olc=3;
+  head;
+  [d] set word=4;
+  [d] deliver;
+  deliver;
+  set olc--;
+  [d] abort;
+  tail;
+
diff --git a/tests/dock/pump+ b/tests/dock/pump+
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/dock/send-without-destination.fleet- b/tests/dock/send-without-destination.fleet-
new file mode 100644 (file)
index 0000000..d6478d8
--- /dev/null
@@ -0,0 +1,40 @@
+#skip
+// output ///////////////////////////////////////////////////////////////////
+#expect 5263
+
+// program //////////////////////////////////////////////////////////////////
+#ship debug        : Debug
+#ship memory       : Memory
+#ship bitfifo      : BitFifo
+#ship fifo         : Fifo
+
+// dumb configurations
+debug.in:           set ilc=*;  take, deliver;
+memory.inAddrRead:  set ilc=*;  take, deliver;
+memory.inAddrWrite: set ilc=*;  take, deliver;
+memory.inDataWrite: set ilc=*;  take, deliver;
+
+FRED: {
+  fifo.in: deliver, send token to fifo.out;
+}
+
+fifo.in: set word= 5263;
+fifo.out: recv token, take, send to debug.in;
+
+bitfifo.in:
+  set word= 0; deliver;     // six bits of leading zero (to wash out the codebag size)
+  set word= FRED; deliver;  // FRED = { address_of_fred[31], size_of_fred[6] }
+
+// strip off bottom 6 bits
+bitfifo.inOp:
+   set word= BitFifo.inOp[take=6]; deliver;
+   set word= BitFifo.inOp[take=37]; deliver;
+bitfifo.outOp:
+   set word= BitFifo.outOp[take=37]; deliver;
+
+bitfifo.out:            take, send to memory.inAddrRead;
+
+// value read out will be the instruction at FRED
+memory.out:             take, send;
+
+
diff --git a/tests/dock/shift-outbox.test b/tests/dock/shift-outbox.test
new file mode 100644 (file)
index 0000000..b2ed461
--- /dev/null
@@ -0,0 +1,14 @@
+#expect 81231
+#ship debug : Debug
+#ship fifo  : Fifo
+
+fifo.out:
+   shift 0;
+   shift 81231;
+   send to debug.in;
+
+debug.in:
+   recv word, deliver;
+
+
+
diff --git a/tests/dock/shift.test b/tests/dock/shift.test
new file mode 100644 (file)
index 0000000..180de2c
--- /dev/null
@@ -0,0 +1,7 @@
+#expect 524290
+#ship debug : Debug
+
+debug.in:
+   set word=1;
+   shift 2;
+   deliver;
diff --git a/tests/dock/test-count.fleet b/tests/dock/test-count.fleet
new file mode 100644 (file)
index 0000000..c6facee
--- /dev/null
@@ -0,0 +1,112 @@
+// expected output
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+#expect 9
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+ set word= 9;
+ set ilc=63;
+ deliver;
+ set ilc=37;
+ deliver;
+
diff --git a/tests/dock/test-repeat-counter-from-data-latch.fleet b/tests/dock/test-repeat-counter-from-data-latch.fleet
new file mode 100644 (file)
index 0000000..4c4a3e0
--- /dev/null
@@ -0,0 +1,24 @@
+#expect 0
+#expect 0
+#expect 0
+#expect 0
+#expect 0
+#expect 1
+
+#ship debug        : Debug
+#ship memory       : Memory
+#ship fifo         : Fifo
+
+debug.in: set ilc=*;  recv, deliver;
+
+fifo.in:
+  set word= 5;
+  deliver;
+
+fifo.out:
+  collect;
+  set ilc=word;
+  set word=0;
+  send to debug.in;
+  set word=1;
+  send to debug.in;
diff --git a/tests/dock/test-repeat-counter.fleet b/tests/dock/test-repeat-counter.fleet
new file mode 100644 (file)
index 0000000..3587a34
--- /dev/null
@@ -0,0 +1,22 @@
+#expect 5
+#expect 5
+#expect 5
+#expect 1
+#expect 2
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in: set ilc=*;  recv, deliver;
+
+fifo.out: set ilc=*;  collect, send to debug.in;
+
+fifo.in:
+  set word= 5;
+  set ilc=3;
+  deliver;
+  set word= 1;
+  deliver;
+  set word= 2;
+  deliver;
+
diff --git a/tests/dock/test-repeat-zero.fleet b/tests/dock/test-repeat-zero.fleet
new file mode 100644 (file)
index 0000000..6aea5b5
--- /dev/null
@@ -0,0 +1,19 @@
+#expect 1
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+fifo.out:
+  set ilc=*;
+  collect, send to debug.in;
+
+fifo.in:
+  set word=0;
+  set ilc=0;
+  deliver;
+  set word=1;
+  deliver;
diff --git a/tests/dock/test-use-loop-counter.fleet b/tests/dock/test-use-loop-counter.fleet
new file mode 100644 (file)
index 0000000..7a07847
--- /dev/null
@@ -0,0 +1,53 @@
+#expect 5
+#expect 7
+#expect 5
+#expect 7
+#expect 5
+#expect 7
+#expect 9
+
+#ship memory       : Memory
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+   set ilc=*;
+   recv, deliver;
+
+fifo.out:
+   set ilc=*;
+   collect, send to debug.in;
+
+fifo.in:
+  set olc=3;
+  head;
+  set word=5;
+  deliver;
+  send token to memory.inCBD;
+  recv, deliver;
+  set olc--;
+  [d] abort;
+  [d] send token to memory.out;
+  tail;
+
+memory.out:
+  set word=7;
+  set ilc=3;
+  send to fifo.in;
+
+  recv token;
+  set ilc=*;
+  collect packet, send;
+
+memory.inCBD:
+  recv nothing;
+  recv nothing;
+  recv nothing;
+  set word={
+    fifo.in:
+       [*] set olc=1;
+       set word=9;
+       deliver;
+  };
+  deliver;
+
diff --git a/tests/flags/basic.test b/tests/flags/basic.test
new file mode 100644 (file)
index 0000000..56649cc
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 0
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set word= 0;
+  set flags a=0, b=0;
+  deliver;
+
diff --git a/tests/flags/c-flag-determined-by-dc.test b/tests/flags/c-flag-determined-by-dc.test
new file mode 100644 (file)
index 0000000..2dd6621
--- /dev/null
@@ -0,0 +1,63 @@
+// expected output
+#expect 1
+#expect 0
+#expect 0
+#expect 0
+#expect 1
+#expect 1
+#expect 0
+#expect 1
+
+#ship debug        : Debug
+#ship alu          : Alu
+#ship fifo         : Fifo
+
+alu.in1:
+  set word=1;
+  set ilc=*;
+  deliver;
+
+alu.inOp:
+  set word=Alu.inOp[CMP];
+  set ilc=*;
+  deliver;
+
+alu.out:
+  set flags a=0, b=0;
+  set olc=8;
+
+  head;
+  [!b] recv token, collect nothing;
+  [b]  recv token, collect word;
+  set flags a=c, b=b;
+  [!a] set word=0;
+  [a]  set word=1;
+  send to debug.in;
+  set olc--;
+  [d] abort;
+  set flags a=a, b=!b;
+  tail;
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+alu.in2:
+  set word=0;
+  set ilc=4;
+  deliver;
+  set word=1;
+  set ilc=4;
+  deliver;
+
+fifo.out:
+  send token to alu.out:1;
+  send token to alu.out:1;
+  send token to alu.out:0;
+  send token to alu.out:0;
+  send token to alu.out:1;
+  send token to alu.out:1;
+  send token to alu.out:0;
+  send token to alu.out:0;
+
+
diff --git a/tests/flags/flags-ab-1.test b/tests/flags/flags-ab-1.test
new file mode 100644 (file)
index 0000000..9d0fd1d
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 1
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=0;
+  [a] set word= 1;
+  [b] set word= 2;
+  deliver;
diff --git a/tests/flags/flags-ab-2.test b/tests/flags/flags-ab-2.test
new file mode 100644 (file)
index 0000000..d022f21
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 4
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=0, b=1;
+  [a] set word= 3;
+  [b] set word= 4;
+  deliver;
diff --git a/tests/flags/flags-ab-3.test b/tests/flags/flags-ab-3.test
new file mode 100644 (file)
index 0000000..28b2d2c
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 6
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=1;
+  [a] set word= 5;
+  [b] set word= 6;
+  deliver;
diff --git a/tests/flags/flags-ab-4.test b/tests/flags/flags-ab-4.test
new file mode 100644 (file)
index 0000000..a5a1046
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 8
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=1;
+  [b] set word= 7;
+  [a] set word= 8;
+  deliver;
diff --git a/tests/flags/flags-ab-5.test b/tests/flags/flags-ab-5.test
new file mode 100644 (file)
index 0000000..3c2a6b6
--- /dev/null
@@ -0,0 +1,12 @@
+// expected output
+#expect 9
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=0, b=0;
+  set word= 9;
+  [b] set word= 10;
+  [a] set word= 11;
+  deliver;
diff --git a/tests/flags/flags-ab-not-1.test b/tests/flags/flags-ab-not-1.test
new file mode 100644 (file)
index 0000000..44760fe
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 2
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=0;
+  [!a] set word= 1;
+  [!b] set word= 2;
+  deliver;
diff --git a/tests/flags/flags-ab-not-2.test b/tests/flags/flags-ab-not-2.test
new file mode 100644 (file)
index 0000000..54652ed
--- /dev/null
@@ -0,0 +1,11 @@
+// expected output
+#expect 3
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=0, b=1;
+  [!a] set word= 3;
+  [!b] set word= 4;
+  deliver;
diff --git a/tests/flags/flags-ab-not-3.test b/tests/flags/flags-ab-not-3.test
new file mode 100644 (file)
index 0000000..ed2f128
--- /dev/null
@@ -0,0 +1,12 @@
+// expected output
+#expect 4
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=1;
+  set word= 4;
+  [!a] set word= 5;
+  [!b] set word= 6;
+  deliver;
diff --git a/tests/flags/flags-ab-not-4.test b/tests/flags/flags-ab-not-4.test
new file mode 100644 (file)
index 0000000..c8bac2f
--- /dev/null
@@ -0,0 +1,12 @@
+// expected output
+#expect 6
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=1, b=1;
+  set word= 6;
+  [!b] set word= 7;
+  [!a] set word= 8;
+  deliver;
diff --git a/tests/flags/flags-ab-not-5.test b/tests/flags/flags-ab-not-5.test
new file mode 100644 (file)
index 0000000..99fddab
--- /dev/null
@@ -0,0 +1,12 @@
+// expected output
+#expect 11
+
+// ships required in order to run this code
+#ship debug        : Debug
+
+debug.in:
+  set flags a=0, b=0;
+  set word= 9;
+  [!b] set word= 10;
+  [!a] set word= 11;
+  deliver;
diff --git a/tests/flags/flags-reset.test b/tests/flags/flags-reset.test
new file mode 100644 (file)
index 0000000..6929934
--- /dev/null
@@ -0,0 +1,19 @@
+// expected output
+#expect 1
+#expect 20
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set flags a=1, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  deliver;
+  set word= 0;
+  set word= 1;
+  set flags a=0, b=b;
+  nop;
+  [!a] set word= 20;
+  deliver;
+
diff --git a/tests/flags/signal-0-from-inbox-to-inbox.test b/tests/flags/signal-0-from-inbox-to-inbox.test
new file mode 100644 (file)
index 0000000..b7179a6
--- /dev/null
@@ -0,0 +1,17 @@
+// expected output
+#expect 0
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set word= 2;
+  set ilc=1;
+  recv;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  deliver;
+
+fifo.in:
+  send token to debug.in:0;
diff --git a/tests/flags/signal-0-from-inbox-to-outbox.test.test b/tests/flags/signal-0-from-inbox-to-outbox.test.test
new file mode 100644 (file)
index 0000000..dc332b9
--- /dev/null
@@ -0,0 +1,20 @@
+// expected output
+#expect 0
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  send token to fifo.out:0;
+  set ilc=*;  recv, deliver;
+
+fifo.out:
+  set word= 2;
+  set ilc=1;
+  recv token;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+
diff --git a/tests/flags/signal-0-from-outbox-to-inbox.test b/tests/flags/signal-0-from-outbox-to-inbox.test
new file mode 100644 (file)
index 0000000..7762c1b
--- /dev/null
@@ -0,0 +1,17 @@
+// expected output
+#expect 0
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set word= 2;
+  set ilc=1;
+  recv;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  deliver;
+
+fifo.out:
+  send token to debug.in:0;
diff --git a/tests/flags/signal-0-from-outbox-to-outbox.test.test b/tests/flags/signal-0-from-outbox-to-outbox.test.test
new file mode 100644 (file)
index 0000000..383e9dc
--- /dev/null
@@ -0,0 +1,21 @@
+// expected output
+#expect 0
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  send token to fifo.out:0;
+  set ilc=*;  recv, deliver;
+
+fifo.out:
+  set word= 2;
+  set ilc=1;
+  recv token;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+
+
diff --git a/tests/flags/signal-1-from-inbox-to-inbox.test b/tests/flags/signal-1-from-inbox-to-inbox.test
new file mode 100644 (file)
index 0000000..b88cd01
--- /dev/null
@@ -0,0 +1,17 @@
+// expected output
+#expect 1
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set word= 2;
+  set ilc=1;
+  recv;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  deliver;
+
+fifo.in:
+  send token to debug.in:1;
diff --git a/tests/flags/signal-1-from-inbox-to-outbox.test.test b/tests/flags/signal-1-from-inbox-to-outbox.test.test
new file mode 100644 (file)
index 0000000..43a0d00
--- /dev/null
@@ -0,0 +1,20 @@
+// expected output
+#expect 1
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  send token to fifo.out:1;
+  set ilc=*;  recv, deliver;
+
+fifo.out:
+  set word= 2;
+  set ilc=1;
+  recv token;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
+
diff --git a/tests/flags/signal-1-from-outbox-to-inbox.test b/tests/flags/signal-1-from-outbox-to-inbox.test
new file mode 100644 (file)
index 0000000..6993911
--- /dev/null
@@ -0,0 +1,17 @@
+// expected output
+#expect 1
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  set word= 2;
+  set ilc=1;
+  recv;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  deliver;
+
+fifo.out:
+  send token to debug.in:1;
diff --git a/tests/flags/signal-1-from-outbox-to-outbox.test.test b/tests/flags/signal-1-from-outbox-to-outbox.test.test
new file mode 100644 (file)
index 0000000..69ac0e9
--- /dev/null
@@ -0,0 +1,19 @@
+// expected output
+#expect 1
+
+#ship debug        : Debug
+#ship fifo         : Fifo
+
+debug.in:
+  send token to fifo.out:1;
+  set ilc=*;  recv, deliver;
+
+fifo.out:
+  set word= 2;
+  set ilc=1;
+  recv token;
+  set flags a=c, b=b;
+  [a]  set word= 1;
+  [!a] set word= 0;
+  send to debug.in;
+
diff --git a/tests/flush/flush-alu.test b/tests/flush/flush-alu.test
new file mode 100644 (file)
index 0000000..bd7f968
--- /dev/null
@@ -0,0 +1,39 @@
+// FIXME: need test for ADD carry-out c-flag
+
+#ship debug : Debug
+#ship alu   : Alu
+
+#expect 18
+#expect 12
+
+debug.in:   set ilc=*;  recv, deliver;
+alu.in1:
+  set word=9;
+  deliver;
+  set word=9;
+  deliver;
+  flush;
+  set word=3;
+  deliver;
+
+alu.in2:
+  set word=9;
+  deliver;
+  set word=10;
+  flush;
+  set word=9;
+  deliver;
+
+alu.inOp:
+ set word=Alu.inOp[ADD];
+ deliver;
+ deliver;
+ deliver;
+ deliver;
+ flush;
+ deliver;
+ deliver;
+
+alu.out:
+  set ilc=*;
+  collect, send to debug.in;
diff --git a/tests/flush/flush-debug.test b/tests/flush/flush-debug.test
new file mode 100644 (file)
index 0000000..8790ed6
--- /dev/null
@@ -0,0 +1,14 @@
+// FIXME: need test for ADD carry-out c-flag
+
+#ship debug : Debug
+
+#expect 1
+#expect 3
+
+debug.in:
+  set word=1;
+  deliver;
+  set word=2;
+  flush;
+  set word=3;
+  deliver;
diff --git a/tests/flush/flush-fifo.test b/tests/flush/flush-fifo.test
new file mode 100644 (file)
index 0000000..4bcf7d6
--- /dev/null
@@ -0,0 +1,23 @@
+// FIXME: need test for ADD carry-out c-flag
+
+#ship debug : Debug
+#ship fifo  : Fifo
+
+#expect 1
+#expect 3
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+fifo.out:
+  set ilc=*;
+  collect, send to debug.in;
+
+fifo.in:
+  set word=1;
+  deliver;
+  set word=2;
+  flush;
+  set word=3;
+  deliver;
diff --git a/tests/literals/negative-absolute-literals.fleet b/tests/literals/negative-absolute-literals.fleet
new file mode 100644 (file)
index 0000000..f097e14
--- /dev/null
@@ -0,0 +1,8 @@
+#expect -1
+#ship debug : Debug
+
+debug.in:
+  set word= -1;
+  deliver;
+
+
diff --git a/tests/memory/memory-test.fleet b/tests/memory/memory-test.fleet
new file mode 100644 (file)
index 0000000..37ff646
--- /dev/null
@@ -0,0 +1,46 @@
+// output ///////////////////////////////////////////////////////////////////
+#expect 14
+#expect 13
+#expect 12
+#expect 11
+
+// program //////////////////////////////////////////////////////////////////
+#ship debug        : Debug
+#ship memory       : Memory
+#ship fifo         : Fifo
+
+// dumb configurations
+debug.in:           set ilc=*;  recv, deliver;
+memory.inAddrRead:  set ilc=*;  recv, deliver;
+
+// send write-completion tokens to the fifo output
+memory.out:
+  set ilc=4;  collect, send token to fifo.out;
+  set ilc=*;  collect, send to debug.in;
+
+memory.inAddrWrite: set word= 1; deliver;
+memory.inDataWrite: set word= 11; deliver;
+
+memory.inAddrWrite:  set word= 2; deliver;
+memory.inDataWrite:  set word= 12; deliver;
+
+memory.inAddrWrite:  set word= 3; deliver;
+memory.inDataWrite:  set word= 13; deliver;
+
+memory.inAddrWrite:  set word= 4; deliver;
+memory.inDataWrite:  set word= 14; deliver;
+
+// when the write-completion tokens accumulate, unleash
+// the read addresses
+fifo.out:
+  set ilc=4;  recv token;
+  set ilc=4;  collect, send to memory.inAddrRead;
+
+fifo.in:
+  set word= 4; deliver;
+  set word= 3; deliver;
+  set word= 2; deliver;
+  set word= 1; deliver;
+
+
+
diff --git a/tests/multiply.test- b/tests/multiply.test-
new file mode 100644 (file)
index 0000000..08c9df1
--- /dev/null
@@ -0,0 +1,66 @@
+#skip
+#ship alu3    : Alu3
+#ship lut3    : Lut3
+#ship bitfifo : BitFifo
+#ship debug   : Debug
+#ship fifo    : Fifo
+#ship rotator : Rotator
+
+#expect -66848683
+#expect 18682
+
+// 0:  100100100111110000000
+// sel 011110100001001000000
+// 1:  111000101000011000011
+// r:  111000100110111000000
+
+bitfifo.in:
+  deliver;      // deliver a junk word
+  set word= 10000;
+  set ilc=37; deliver; // deliver it 37 times (once per bit)
+  set word= 0;
+  set ilc=38; deliver; // deliver it 37 times
+
+// insert bits in lsb order
+bitfifo.inOp:
+  set word= BitFifo.inOp[lsbFirst,take=37];
+  set ilc=*;  deliver;
+
+// toss out 37 bits, take one, repeat.  sign extend the result
+bitfifo.outOp:
+  set word= BitFifo.outOp[drop=37,take=1,signExtend];
+  set ilc=*;  deliver;
+
+bitfifo.out:        set ilc=*;  recv token, take, send to lut3.in2;
+lut3.in2:           set ilc=4; send token to bitfifo.out;
+                    set ilc=63;
+                    take, deliver, send token to bitfifo.out;
+                    set ilc=11;
+                    take, deliver, send token to bitfifo.out;
+
+// mux on second input
+lut3.inLut:         set word= 226;
+                    set ilc=*;  deliver;
+
+lut3.in1:           set word= 18683;
+                    set ilc=37; deliver;
+                    set word= 0;
+                    set ilc=37; deliver;
+
+lut3.in3:           set word= 12000;
+                    set ilc=37; deliver;
+                    set word= 0;
+                    set ilc=37; deliver;
+
+lut3.out:           set ilc=*;  recv token, take, send to alu3.in2;
+
+alu3.in1:      set word= 0; deliver; set ilc=*;  take, deliver;
+alu3.in2:      send token to lut3.out; set ilc=*;  take, deliver, send token to lut3.out;
+alu3.in3:      set word= 0; deliver; set ilc=*;  take, deliver;
+alu3.outBits:  set ilc=*;  take, send to debug.in;
+
+alu3.out1:     set ilc=*;  take, send to alu3.in1;
+alu3.out2:     set ilc=*;  take, send to alu3.in3;
+
+debug.in:      set ilc=*;  take, deliver;
+
diff --git a/tests/ndp/p-plus.fleet- b/tests/ndp/p-plus.fleet-
new file mode 100644 (file)
index 0000000..9e9921a
--- /dev/null
@@ -0,0 +1,84 @@
+
+#expect 0
+
+#ship mem1  : Memory
+#ship mem2  : Memory
+#ship mem3  : Memory
+#ship alu   : Alu2
+#ship counter1   : Alu2
+#ship counter2   : Alu2
+#ship debug : Debug
+
+debug.in:   set ilc=*;  recv, deliver;
+mem1.inCBD:
+  set word= SETUP; deliver;
+  recv;
+  recv;
+  set word= GO; deliver;
+
+SETUP: {
+mem1.inAddrWrite: set word= 1000; [11] deliver;
+mem1.inDataWrite:
+  set word= 10; deliver;
+  set word= 1;  deliver;
+  set word= 2;  deliver;
+  set word= 3;  deliver;
+  set word= 4;  deliver;
+  set word= 5;  deliver;
+  set word= 6;  deliver;
+  set word= 7;  deliver;
+  set word= 8;  deliver;
+  set word= 9;  deliver;
+mem1.out:
+  [11] collect;
+  send token to mem1.inCBD;
+mem2.inAddrWrite: set word= 1000; [11] deliver;
+mem2.inDataWrite:
+  set word= 10; deliver;
+  set word= 1;  deliver;
+  set word= 2;  deliver;
+  set word= 3;  deliver;
+  set word= 4;  deliver;
+  set word= 5;  deliver;
+  set word= 6;  deliver;
+  set word= 7;  deliver;
+  set word= 8;  deliver;
+  set word= 9;  deliver;
+mem2.out:
+  [11] collect;
+  send token to mem1.inCBD;
+}
+
+GO: {
+
+mem1.inAddrRead:  set word= 1000; deliver;
+mem2.inAddrRead:  set word= 1000; deliver;
+
+// normally we would write to memory, but here we send to debug
+//mem3.inAddrWrite: set word= 0; deliver;
+//mem3.out:         set ilc=*;  collect, send to debug.in;
+
+alu.in1:  set ilc=*;  recv, deliver;
+alu.in2:  set ilc=*;  recv, deliver;
+alu.inOp: set word= Alu2.inOp[MAX]; deliver; set word= Alu2.inOp[ADD]; set ilc=*;  deliver;
+//alu.out:  set ilc=*;  collect, send to debug.in;
+
+mem1.out:
+  collect;
+  send to counter1.in1;
+  send to alu.in1;
+  set ilc=data;
+  collect, send to alu.in1;
+mem2.out:
+  collect;
+  send to counter2.in1;
+  send to alu.in2;
+  set ilc=data;
+  collect, send to alu.in2;
+
+counter1.in1:  set word= 10; set ilc=data; set word= 1; deliver;
+counter1.in2:  set word= 0; deliver; set ilc=*;  recv, deliver;
+counter1.inOp: set word= Alu2.inOp[ADD]; set ilc=*;  deliver;
+counter1.out:  set olc=1; collect; send to debug.in; unclog;
+
+}
diff --git a/tests/requeue/requeueing-literal.fleet b/tests/requeue/requeueing-literal.fleet
new file mode 100644 (file)
index 0000000..a6eed71
--- /dev/null
@@ -0,0 +1,30 @@
+#expect 5
+#expect 9
+#expect 5
+#expect 9
+#expect 5
+#expect 9
+
+#ship fifo : Fifo
+#ship debug : Debug
+
+fifo.in:
+  set word= 9;
+  set ilc=6;
+  deliver;
+
+debug.in:
+  set ilc=*;  recv, deliver;
+
+fifo.out:
+  set olc=3;
+  head;
+  set word= 5;
+  send to debug.in;
+  collect;
+  send to debug.in;
+  [d] abort;
+  tail;
+
+
+  
diff --git a/tests/requeue/test-for-common-requeue-timing-error.fleet b/tests/requeue/test-for-common-requeue-timing-error.fleet
new file mode 100644 (file)
index 0000000..4a9e007
--- /dev/null
@@ -0,0 +1,49 @@
+#expect 14
+#expect 14
+#expect 14
+#expect 14
+#expect 14
+#expect 14
+
+#ship debug0       : Debug
+#ship fifo0        : Fifo
+#ship fifo1        : Fifo
+#ship alu20        : Alu
+#ship alu21        : Alu
+
+
+fifo0.out: set olc=1;
+fifo0.out: collect;
+
+debug0.in: set ilc=*;
+debug0.in: recv, deliver, send token to alu21.out;
+
+fifo0.in: set word= 12;
+fifo0.in: set ilc=*;
+fifo0.in: deliver;
+
+alu21.inOp: set word= 2;
+alu21.inOp: set ilc=6;
+alu21.inOp: deliver;
+
+alu21.in1: set ilc=*;
+alu21.in1: recv, deliver, send token to fifo0.out;
+
+fifo0.out: head;
+fifo0.out: send to alu21.in1;
+fifo0.out: recv token;
+
+alu21.in2: set word= 2;
+alu21.in2: set ilc=*;
+alu21.in2: deliver;
+
+fifo0.out: tail;
+
+alu21.out: send token to alu21.out;
+alu21.out: set olc=1;
+alu21.out: head;
+alu21.out: collect;
+//alu21.out: set flags a=a, b=b;   // uncommenting this line will mask the bug
+alu21.out: send to debug0.in;
+alu21.out: recv token;
+alu21.out: tail;
diff --git a/tests/requeue/test-requeue.fleet b/tests/requeue/test-requeue.fleet
new file mode 100644 (file)
index 0000000..2f0e1d8
--- /dev/null
@@ -0,0 +1,69 @@
+#expect 6
+#expect 6
+#expect 6
+#expect 6
+#expect 10
+#expect 10
+#expect 10
+#expect 10
+#expect 14
+#expect 14
+#expect 14
+#expect 14
+#expect 18
+#expect 18
+#expect 18
+#expect 18
+#expect 22
+#expect 22
+#expect 22
+#expect 22
+#expect 26
+#expect 26
+#expect 26
+#expect 26
+#expect 30
+#expect 30
+#expect 30
+#expect 30
+#expect 34
+#expect 34
+#expect 34
+#expect 34
+#expect 38
+#expect 38
+#expect 38
+#expect 38
+#expect 42
+#expect 42
+#expect 42
+#expect 42
+#expect 46
+
+#ship alu   : Alu
+#ship debug : Debug
+
+alu.inOp:  set word=Alu.inOp[ADD];
+           set ilc=*;  deliver;
+
+debug.in:  set ilc=41;  recv, deliver, send token to alu.out;
+
+alu.in2:   set word= 4;
+           set ilc=*;  deliver;
+
+alu.out:   set olc=40;
+           head;
+           collect, send to alu.in1;
+           send to debug.in;
+           recv token;
+           tail;
+
+alu.in1:   set word= 2;
+           set ilc=4;
+           deliver;
+           set olc=2;
+           head;
+           recv, deliver;
+           recv nothing, deliver;
+           tail;
+
diff --git a/tests/torpedo/basic-torpedo-inbox.test b/tests/torpedo/basic-torpedo-inbox.test
new file mode 100644 (file)
index 0000000..660ef10
--- /dev/null
@@ -0,0 +1,17 @@
+#expect 20
+#ship debug : Debug
+#ship fifo  : Fifo
+
+debug.in:
+  head;
+  send token to fifo.out;
+  set ilc=*;
+  [T] recv token;
+  [*] set word= 20;
+  [*] deliver;
+  tail;
+
+fifo.out:
+  recv token;
+  send token to debug.in:i;
+
diff --git a/tests/torpedo/basic-torpedo-outbox.test b/tests/torpedo/basic-torpedo-outbox.test
new file mode 100644 (file)
index 0000000..a8a21bd
--- /dev/null
@@ -0,0 +1,21 @@
+#expect 20
+#ship debug : Debug
+#ship fifo  : Fifo
+
+debug.in:
+  set ilc=*;
+  recv, deliver;
+
+fifo.out:
+  head;
+  send token to fifo.in;
+  set ilc=*;
+  [T] recv token;
+  [*] set word=20;
+  [*] send to debug.in;
+  tail;
+
+fifo.in:
+  recv token;
+  send token to fifo.out:i;
+
diff --git a/tests/torpedo/epilogue-fifo.test b/tests/torpedo/epilogue-fifo.test
new file mode 100644 (file)
index 0000000..e858d00
--- /dev/null
@@ -0,0 +1,17 @@
+#expect 0
+#expect 0
+#ship debug : Debug
+#ship fifo  : Fifo
+
+debug.in:
+  set word= 0;
+  head;
+  nop;
+  deliver;
+  set olc=0;
+  [d] abort;
+  [d] deliver;
+  tail;
+
+
+
diff --git a/tests/torpedo/infinite-nop-is-torpedoable.fleet b/tests/torpedo/infinite-nop-is-torpedoable.fleet
new file mode 100644 (file)
index 0000000..6491543
--- /dev/null
@@ -0,0 +1,13 @@
+#expect 5
+#ship debug : Debug
+#ship fifo  : Fifo
+
+debug.in:
+  set ilc=*;
+  [T] nop;
+  [*] set word=5;
+  [*] deliver;
+
+fifo.out:
+  send token to debug.in:i;
+