From fafea3fd0253d776c0fed25b8debf2f506973786 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 12 Jul 2010 15:33:22 +0000 Subject: [PATCH] Initial import of stratus1 --- stratus1/CMakeLists.txt | 68 + stratus1/LICENSE | 340 ++++ stratus1/configure.in | 28 + stratus1/devdoc/.latex2html-init | 308 ++++ stratus1/devdoc/ASIM.css | 164 ++ stratus1/devdoc/Makefile | 37 + stratus1/devdoc/man_inst.tex | 52 + stratus1/devdoc/man_model.tex | 66 + stratus1/devdoc/man_net.tex | 73 + stratus1/devdoc/man_stratus.tex | 119 ++ stratus1/devdoc/see_also.tex | 3 + stratus1/devdoc/stratus.tex | 90 ++ stratus1/doc/.latex2html-init | 308 ++++ stratus1/doc/ASIM.css | 164 ++ stratus1/doc/Makefile.am | 2 + stratus1/doc/Makefile.manual | 34 + stratus1/doc/developper/.latex2html-init | 308 ++++ stratus1/doc/developper/ASIM.css | 164 ++ stratus1/doc/developper/Makefile | 37 + stratus1/doc/developper/Makefile.am | 70 + stratus1/doc/developper/html.entry | 1 + stratus1/doc/developper/man_inst.tex | 50 + stratus1/doc/developper/man_model.tex | 66 + stratus1/doc/developper/man_net.tex | 73 + stratus1/doc/developper/man_stratus.tex | 119 ++ stratus1/doc/developper/see_also.tex | 3 + stratus1/doc/developper/stratus.out | 18 + stratus1/doc/developper/stratus.tex | 90 ++ stratus1/doc/developper/stratus/ASIM.css | 164 ++ stratus1/doc/developper/stratus/WARNINGS | 9 + stratus1/doc/developper/stratus/index.html | 130 ++ stratus1/doc/developper/stratus/internals.pl | 18 + stratus1/doc/developper/stratus/labels.pl | 25 + stratus1/doc/developper/stratus/node1.html | 227 +++ stratus1/doc/developper/stratus/node2.html | 239 +++ stratus1/doc/developper/stratus/node3.html | 193 +++ stratus1/doc/developper/stratus/stratus.css | 33 + stratus1/doc/developper/stratus/stratus.html | 130 ++ stratus1/doc/dpgen/.latex2html-init | 308 ++++ stratus1/doc/dpgen/ASIM.css | 164 ++ stratus1/doc/dpgen/Makefile.am | 98 ++ stratus1/doc/dpgen/dpgen.tex | 142 ++ stratus1/doc/dpgen/html.entry | 1 + stratus1/doc/dpgen/man_dpgenadsb2f.tex | 76 + stratus1/doc/dpgen/man_dpgenand2.tex | 69 + stratus1/doc/dpgen/man_dpgenand3.tex | 72 + stratus1/doc/dpgen/man_dpgenand4.tex | 75 + stratus1/doc/dpgen/man_dpgenbuff.tex | 66 + stratus1/doc/dpgen/man_dpgenbuse.tex | 65 + stratus1/doc/dpgen/man_dpgenconst.tex | 60 + stratus1/doc/dpgen/man_dpgendff.tex | 69 + stratus1/doc/dpgen/man_dpgendfft.tex | 77 + stratus1/doc/dpgen/man_dpgenfifo.tex | 91 ++ stratus1/doc/dpgen/man_dpgeninv.tex | 66 + stratus1/doc/dpgen/man_dpgenmux2.tex | 74 + stratus1/doc/dpgen/man_dpgennand2.tex | 69 + stratus1/doc/dpgen/man_dpgennand2mask.tex | 74 + stratus1/doc/dpgen/man_dpgennand3.tex | 72 + stratus1/doc/dpgen/man_dpgennand4.tex | 75 + stratus1/doc/dpgen/man_dpgennbuse.tex | 65 + stratus1/doc/dpgen/man_dpgennmux2.tex | 67 + stratus1/doc/dpgen/man_dpgennor2.tex | 69 + stratus1/doc/dpgen/man_dpgennor2mask.tex | 74 + stratus1/doc/dpgen/man_dpgennor3.tex | 72 + stratus1/doc/dpgen/man_dpgennor4.tex | 76 + stratus1/doc/dpgen/man_dpgennul.tex | 58 + stratus1/doc/dpgen/man_dpgenor2.tex | 70 + stratus1/doc/dpgen/man_dpgenor3.tex | 72 + stratus1/doc/dpgen/man_dpgenor4.tex | 75 + stratus1/doc/dpgen/man_dpgenram.tex | 72 + stratus1/doc/dpgen/man_dpgenrf1.tex | 82 + stratus1/doc/dpgen/man_dpgenrf1d.tex | 89 ++ stratus1/doc/dpgen/man_dpgenrom2.tex | 66 + stratus1/doc/dpgen/man_dpgenrom4.tex | 76 + stratus1/doc/dpgen/man_dpgensff.tex | 69 + stratus1/doc/dpgen/man_dpgensfft.tex | 77 + stratus1/doc/dpgen/man_dpgenshift.tex | 69 + stratus1/doc/dpgen/man_dpgenshrot.tex | 70 + stratus1/doc/dpgen/man_dpgenxnor2.tex | 69 + stratus1/doc/dpgen/man_dpgenxnor2mask.tex | 74 + stratus1/doc/dpgen/man_dpgenxor2.tex | 69 + stratus1/doc/html.entry | 1 + stratus1/doc/images/Makefile.am | 11 + stratus1/doc/images/add1.png | Bin 0 -> 5500 bytes stratus1/doc/images/add2.png | Bin 0 -> 15347 bytes stratus1/doc/images/addaccu.png | Bin 0 -> 111942 bytes stratus1/doc/images/editor.png | Bin 0 -> 43831 bytes stratus1/doc/images/test.png | Bin 0 -> 23992 bytes stratus1/doc/images/xml.png | Bin 0 -> 44214 bytes stratus1/doc/man_alias.tex | 62 + stratus1/doc/man_alim_connectors.tex | 23 + stratus1/doc/man_alim_rail.tex | 52 + stratus1/doc/man_arithmetic.tex | 73 + stratus1/doc/man_boolean.tex | 65 + stratus1/doc/man_buff.tex | 44 + stratus1/doc/man_cat.tex | 47 + stratus1/doc/man_comp.tex | 67 + stratus1/doc/man_const.tex | 81 + stratus1/doc/man_def_ab.tex | 49 + stratus1/doc/man_dpgenadsb2f.tex | 58 + stratus1/doc/man_dpgenand2.tex | 48 + stratus1/doc/man_dpgenand3.tex | 51 + stratus1/doc/man_dpgenand4.tex | 54 + stratus1/doc/man_dpgenbuff.tex | 45 + stratus1/doc/man_dpgenbuse.tex | 49 + stratus1/doc/man_dpgenconst.tex | 38 + stratus1/doc/man_dpgendff.tex | 50 + stratus1/doc/man_dpgendfft.tex | 58 + stratus1/doc/man_dpgenfifo.tex | 79 + stratus1/doc/man_dpgeninv.tex | 45 + stratus1/doc/man_dpgenmux2.tex | 54 + stratus1/doc/man_dpgennand2.tex | 48 + stratus1/doc/man_dpgennand2mask.tex | 55 + stratus1/doc/man_dpgennand3.tex | 51 + stratus1/doc/man_dpgennand4.tex | 54 + stratus1/doc/man_dpgennbuse.tex | 46 + stratus1/doc/man_dpgennmux2.tex | 55 + stratus1/doc/man_dpgennor2.tex | 48 + stratus1/doc/man_dpgennor2mask.tex | 55 + stratus1/doc/man_dpgennor3.tex | 51 + stratus1/doc/man_dpgennor4.tex | 54 + stratus1/doc/man_dpgennul.tex | 41 + stratus1/doc/man_dpgenor2.tex | 48 + stratus1/doc/man_dpgenor3.tex | 51 + stratus1/doc/man_dpgenor4.tex | 54 + stratus1/doc/man_dpgenram.tex | 56 + stratus1/doc/man_dpgenrf1.tex | 70 + stratus1/doc/man_dpgenrf1d.tex | 81 + stratus1/doc/man_dpgenrom2.tex | 48 + stratus1/doc/man_dpgenrom4.tex | 56 + stratus1/doc/man_dpgensff.tex | 50 + stratus1/doc/man_dpgensfft.tex | 58 + stratus1/doc/man_dpgenshift.tex | 54 + stratus1/doc/man_dpgenshrot.tex | 55 + stratus1/doc/man_dpgenxnor2.tex | 48 + stratus1/doc/man_dpgenxnor2mask.tex | 55 + stratus1/doc/man_dpgenxor2.tex | 48 + stratus1/doc/man_example.tex | 63 + stratus1/doc/man_extend.tex | 52 + stratus1/doc/man_fill_cell.tex | 44 + stratus1/doc/man_generators.tex | 82 + stratus1/doc/man_inst.tex | 56 + stratus1/doc/man_library.tex | 68 + stratus1/doc/man_model.tex | 47 + stratus1/doc/man_mux.tex | 131 ++ stratus1/doc/man_net.tex | 57 + stratus1/doc/man_pads.tex | 51 + stratus1/doc/man_param.tex | 50 + stratus1/doc/man_place.tex | 60 + stratus1/doc/man_place_bottom.tex | 63 + stratus1/doc/man_place_centric.tex | 46 + stratus1/doc/man_place_glu.tex | 37 + stratus1/doc/man_place_left.tex | 63 + stratus1/doc/man_place_right.tex | 63 + stratus1/doc/man_place_top.tex | 63 + stratus1/doc/man_power_ring.tex | 45 + stratus1/doc/man_reg.tex | 51 + stratus1/doc/man_resize_ab.tex | 49 + stratus1/doc/man_route_ck.tex | 45 + stratus1/doc/man_set_ref_ins.tex | 53 + stratus1/doc/man_shift.tex | 82 + stratus1/doc/man_stratus.tex | 119 ++ stratus1/doc/patterns/.latex2html-init | 308 ++++ stratus1/doc/patterns/ASIM.css | 164 ++ stratus1/doc/patterns/Makefile.am | 66 + stratus1/doc/patterns/html.entry | 1 + stratus1/doc/patterns/patterns.tex | 269 ++++ stratus1/doc/see_also.tex | 3 + stratus1/doc/stratus.tex | 289 ++++ stratus1/doc/stratus/.latex2html-init | 308 ++++ stratus1/doc/stratus/ASIM.css | 164 ++ stratus1/doc/stratus/Makefile.am | 106 ++ stratus1/doc/stratus/fichiers/Makefile | 5 + stratus1/doc/stratus/fichiers/addaccu.py | 79 + stratus1/doc/stratus/fichiers/test.py | 19 + stratus1/doc/stratus/html.entry | 1 + stratus1/doc/stratus/images/Makefile.am | 13 + stratus1/doc/stratus/images/add1.png | Bin 0 -> 5500 bytes stratus1/doc/stratus/images/add2.png | Bin 0 -> 15347 bytes stratus1/doc/stratus/images/addaccu1.png | Bin 0 -> 102142 bytes stratus1/doc/stratus/images/addaccu2.png | Bin 0 -> 41878 bytes stratus1/doc/stratus/images/editor.png | Bin 0 -> 18669 bytes stratus1/doc/stratus/images/resizeAb.png | Bin 0 -> 949 bytes stratus1/doc/stratus/images/test.png | Bin 0 -> 24309 bytes stratus1/doc/stratus/images/xml.png | Bin 0 -> 36313 bytes stratus1/doc/stratus/man_alim_connectors.tex | 25 + stratus1/doc/stratus/man_alim_rail.tex | 56 + stratus1/doc/stratus/man_arithmetic.tex | 77 + stratus1/doc/stratus/man_boolean.tex | 69 + stratus1/doc/stratus/man_buff.tex | 48 + stratus1/doc/stratus/man_comp.tex | 71 + stratus1/doc/stratus/man_const.tex | 85 + stratus1/doc/stratus/man_copy_up_segment.tex | 54 + stratus1/doc/stratus/man_def_ab.tex | 54 + stratus1/doc/stratus/man_example.tex | 107 ++ stratus1/doc/stratus/man_fill_cell.tex | 48 + stratus1/doc/stratus/man_generate.tex | 59 + stratus1/doc/stratus/man_get_ref.tex | 51 + stratus1/doc/stratus/man_inst.tex | 56 + stratus1/doc/stratus/man_library.tex | 96 ++ stratus1/doc/stratus/man_mux.tex | 135 ++ stratus1/doc/stratus/man_net.tex | 118 ++ stratus1/doc/stratus/man_new.tex | 15 + stratus1/doc/stratus/man_pads.tex | 56 + stratus1/doc/stratus/man_place.tex | 64 + stratus1/doc/stratus/man_place_bottom.tex | 68 + stratus1/doc/stratus/man_place_centric.tex | 50 + stratus1/doc/stratus/man_place_contact.tex | 56 + stratus1/doc/stratus/man_place_glu.tex | 42 + stratus1/doc/stratus/man_place_left.tex | 68 + stratus1/doc/stratus/man_place_pin.tex | 60 + stratus1/doc/stratus/man_place_ref.tex | 49 + stratus1/doc/stratus/man_place_right.tex | 68 + stratus1/doc/stratus/man_place_segment.tex | 55 + stratus1/doc/stratus/man_place_top.tex | 68 + stratus1/doc/stratus/man_power_ring.tex | 49 + stratus1/doc/stratus/man_reg.tex | 55 + stratus1/doc/stratus/man_resize_ab.tex | 59 + stratus1/doc/stratus/man_route_ck.tex | 49 + stratus1/doc/stratus/man_set_ref_ins.tex | 57 + stratus1/doc/stratus/man_shift.tex | 86 + stratus1/doc/stratus/man_stratus.tex | 127 ++ stratus1/doc/stratus/see_also.tex | 3 + stratus1/doc/stratus/stratus.tex | 232 +++ stratus1/etc/CMakeLists.txt | 3 + stratus1/etc/stratus.vim | 174 +++ stratus1/etc/stratus2sxlib.xml | 32 + stratus1/src/CMakeLists.txt | 3 + stratus1/src/dpgen/CMakeLists.txt | 16 + stratus1/src/dpgen/ROM_encours.py | 865 +++++++++++ stratus1/src/dpgen/dpgen_ADSB2F.py | 362 +++++ stratus1/src/dpgen/dpgen_Nul.py | 406 +++++ stratus1/src/dpgen/dpgen_RAM.py | 675 ++++++++ stratus1/src/dpgen/dpgen_RF1.py | 1441 +++++++++++++++++ stratus1/src/dpgen/dpgen_RF2.py | 1145 ++++++++++++++ stratus1/src/dpgen/dpgen_ROM.py | 937 +++++++++++ stratus1/src/dpgen/dpgen_ROM2.py | 226 +++ stratus1/src/dpgen/dpgen_ROM4.py | 294 ++++ stratus1/src/dpgen/dpgen_Regular.py | 1463 ++++++++++++++++++ stratus1/src/dpgen/dpgen_Shifter.py | 263 ++++ stratus1/src/dpgen/dpgen_Shrot.py | 343 ++++ stratus1/src/lib/fulladder.vst | 102 ++ stratus1/src/modules/CMakeLists.txt | 2 + stratus1/src/modules/patterns/CMakeLists.txt | 9 + stratus1/src/modules/patterns/Makefile.am | 8 + stratus1/src/modules/patterns/patread.py | 203 +++ stratus1/src/modules/patterns/patterns.py | 86 + stratus1/src/modules/patterns/patwrite.py | 683 ++++++++ stratus1/src/modules/patterns/synopsys.py | 867 +++++++++++ stratus1/src/modules/patterns/utils.py | 616 ++++++++ stratus1/src/stratus/CMakeLists.txt | 36 + stratus1/src/stratus/st_bool.py | 159 ++ stratus1/src/stratus/st_cat.py | 104 ++ stratus1/src/stratus/st_comp.py | 198 +++ stratus1/src/stratus/st_const.py | 199 +++ stratus1/src/stratus/st_extend.py | 88 ++ stratus1/src/stratus/st_func_gen_wallace.py | 340 ++++ stratus1/src/stratus/st_generate.py | 115 ++ stratus1/src/stratus/st_getrealmodel.py | 93 ++ stratus1/src/stratus/st_instance.py | 375 +++++ stratus1/src/stratus/st_model.py | 1123 ++++++++++++++ stratus1/src/stratus/st_mult.py | 212 +++ stratus1/src/stratus/st_mult_blocs.py | 99 ++ stratus1/src/stratus/st_mult_matrix.py | 106 ++ stratus1/src/stratus/st_mux.py | 145 ++ stratus1/src/stratus/st_net.py | 1166 ++++++++++++++ stratus1/src/stratus/st_param.py | 76 + stratus1/src/stratus/st_parser.py | 215 +++ stratus1/src/stratus/st_placeAndRoute.py | 344 ++++ stratus1/src/stratus/st_placement.py | 537 +++++++ stratus1/src/stratus/st_ref.py | 242 +++ stratus1/src/stratus/st_shifter.py | 219 +++ stratus1/src/stratus/st_slansky.py | 409 +++++ stratus1/src/stratus/stratus.py | 71 + stratus1/src/stratus/util.py | 61 + stratus1/src/stratus/util_Const.py | 285 ++++ stratus1/src/stratus/util_Defs.py | 122 ++ stratus1/src/stratus/util_Gen.py | 102 ++ stratus1/src/stratus/util_Misc.py | 98 ++ stratus1/src/stratus/util_Place.py | 70 + stratus1/src/stratus/util_Route.py | 62 + stratus1/src/stratus/util_Shift.py | 67 + stratus1/src/stratus/util_uRom.py | 111 ++ 283 files changed, 34913 insertions(+) create mode 100644 stratus1/CMakeLists.txt create mode 100644 stratus1/LICENSE create mode 100644 stratus1/configure.in create mode 100644 stratus1/devdoc/.latex2html-init create mode 100644 stratus1/devdoc/ASIM.css create mode 100644 stratus1/devdoc/Makefile create mode 100644 stratus1/devdoc/man_inst.tex create mode 100644 stratus1/devdoc/man_model.tex create mode 100644 stratus1/devdoc/man_net.tex create mode 100644 stratus1/devdoc/man_stratus.tex create mode 100644 stratus1/devdoc/see_also.tex create mode 100644 stratus1/devdoc/stratus.tex create mode 100644 stratus1/doc/.latex2html-init create mode 100644 stratus1/doc/ASIM.css create mode 100644 stratus1/doc/Makefile.am create mode 100644 stratus1/doc/Makefile.manual create mode 100644 stratus1/doc/developper/.latex2html-init create mode 100644 stratus1/doc/developper/ASIM.css create mode 100644 stratus1/doc/developper/Makefile create mode 100644 stratus1/doc/developper/Makefile.am create mode 100644 stratus1/doc/developper/html.entry create mode 100644 stratus1/doc/developper/man_inst.tex create mode 100644 stratus1/doc/developper/man_model.tex create mode 100644 stratus1/doc/developper/man_net.tex create mode 100644 stratus1/doc/developper/man_stratus.tex create mode 100644 stratus1/doc/developper/see_also.tex create mode 100644 stratus1/doc/developper/stratus.out create mode 100644 stratus1/doc/developper/stratus.tex create mode 100644 stratus1/doc/developper/stratus/ASIM.css create mode 100644 stratus1/doc/developper/stratus/WARNINGS create mode 100644 stratus1/doc/developper/stratus/index.html create mode 100644 stratus1/doc/developper/stratus/internals.pl create mode 100644 stratus1/doc/developper/stratus/labels.pl create mode 100644 stratus1/doc/developper/stratus/node1.html create mode 100644 stratus1/doc/developper/stratus/node2.html create mode 100644 stratus1/doc/developper/stratus/node3.html create mode 100644 stratus1/doc/developper/stratus/stratus.css create mode 100644 stratus1/doc/developper/stratus/stratus.html create mode 100644 stratus1/doc/dpgen/.latex2html-init create mode 100644 stratus1/doc/dpgen/ASIM.css create mode 100644 stratus1/doc/dpgen/Makefile.am create mode 100644 stratus1/doc/dpgen/dpgen.tex create mode 100644 stratus1/doc/dpgen/html.entry create mode 100644 stratus1/doc/dpgen/man_dpgenadsb2f.tex create mode 100644 stratus1/doc/dpgen/man_dpgenand2.tex create mode 100644 stratus1/doc/dpgen/man_dpgenand3.tex create mode 100644 stratus1/doc/dpgen/man_dpgenand4.tex create mode 100644 stratus1/doc/dpgen/man_dpgenbuff.tex create mode 100644 stratus1/doc/dpgen/man_dpgenbuse.tex create mode 100644 stratus1/doc/dpgen/man_dpgenconst.tex create mode 100644 stratus1/doc/dpgen/man_dpgendff.tex create mode 100644 stratus1/doc/dpgen/man_dpgendfft.tex create mode 100644 stratus1/doc/dpgen/man_dpgenfifo.tex create mode 100644 stratus1/doc/dpgen/man_dpgeninv.tex create mode 100644 stratus1/doc/dpgen/man_dpgenmux2.tex create mode 100644 stratus1/doc/dpgen/man_dpgennand2.tex create mode 100644 stratus1/doc/dpgen/man_dpgennand2mask.tex create mode 100644 stratus1/doc/dpgen/man_dpgennand3.tex create mode 100644 stratus1/doc/dpgen/man_dpgennand4.tex create mode 100644 stratus1/doc/dpgen/man_dpgennbuse.tex create mode 100644 stratus1/doc/dpgen/man_dpgennmux2.tex create mode 100644 stratus1/doc/dpgen/man_dpgennor2.tex create mode 100644 stratus1/doc/dpgen/man_dpgennor2mask.tex create mode 100644 stratus1/doc/dpgen/man_dpgennor3.tex create mode 100644 stratus1/doc/dpgen/man_dpgennor4.tex create mode 100644 stratus1/doc/dpgen/man_dpgennul.tex create mode 100644 stratus1/doc/dpgen/man_dpgenor2.tex create mode 100644 stratus1/doc/dpgen/man_dpgenor3.tex create mode 100644 stratus1/doc/dpgen/man_dpgenor4.tex create mode 100644 stratus1/doc/dpgen/man_dpgenram.tex create mode 100644 stratus1/doc/dpgen/man_dpgenrf1.tex create mode 100644 stratus1/doc/dpgen/man_dpgenrf1d.tex create mode 100644 stratus1/doc/dpgen/man_dpgenrom2.tex create mode 100644 stratus1/doc/dpgen/man_dpgenrom4.tex create mode 100644 stratus1/doc/dpgen/man_dpgensff.tex create mode 100644 stratus1/doc/dpgen/man_dpgensfft.tex create mode 100644 stratus1/doc/dpgen/man_dpgenshift.tex create mode 100644 stratus1/doc/dpgen/man_dpgenshrot.tex create mode 100644 stratus1/doc/dpgen/man_dpgenxnor2.tex create mode 100644 stratus1/doc/dpgen/man_dpgenxnor2mask.tex create mode 100644 stratus1/doc/dpgen/man_dpgenxor2.tex create mode 100644 stratus1/doc/html.entry create mode 100644 stratus1/doc/images/Makefile.am create mode 100644 stratus1/doc/images/add1.png create mode 100644 stratus1/doc/images/add2.png create mode 100644 stratus1/doc/images/addaccu.png create mode 100644 stratus1/doc/images/editor.png create mode 100644 stratus1/doc/images/test.png create mode 100644 stratus1/doc/images/xml.png create mode 100644 stratus1/doc/man_alias.tex create mode 100644 stratus1/doc/man_alim_connectors.tex create mode 100644 stratus1/doc/man_alim_rail.tex create mode 100644 stratus1/doc/man_arithmetic.tex create mode 100644 stratus1/doc/man_boolean.tex create mode 100644 stratus1/doc/man_buff.tex create mode 100644 stratus1/doc/man_cat.tex create mode 100644 stratus1/doc/man_comp.tex create mode 100644 stratus1/doc/man_const.tex create mode 100644 stratus1/doc/man_def_ab.tex create mode 100644 stratus1/doc/man_dpgenadsb2f.tex create mode 100644 stratus1/doc/man_dpgenand2.tex create mode 100644 stratus1/doc/man_dpgenand3.tex create mode 100644 stratus1/doc/man_dpgenand4.tex create mode 100644 stratus1/doc/man_dpgenbuff.tex create mode 100644 stratus1/doc/man_dpgenbuse.tex create mode 100644 stratus1/doc/man_dpgenconst.tex create mode 100644 stratus1/doc/man_dpgendff.tex create mode 100644 stratus1/doc/man_dpgendfft.tex create mode 100644 stratus1/doc/man_dpgenfifo.tex create mode 100644 stratus1/doc/man_dpgeninv.tex create mode 100644 stratus1/doc/man_dpgenmux2.tex create mode 100644 stratus1/doc/man_dpgennand2.tex create mode 100644 stratus1/doc/man_dpgennand2mask.tex create mode 100644 stratus1/doc/man_dpgennand3.tex create mode 100644 stratus1/doc/man_dpgennand4.tex create mode 100644 stratus1/doc/man_dpgennbuse.tex create mode 100644 stratus1/doc/man_dpgennmux2.tex create mode 100644 stratus1/doc/man_dpgennor2.tex create mode 100644 stratus1/doc/man_dpgennor2mask.tex create mode 100644 stratus1/doc/man_dpgennor3.tex create mode 100644 stratus1/doc/man_dpgennor4.tex create mode 100644 stratus1/doc/man_dpgennul.tex create mode 100644 stratus1/doc/man_dpgenor2.tex create mode 100644 stratus1/doc/man_dpgenor3.tex create mode 100644 stratus1/doc/man_dpgenor4.tex create mode 100644 stratus1/doc/man_dpgenram.tex create mode 100644 stratus1/doc/man_dpgenrf1.tex create mode 100644 stratus1/doc/man_dpgenrf1d.tex create mode 100644 stratus1/doc/man_dpgenrom2.tex create mode 100644 stratus1/doc/man_dpgenrom4.tex create mode 100644 stratus1/doc/man_dpgensff.tex create mode 100644 stratus1/doc/man_dpgensfft.tex create mode 100644 stratus1/doc/man_dpgenshift.tex create mode 100644 stratus1/doc/man_dpgenshrot.tex create mode 100644 stratus1/doc/man_dpgenxnor2.tex create mode 100644 stratus1/doc/man_dpgenxnor2mask.tex create mode 100644 stratus1/doc/man_dpgenxor2.tex create mode 100644 stratus1/doc/man_example.tex create mode 100644 stratus1/doc/man_extend.tex create mode 100644 stratus1/doc/man_fill_cell.tex create mode 100644 stratus1/doc/man_generators.tex create mode 100644 stratus1/doc/man_inst.tex create mode 100644 stratus1/doc/man_library.tex create mode 100644 stratus1/doc/man_model.tex create mode 100644 stratus1/doc/man_mux.tex create mode 100644 stratus1/doc/man_net.tex create mode 100644 stratus1/doc/man_pads.tex create mode 100644 stratus1/doc/man_param.tex create mode 100644 stratus1/doc/man_place.tex create mode 100644 stratus1/doc/man_place_bottom.tex create mode 100644 stratus1/doc/man_place_centric.tex create mode 100644 stratus1/doc/man_place_glu.tex create mode 100644 stratus1/doc/man_place_left.tex create mode 100644 stratus1/doc/man_place_right.tex create mode 100644 stratus1/doc/man_place_top.tex create mode 100644 stratus1/doc/man_power_ring.tex create mode 100644 stratus1/doc/man_reg.tex create mode 100644 stratus1/doc/man_resize_ab.tex create mode 100644 stratus1/doc/man_route_ck.tex create mode 100644 stratus1/doc/man_set_ref_ins.tex create mode 100644 stratus1/doc/man_shift.tex create mode 100644 stratus1/doc/man_stratus.tex create mode 100644 stratus1/doc/patterns/.latex2html-init create mode 100644 stratus1/doc/patterns/ASIM.css create mode 100644 stratus1/doc/patterns/Makefile.am create mode 100644 stratus1/doc/patterns/html.entry create mode 100644 stratus1/doc/patterns/patterns.tex create mode 100644 stratus1/doc/see_also.tex create mode 100644 stratus1/doc/stratus.tex create mode 100644 stratus1/doc/stratus/.latex2html-init create mode 100644 stratus1/doc/stratus/ASIM.css create mode 100644 stratus1/doc/stratus/Makefile.am create mode 100644 stratus1/doc/stratus/fichiers/Makefile create mode 100644 stratus1/doc/stratus/fichiers/addaccu.py create mode 100755 stratus1/doc/stratus/fichiers/test.py create mode 100644 stratus1/doc/stratus/html.entry create mode 100644 stratus1/doc/stratus/images/Makefile.am create mode 100644 stratus1/doc/stratus/images/add1.png create mode 100644 stratus1/doc/stratus/images/add2.png create mode 100644 stratus1/doc/stratus/images/addaccu1.png create mode 100644 stratus1/doc/stratus/images/addaccu2.png create mode 100644 stratus1/doc/stratus/images/editor.png create mode 100644 stratus1/doc/stratus/images/resizeAb.png create mode 100644 stratus1/doc/stratus/images/test.png create mode 100644 stratus1/doc/stratus/images/xml.png create mode 100644 stratus1/doc/stratus/man_alim_connectors.tex create mode 100644 stratus1/doc/stratus/man_alim_rail.tex create mode 100644 stratus1/doc/stratus/man_arithmetic.tex create mode 100644 stratus1/doc/stratus/man_boolean.tex create mode 100644 stratus1/doc/stratus/man_buff.tex create mode 100644 stratus1/doc/stratus/man_comp.tex create mode 100644 stratus1/doc/stratus/man_const.tex create mode 100644 stratus1/doc/stratus/man_copy_up_segment.tex create mode 100644 stratus1/doc/stratus/man_def_ab.tex create mode 100644 stratus1/doc/stratus/man_example.tex create mode 100644 stratus1/doc/stratus/man_fill_cell.tex create mode 100644 stratus1/doc/stratus/man_generate.tex create mode 100644 stratus1/doc/stratus/man_get_ref.tex create mode 100644 stratus1/doc/stratus/man_inst.tex create mode 100644 stratus1/doc/stratus/man_library.tex create mode 100644 stratus1/doc/stratus/man_mux.tex create mode 100644 stratus1/doc/stratus/man_net.tex create mode 100644 stratus1/doc/stratus/man_new.tex create mode 100644 stratus1/doc/stratus/man_pads.tex create mode 100644 stratus1/doc/stratus/man_place.tex create mode 100644 stratus1/doc/stratus/man_place_bottom.tex create mode 100644 stratus1/doc/stratus/man_place_centric.tex create mode 100644 stratus1/doc/stratus/man_place_contact.tex create mode 100644 stratus1/doc/stratus/man_place_glu.tex create mode 100644 stratus1/doc/stratus/man_place_left.tex create mode 100644 stratus1/doc/stratus/man_place_pin.tex create mode 100644 stratus1/doc/stratus/man_place_ref.tex create mode 100644 stratus1/doc/stratus/man_place_right.tex create mode 100644 stratus1/doc/stratus/man_place_segment.tex create mode 100644 stratus1/doc/stratus/man_place_top.tex create mode 100644 stratus1/doc/stratus/man_power_ring.tex create mode 100644 stratus1/doc/stratus/man_reg.tex create mode 100644 stratus1/doc/stratus/man_resize_ab.tex create mode 100644 stratus1/doc/stratus/man_route_ck.tex create mode 100644 stratus1/doc/stratus/man_set_ref_ins.tex create mode 100644 stratus1/doc/stratus/man_shift.tex create mode 100644 stratus1/doc/stratus/man_stratus.tex create mode 100644 stratus1/doc/stratus/see_also.tex create mode 100644 stratus1/doc/stratus/stratus.tex create mode 100644 stratus1/etc/CMakeLists.txt create mode 100644 stratus1/etc/stratus.vim create mode 100644 stratus1/etc/stratus2sxlib.xml create mode 100644 stratus1/src/CMakeLists.txt create mode 100644 stratus1/src/dpgen/CMakeLists.txt create mode 100644 stratus1/src/dpgen/ROM_encours.py create mode 100644 stratus1/src/dpgen/dpgen_ADSB2F.py create mode 100644 stratus1/src/dpgen/dpgen_Nul.py create mode 100644 stratus1/src/dpgen/dpgen_RAM.py create mode 100644 stratus1/src/dpgen/dpgen_RF1.py create mode 100644 stratus1/src/dpgen/dpgen_RF2.py create mode 100644 stratus1/src/dpgen/dpgen_ROM.py create mode 100644 stratus1/src/dpgen/dpgen_ROM2.py create mode 100644 stratus1/src/dpgen/dpgen_ROM4.py create mode 100644 stratus1/src/dpgen/dpgen_Regular.py create mode 100644 stratus1/src/dpgen/dpgen_Shifter.py create mode 100644 stratus1/src/dpgen/dpgen_Shrot.py create mode 100644 stratus1/src/lib/fulladder.vst create mode 100644 stratus1/src/modules/CMakeLists.txt create mode 100644 stratus1/src/modules/patterns/CMakeLists.txt create mode 100644 stratus1/src/modules/patterns/Makefile.am create mode 100644 stratus1/src/modules/patterns/patread.py create mode 100644 stratus1/src/modules/patterns/patterns.py create mode 100644 stratus1/src/modules/patterns/patwrite.py create mode 100644 stratus1/src/modules/patterns/synopsys.py create mode 100644 stratus1/src/modules/patterns/utils.py create mode 100644 stratus1/src/stratus/CMakeLists.txt create mode 100644 stratus1/src/stratus/st_bool.py create mode 100644 stratus1/src/stratus/st_cat.py create mode 100644 stratus1/src/stratus/st_comp.py create mode 100644 stratus1/src/stratus/st_const.py create mode 100644 stratus1/src/stratus/st_extend.py create mode 100644 stratus1/src/stratus/st_func_gen_wallace.py create mode 100644 stratus1/src/stratus/st_generate.py create mode 100644 stratus1/src/stratus/st_getrealmodel.py create mode 100644 stratus1/src/stratus/st_instance.py create mode 100644 stratus1/src/stratus/st_model.py create mode 100644 stratus1/src/stratus/st_mult.py create mode 100644 stratus1/src/stratus/st_mult_blocs.py create mode 100644 stratus1/src/stratus/st_mult_matrix.py create mode 100644 stratus1/src/stratus/st_mux.py create mode 100644 stratus1/src/stratus/st_net.py create mode 100644 stratus1/src/stratus/st_param.py create mode 100644 stratus1/src/stratus/st_parser.py create mode 100644 stratus1/src/stratus/st_placeAndRoute.py create mode 100644 stratus1/src/stratus/st_placement.py create mode 100644 stratus1/src/stratus/st_ref.py create mode 100644 stratus1/src/stratus/st_shifter.py create mode 100644 stratus1/src/stratus/st_slansky.py create mode 100644 stratus1/src/stratus/stratus.py create mode 100644 stratus1/src/stratus/util.py create mode 100644 stratus1/src/stratus/util_Const.py create mode 100644 stratus1/src/stratus/util_Defs.py create mode 100644 stratus1/src/stratus/util_Gen.py create mode 100644 stratus1/src/stratus/util_Misc.py create mode 100644 stratus1/src/stratus/util_Place.py create mode 100644 stratus1/src/stratus/util_Route.py create mode 100644 stratus1/src/stratus/util_Shift.py create mode 100644 stratus1/src/stratus/util_uRom.py diff --git a/stratus1/CMakeLists.txt b/stratus1/CMakeLists.txt new file mode 100644 index 00000000..2f69d534 --- /dev/null +++ b/stratus1/CMakeLists.txt @@ -0,0 +1,68 @@ +PROJECT(STRATUS1) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0) +IF(COMMAND CMAKE_POLICY) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND CMAKE_POLICY) + +IF(APPLE) + EXECUTE_PROCESS( + COMMAND sw_vers -productVersion + OUTPUT_VARIABLE OSX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + MESSAGE(STATUS "OSX_VERSION='${OSX_VERSION}'") + IF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?") + MESSAGE(STATUS "OSX < 10.6") + ELSE(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?") + SET(CMAKE_OSX_ARCHITECTURES "i386;ppc") # for QT4.5 32bits on snow leopard + ENDIF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?") +ENDIF(APPLE) + +SET(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE) +SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) + +# This macro has to be included in all the tools CMakeLists.txt as it's +# the sole means of localizing other tools/projects. +MACRO(SETUP_PROJECT_PATHS project) + IF( NOT("$ENV{${project}_TOP}" STREQUAL "") ) + MESSAGE("-- ${project}_TOP is set to $ENV{${project}_TOP}") + SET(PROJECT_MODULE_PATH "${DESTDIR}$ENV{${project}_TOP}/share/cmake/Modules/") + LIST(INSERT CMAKE_MODULE_PATH 0 "${PROJECT_MODULE_PATH}") + ENDIF( NOT("$ENV{${project}_TOP}" STREQUAL "") ) + + IF( NOT("$ENV{${project}_USER_TOP}" STREQUAL "") ) + MESSAGE("-- ${project}_USER_TOP is set to $ENV{${project}_USER_TOP}") + SET(PROJECT_MODULE_PATH "${DESTDIR}$ENV{${project}_USER_TOP}/share/cmake/Modules/") + LIST(INSERT CMAKE_MODULE_PATH 0 "${PROJECT_MODULE_PATH}") + ENDIF( NOT("$ENV{${project}_USER_TOP}" STREQUAL "") ) + + LIST(REMOVE_DUPLICATES CMAKE_MODULE_PATH) +ENDMACRO(SETUP_PROJECT_PATHS project) + +SETUP_PROJECT_PATHS(VLSISAPD) +SETUP_PROJECT_PATHS(CORIOLIS) + +STRING(REGEX MATCH "^/usr" IS_USR "$ENV{CORIOLIS_TOP}") +STRING(REGEX MATCH "^/opt" IS_OPT "$ENV{CORIOLIS_TOP}") +IF(IS_USR OR IS_OPT) + MESSAGE("-- Using system-wide /etc.") + SET(SYS_CONF_DIR "/etc" CACHE STRING "System configuration directory (/etc)" FORCE) +ELSE(IS_USR OR IS_OPT) + MESSAGE("-- Using install tree /etc.") + SET(SYS_CONF_DIR "etc" CACHE STRING "System configuration directory (/etc)" FORCE) +ENDIF(IS_USR OR IS_OPT) + +FIND_PACKAGE(PythonLibs REQUIRED) +FIND_PACKAGE(PythonSitePackages REQUIRED) +FIND_PACKAGE(VLSISAPD REQUIRED) +FIND_PACKAGE(HURRICANE REQUIRED) +FIND_PACKAGE(CORIOLIS REQUIRED) + +SET_LIB_LINK_MODE() + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(etc) diff --git a/stratus1/LICENSE b/stratus1/LICENSE new file mode 100644 index 00000000..3912109b --- /dev/null +++ b/stratus1/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/stratus1/configure.in b/stratus1/configure.in new file mode 100644 index 00000000..d7d9ddd1 --- /dev/null +++ b/stratus1/configure.in @@ -0,0 +1,28 @@ + +AC_INIT(src/st_model.py) + +STRATUS_VERSION=3.1 +STRATUS_RELEASE=20090304 +VERSION=$STRATUS_VERSION.$STRATUS_RELEASE + +AM_INIT_AUTOMAKE(stratus,$VERSION) + +AC_PROG_MAKE_SET +AM_CORIOLIS + +AC_OUTPUT([ +coriolis-stratus.spec +Makefile +src/Makefile +src/lib/Makefile +src/dpgen/Makefile +doc/Makefile +doc/stratus/Makefile +doc/stratus/images/Makefile +doc/developper/Makefile +doc/dpgen/Makefile +doc/patterns/Makefile +etc/Makefile +modules/Makefile +modules/patterns/Makefile +]) diff --git a/stratus1/devdoc/.latex2html-init b/stratus1/devdoc/.latex2html-init new file mode 100644 index 00000000..41736623 --- /dev/null +++ b/stratus1/devdoc/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 4; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
\n$address_data[1]
"; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "

\n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
\n"; +} + + +sub bot_navigation_panel { + return "\n

\n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/devdoc/ASIM.css b/stratus1/devdoc/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/devdoc/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/devdoc/Makefile b/stratus1/devdoc/Makefile new file mode 100644 index 00000000..f87d676b --- /dev/null +++ b/stratus1/devdoc/Makefile @@ -0,0 +1,37 @@ +all : stratus.pdf stratus/index.html ASIM.css stratus/ASIM.css + +stratus.pdf: *.tex + @pdflatex stratus.tex + @pdflatex stratus.tex +# xdvi stratus.dvi + +viewpdf: stratus.pdf + @acroread stratus.pdf & + + +stratus/index.html: *.tex + @latex2html -no_math -html_version 4.0,math -style ./ASIM.css stratus.tex + +stratus/ASIM.css: ASIM.css + @cp -p ASIM.css stratus/ASIM.css + + +orthographe: stratus.tex + aspell -t --lang=fr -c $< + +clean: + @rm -rf *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus.pdf \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS + @rm -rf stratus/* + @rmdir stratus diff --git a/stratus1/devdoc/man_inst.tex b/stratus1/devdoc/man_inst.tex new file mode 100644 index 00000000..7b095c73 --- /dev/null +++ b/stratus1/devdoc/man_inst.tex @@ -0,0 +1,52 @@ +\subsection{Synopsys} + +\begin{verbatim} +Inst ( model + , name + , param = myParam + , map = myMap + ) +\end{verbatim} + +\subsection{Description} + +Instantiation of an instance. The type of the instance is given by the \verb-model- parameter. The connexions are made thanks to the \verb-map- parameters. + +\subsection{Parameters} + +\begin{itemize} + \item \verb-model- : Name of the mastercell of the instance to create (mandatory argument) + \item \verb-name- : Name of the instance (optional)\\ +When this argument is not defined, the instance has a name created by default. This argument is usefull when one wants to create a layout as well. Indeed, the placement of the instances is much easier when the conceptor has chosen himself the name f the instances. + \item \verb-param- : Dictionnary for parameters of the mastercell (optional : only for mastercells which require it) + \item \verb-map- : Dictionnary for connexions in order to make the netlist\\ +\end{itemize} + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the instance (the name given as parameter if there's one, a name created otherwise) + \item \verb-_model- : Name of the model given as argument + \item \verb-_real_model- : Name of the model created thanks to \verb-_model- and all the parameters + \item \verb-_map- : Dictionnary \verb-map- given at the instanciation + \item \verb-_param- : Dictionnary \verb-param- given at the instanciation + \item \verb-_st_cell- : The stratus cell which the instance is instanciated in + \item \verb-_st_masterCell- : The stratus master cell of the instance\\ +\end{itemize} +\indent For placement : +\begin{itemize} + \item \verb-_plac- : tells if the instance is placed or not (UNPLACED by default) + \item \verb-_x-, \verb-_y- : the coordinates of the instance (only for placed instances) + \item \verb-_sym- : the symetry of the instance (only for placed instances)\\ +\end{itemize} +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_instance- : The hurricane instance (None by default) + \item \verb-_hur_masterCell- : The Hurricane master cell of the instance (None by default) +\end{itemize} + +\subsection{Methods} + +\begin{itemize} + \item Delete : Deletion of the Hurricane instance +\end{itemize} diff --git a/stratus1/devdoc/man_model.tex b/stratus1/devdoc/man_model.tex new file mode 100644 index 00000000..212e2f00 --- /dev/null +++ b/stratus1/devdoc/man_model.tex @@ -0,0 +1,66 @@ +\subsection{Synopsys} + +\begin{verbatim} +class myClass ( Model ) : + ... + +exemple = myClass ( name, param ) +\end{verbatim} + +\subsection{Description} + +Every cell made is a class herited from class \verb-Model-.\\ +\indent Some methods have to be created, like \verb-Interface-, \verb-Netlist- ... Some methods are inherited from the class \verb-Model-. + +\subsection{Parameters} + +\begin{itemize} + \item \verb-name- : The name of the cell (which is the name of the files which will be created) + \item \verb-param- : A dictionnary which gives all the parameters useful in order to create the cell +\end{itemize} + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the cell + \item \verb-_st_insts- : List of all the instances of the cell + \item \verb-_st_ports- : List of all the external nets of the cell (except for alimentations and clock) + \item \verb-_st_sigs- : List of all the internal nets of the cell + \item \verb-_st_vdds-, \verb-_st_vsss- : Two tabs of the nets which are instancied as \verb-VddIn- and \verb-VssIn- + \item \verb-_st_cks- : List of all the nets which are instancied as \verb-CkIn- + \item \verb-_st_merge- : List of all the internal nets which have to be merged + \item \verb-_param- : The map given as argument at the creation of the cell + \item \verb-_underCells- : List of all the instances which are cells that have to be created + \item \verb-_and-, \verb-_or-, \verb-_xor-, \verb-_not-, \verb-_buff-, \verb-_mux-, \verb-_reg-, \verb-_shift-, \verb-_comp-, \verb-_add-, \verb-_mult-, \verb-_div- : tells which generator to use when using overloard + \item \verb-_NB_INST- : The number of instances of the cell (useful in order to automatically give a name to the instances) + \item \verb-_TAB_NETS_OUT- and \verb-_TAB_NETS_CAT- : Lists of all the nets automatically created + \item \verb-_insref- : The reference instance (for placement)\\ +\end{itemize} + +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_cell- : The hurricane cell (None by default) + \item \verb-_db- : The database + \item \verb-_lib0- : \verb-self._db.Get_CATA_LIB ( 0 )- + \item \verb-_nb_alims_verticales-, \verb-_nb_pins-, \verb-_nb_vdd_pins-, \verb-_nb_vss_pins-, \verb-standard_instances_list-, \verb-pad_north-, \verb-pad_south-, \verb-pad_east-, \verb-pad_west- : all place and route stuffs ... + +\end{itemize} + +\subsection{Methods} + +Methods of class \verb-Model- are listed below : +\begin{itemize} + \item \verb-HurricanePlug- : Creates the Hurricane cell thanks to the stratus cell.\\Before calling this method, only the stratus cell is created, after this method, both cells are created. This method has to be called before View and Save, and before Layout. + \item \verb-View- : Opens/Refreshes the editor in order to see the created layout + \item \verb-Quit- : Finishes a cell without saving + \item \verb-Save- : Saves the created cell\\If several cells have been created, they are all going to be saved in separated files\\ +\end{itemize} + +Some of those methods have to be defined in order to create a new cell : +\begin{itemize} + \item \verb-Interface- : Description of the external ports of the cell + \item \verb-Netlist- : Description of the netlist of the cell + \item \verb-Layout- : Description of the layout of the cell + \item \verb-Vbe- : Description of the behavior of the cell + \item \verb-Pattern- : Description of the patterns in order to test the cell +\end{itemize} diff --git a/stratus1/devdoc/man_net.tex b/stratus1/devdoc/man_net.tex new file mode 100644 index 00000000..9cdb22e4 --- /dev/null +++ b/stratus1/devdoc/man_net.tex @@ -0,0 +1,73 @@ +\subsection{Synopsys} + +\begin{verbatim} +netInput = LogicIn ( name, arity ) +\end{verbatim} + +\subsection{Description} + +Instanciation of net. Differents kind of nets are listed below : +\begin{itemize} + \item \verb-LogicIn- : Creation of an input port + \item \verb-LogicOut- : Creation of an output port + \item \verb-LogicInOut- : Creation of an inout port + \item \verb-LogicUnknown- : Creation of an input/output port which direction is not defined + \item \verb-TriState- : Creation of a tristate port + \item \verb-CkIn- : Creation of a clock port + \item \verb-VddIn- : Creation of the vdd alimentation + \item \verb-VssIn- : Creation of the vss alimentation + \item \verb-Signal- : Creation of an internal net +\end{itemize} + +\subsection{Parameters} + +\begin{itemize} + \item \verb-name- : Name of the net (mandatory argument) + \item \verb-arity- : Arity of the net (mandatory argument) + \item \verb-indice- : For buses only : the LSB bit (optional argument : set to 0 by default)\\ +\end{itemize} + +\indent Only \verb-CkIn, -\verb-VddIn- and \verb-VssIn- do not have the same parameters : there is only the \verb-name- parameter (they are 1 bit nets). + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the net + \item \verb-_arity- : Arity of the net (by default set to 0) + \item \verb-_ind- : LSB of the net + \item \verb-_ext- : Tells if the net is external or not (True/False) + \item \verb-_direct- : If the net is external, tells the direction ("IN", "OUT", "INOUT", "TRISTATE", "UNKNOWN") + \item \verb-_h_type- : If the net is an alimentation or a clock, tells the type ("POWER", "GROUND", "CLOCK") + \item \verb-_type- : The arithmetic type of the net ( "nr" ) + \item \verb-_st_cell- : The stratus cell which the net is instanciated in + \item \verb-_real_net- : If the net is a part of a net (Sig) it is the real net corresponding + \item \verb-_alias- : [] by default. When the net has an alias, it's a tab. Each element of the tab correspond to a bit of the net (from the LSB to the MSB), it'a a dictionnary : the only key is the net which this net is an alias from, the value is the bit of the net + \item \verb-_to_merge- : [] by default. The same as \_alias + \item \verb-_to_cat- : [] by default. The same as \_alias\\ +\end{itemize} + +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_net- : A tab with all the hurricane nets corresponding to the stratus net ; From the LSB to the MSB (for example, with a 1 bit net, one gets the hurricane net by doing : \verb-net._hur_net[0]- ). +\end{itemize} + +\subsection{Methods} + +\begin{itemize} + \item \verb-Buffer- : Instanciation of a Buffer + \item \verb-Shift- : Instanciation of a shifter + \item \verb-Mux- : Instanciation of a multiplexor + \item \verb-Reg- : Instanciation of a register + \item \verb-Eq/Ne- : Instanciation of comparison generator + \item \verb-Extend- : A net is extended + \item \verb-Alias- : A net is an alias of another net + \item \verb-Delete- : Deletion of the Hurricane nets\\ +\end{itemize} +\indent And the overloards : +\begin{itemize} + \item \_\_init\_\_ : Initialisation of nets + \item \_\_le\_\_ : initialisation of a net thanks to <= notation + \item \_\_getitem\_\_, \_\_geslice\_\_ : Creation of "Sig" nets : which are part of nets (use of \verb-[]- and \verb-[:]-) + \item \_\_and\_\_, \_\_or\_\_, \_\_xor\_\_, \_\_invert\_\_ : boolean operation with \&, |, \^ , ~ + \item \_\_add\_\_, \_\_mul\_\_, \_\_div\_\_ : arithmetic operators with +, * and / +\end{itemize} diff --git a/stratus1/devdoc/man_stratus.tex b/stratus1/devdoc/man_stratus.tex new file mode 100644 index 00000000..840123c7 --- /dev/null +++ b/stratus1/devdoc/man_stratus.tex @@ -0,0 +1,119 @@ +\subsubsection{Name} + +Stratus -- Procedural design language based upon \emph{Python} + +\subsubsection{Description} + +\emph{Stratus} is a set of \emph{Python} methods/functions dedicated to procedural generation purposes. From a user point of view, \emph{Stratus} is a circuit's description language that allows \emph{Python} programming flow control, variable use, and specialized functions in order to handle vlsi objects.\\ + +\indent Based upon the \emph{Hurricane} data structures, the \emph{Stratus} language gives the user the ability to describe netlist and layout views. + +\subsubsection{Creation of a cell} + +A cell is a hierachical structural description of a circuit in terms of ports (I/Os), signals (nets) and instances : + +\begin{itemize} +\item Method \verb-Interface- + \begin{itemize} + \item LogicIn + \item LogicOut + \item LogicInOut + \item TriState + \item VddIn + \item VssIn + \end{itemize} +\item Method \verb-Netlist- + \begin{itemize} + \item Signal + \item Inst + \item Facilities : \&, |, +, Mux, Shift, Eq/Ne ... + \end{itemize} +\item Method \verb-Layout- + \begin{itemize} + \item Place, PlaceTop, PlaceBottom, PlaceRight, PlaceLeft + \item SetRefIns + \item DefAb, ResizeAb + \item PlaceCentric + \item PlaceGlue, FillCell + \item PadNorth, PadSouth, PadEast, PadWest + \item AlimVerticalRail, AlimHorizontalRail + \item AlimConnectors + \item PowerRing + \item RouteCk + \end{itemize} + \item Method \verb-Pattern- + \item Method \verb-View- + \item Method \verb-Save- +\end{itemize} + +\subsubsection{Syntax highlighting} + +This chapter describes what to do to have the right syntax highlighting when using vi. + +\begin{itemize} + \item Commands to do when you want to change once the coloration of your file : +\end{itemize} +\begin{small} +\begin{verbatim} +:syntax off +:source /asim/coriolis/share/etc/stratus.vim +\end{verbatim} +\end{small} +\begin{itemize} + \item Modification of your .vimrc in order to have the syntax highlighting each time you open a file : +\end{itemize} +\begin{small} +\begin{verbatim} +syntax off +autocmd BufRead,BufNewfile *.py so /asim/coriolis/share/etc/stratus.vim +syntax on +\end{verbatim} +\end{small} + +\subsubsection{Environment variables} + +\begin{itemize} + \item CRL\_IN\_LO, default value : \verb-def- + \item CRL\_OUT\_LO, default value : \verb-def- + \item CRL\_IN\_PH, default value : \verb-def- + \item CRL\_OUT\_PH, default value : \verb-def- + \item CRL\_CATA\_LIB, default value : \verb-.- + \item CRL\_CATAL\_NAME, default value : \verb-CATAL- +\end{itemize} + +\subsubsection{Syntax} + +A \emph{Stratus} file must have a .py extension and must begin as follow : +\begin{verbatim} +#!/usr/bin/python + +from stratus import * +\end{verbatim} + +\indent In order to execute a \emph{Stratus} file (named \verb-file- for example), one has two choices : +\begin{verbatim} +python file.py +\end{verbatim} +\indent Or : +\begin{verbatim} +chmod u+x file.py +./file.py +\end{verbatim} + +\indent The names used in \emph{Stratus}, as arguments to \emph{Stratus} functions, should be alphanumerical, including the underscore. The arguments of \emph{Stratus} are case sensitive, so \textsc{VDD} is not equivalent to \textsc{vdd}.\\ + +\indent Vectorized connectors or signal can be used using the \textsc{[n:m]} construct.\\ + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Model}}{}{Model}{secmodel} +\hyperref[ref]{\emph{Param}}{}{Param}{secparam} +\hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/devdoc/see_also.tex b/stratus1/devdoc/see_also.tex new file mode 100644 index 00000000..32299cf7 --- /dev/null +++ b/stratus1/devdoc/see_also.tex @@ -0,0 +1,3 @@ +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} diff --git a/stratus1/devdoc/stratus.tex b/stratus1/devdoc/stratus.tex new file mode 100644 index 00000000..ddf0da52 --- /dev/null +++ b/stratus1/devdoc/stratus.tex @@ -0,0 +1,90 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyheadings} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage[french]{babel} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{color} +\usepackage{url} +\usepackage{html} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +%\setlength{\hoffset}{-18pt} +%\setlength{\oddsidemargin}{0pt} % Marge gauche sur pages impaires +%\setlength{\evensidemargin}{9pt} % Marge gauche sur pages paires +%\setlength{\marginparwidth}{54pt} % Largeur de note dans la marge +%\setlength{\textwidth}{481pt} % Largeur de la zone de texte (17cm) +%\setlength{\voffset}{-18pt} % Bon pour DOS +%\setlength{\marginparsep}{7pt} % Séparation de la marge +%\setlength{\topmargin}{0pt} % Pas de marge en haut +%\setlength{\headheight}{13pt} % Haut de page +%\setlength{\headsep}{10pt} % Entre le haut de page et le texte +%\setlength{\footskip}{27pt} % Bas de page + séparation +%\setlength{\textheight}{708pt} % Hauteur de la zone de texte (25cm) +\sloppy + +\newcommand{\image}[4] +% {\begin{figure}[htbp] + {\begin{figure}[h!] + \includegraphics[width=#2\textwidth]{#1} + \end{figure} + } +% \image{fig.eps}{scale} + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +\setlength{\footrulewidth}{0.6pt} +%---------------------------------- document --------------------------------- +\date {} +\title {Stratus Developper's Manual} +\author {Sophie Belloeil} + +\begin{document} + +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{Class Model} +\label{secmodel} +\input{man_model} + +\section{Nets} +\label{secnet} +\input{man_net} + +\section{Instances} +\label{secinst} +\input{man_inst} + +\end{document} diff --git a/stratus1/doc/.latex2html-init b/stratus1/doc/.latex2html-init new file mode 100644 index 00000000..df1398eb --- /dev/null +++ b/stratus1/doc/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 5; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
\n$address_data[1]
"; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "


\n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
\n"; +} + + +sub bot_navigation_panel { + return "\n

\n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/doc/ASIM.css b/stratus1/doc/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/Makefile.am b/stratus1/doc/Makefile.am new file mode 100644 index 00000000..58c4276a --- /dev/null +++ b/stratus1/doc/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = stratus dpgen developper patterns diff --git a/stratus1/doc/Makefile.manual b/stratus1/doc/Makefile.manual new file mode 100644 index 00000000..671f308c --- /dev/null +++ b/stratus1/doc/Makefile.manual @@ -0,0 +1,34 @@ +all : stratus.pdf stratus/index.html ASIM.css stratus/ASIM.css + +stratus.pdf: *.tex + @pdflatex stratus.tex + @pdflatex stratus.tex +# xdvi stratus.dvi + +viewpdf: stratus.pdf + @acroread stratus.pdf & + + +stratus/index.html: *.tex + @latex2html -no_math -html_version 4.0,math -style ./ASIM.css stratus.tex + +stratus/ASIM.css: ASIM.css + @cp -p ASIM.css stratus/ASIM.css + + +orthographe: stratus.tex + aspell -t --lang=fr -c $< + +clean: + @rm -rf *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS diff --git a/stratus1/doc/developper/.latex2html-init b/stratus1/doc/developper/.latex2html-init new file mode 100644 index 00000000..41736623 --- /dev/null +++ b/stratus1/doc/developper/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 4; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
\n$address_data[1]
"; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "


\n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
$t_title
" + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
" + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
\n" + . "
\n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
\n"; +} + + +sub bot_navigation_panel { + return "\n

\n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/doc/developper/ASIM.css b/stratus1/doc/developper/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/developper/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/developper/Makefile b/stratus1/doc/developper/Makefile new file mode 100644 index 00000000..f87d676b --- /dev/null +++ b/stratus1/doc/developper/Makefile @@ -0,0 +1,37 @@ +all : stratus.pdf stratus/index.html ASIM.css stratus/ASIM.css + +stratus.pdf: *.tex + @pdflatex stratus.tex + @pdflatex stratus.tex +# xdvi stratus.dvi + +viewpdf: stratus.pdf + @acroread stratus.pdf & + + +stratus/index.html: *.tex + @latex2html -no_math -html_version 4.0,math -style ./ASIM.css stratus.tex + +stratus/ASIM.css: ASIM.css + @cp -p ASIM.css stratus/ASIM.css + + +orthographe: stratus.tex + aspell -t --lang=fr -c $< + +clean: + @rm -rf *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus.pdf \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS + @rm -rf stratus/* + @rmdir stratus diff --git a/stratus1/doc/developper/Makefile.am b/stratus1/doc/developper/Makefile.am new file mode 100644 index 00000000..cd38979d --- /dev/null +++ b/stratus1/doc/developper/Makefile.am @@ -0,0 +1,70 @@ + +doc_en_latex_stratusdevdir = $(datadir)/doc/en/latex/stratusdev +doc_en_html_stratusdevdir = $(datadir)/doc/en/html/stratusdev +doc_en_pdf_stratusdevdir = $(datadir)/doc/en/pdf/stratusdev + + +doc_en_stratus_EXTRA = stratus.tex \ + man_inst.tex \ + man_net.tex \ + man_model.tex \ + man_stratus.tex \ + html.entry \ + ASIM.css \ + .latex2html-init + + +install-data-hook: + @if [ `which latex2html 2>/dev/null` ]; then \ + for file in `ls $(srcdir)/*.tex`; do \ + filename=`basename $$file`; \ + if [ ! -L $$filename -a ! -f $$filename ]; then \ + ln -sf $(srcdir)/$$filename . ; \ + fi ; \ + done ; \ + if [ ! -L ASIM.css -a ! -f ASIM.css ]; then \ + ln -sf $(srcdir)/*.css . ; \ + ln -sf $(srcdir)/.latex2html-init . ; \ + $(mkinstalldirs) images ; \ + ln -sf $(srcdir)/images/*.png ./images/ ; \ + fi ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_stratusdevdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_stratusdevdir)/images ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_html_stratusdevdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_pdf_stratusdevdir) ; \ + cp -r *.tex $(DESTDIR)$(doc_en_latex_stratusdevdir) ; \ + cp -r *.css $(DESTDIR)$(doc_en_latex_stratusdevdir) ; \ + cp -r .latex2html-init $(DESTDIR)$(doc_en_latex_stratusdevdir) ; \ + cp -r images/*.png $(DESTDIR)$(doc_en_latex_stratusdevdir)/images ; \ + rm -f *.aux *.lof *.log *.out *.toc *.dvi ; \ + latex2html -no_math -html_version 4.0,math -style ./ASIM.css stratus.tex ; \ + cp -pr stratus/* $(DESTDIR)$(doc_en_html_stratusdevdir) ; \ + cp -p ASIM.css $(DESTDIR)$(doc_en_html_stratusdevdir)/ASIM.css ; \ + pdflatex stratus.tex ; \ + pdflatex stratus.tex ; \ + cp stratus.pdf $(DESTDIR)$(doc_en_pdf_stratusdevdir) ; \ + cp $(srcdir)/html.entry $(DESTDIR)$(doc_en_html_stratusdevdir); \ + if [ -x $(datadir)/doc/en/html/generateIndex.sh ]; then \ + $(datadir)/doc/en/html/generateIndex.sh \ + --prefix=${prefix} --destdir=$(DESTDIR) ; \ + fi ; \ + else \ + echo "[WARNING] latex2html not found, skipping doc generation."; \ + fi + + +EXTRA_DIST = $(doc_en_stratus_EXTRA) + +CLEANFILES = *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS + diff --git a/stratus1/doc/developper/html.entry b/stratus1/doc/developper/html.entry new file mode 100644 index 00000000..e6bd336f --- /dev/null +++ b/stratus1/doc/developper/html.entry @@ -0,0 +1 @@ +

  • Stratus Dev
    Stratus Developpers Documentation

    diff --git a/stratus1/doc/developper/man_inst.tex b/stratus1/doc/developper/man_inst.tex new file mode 100644 index 00000000..5a04702e --- /dev/null +++ b/stratus1/doc/developper/man_inst.tex @@ -0,0 +1,50 @@ +\subsection{Synopsys} + +\begin{verbatim} +Inst ( model + , name + , map = myMap + ) +\end{verbatim} + +\subsection{Description} + +Instantiation of an instance. The type of the instance is given by the \verb-model- parameter. The connexions are made thanks to the \verb-map- parameters. + +\subsection{Parameters} + +\begin{itemize} + \item \verb-model- : Name of the mastercell of the instance to create (mandatory argument) + \item \verb-name- : Name of the instance (optional)\\ +When this argument is not defined, the instance has a name created by default. This argument is usefull when one wants to create a layout as well. Indeed, the placement of the instances is much easier when the conceptor has chosen himself the name f the instances. + \item \verb-map- : Dictionnary for connexions in order to make the netlist\\ +\end{itemize} + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the instance (the name given as parameter if there's one, a name created otherwise) + \item \verb-_model- : Name of the model given as argument + \item \verb-_real_model- : Name of the model created thanks to \verb-_model- and all the parameters + \item \verb-_map- : Dictionnary \verb-map- given at the instanciation + \item \verb-_param- : Dictionnary \verb-param- given at the instanciation + \item \verb-_st_cell- : The stratus cell which the instance is instanciated in + \item \verb-_st_masterCell- : The stratus master cell of the instance\\ +\end{itemize} +\indent For placement : +\begin{itemize} + \item \verb-_plac- : tells if the instance is placed or not (UNPLACED by default) + \item \verb-_x-, \verb-_y- : the coordinates of the instance (only for placed instances) + \item \verb-_sym- : the symetry of the instance (only for placed instances)\\ +\end{itemize} +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_instance- : The hurricane instance (None by default) + \item \verb-_hur_masterCell- : The Hurricane master cell of the instance (None by default) +\end{itemize} + +\subsection{Methods} + +\begin{itemize} + \item Delete : Deletion of the Hurricane instance +\end{itemize} diff --git a/stratus1/doc/developper/man_model.tex b/stratus1/doc/developper/man_model.tex new file mode 100644 index 00000000..212e2f00 --- /dev/null +++ b/stratus1/doc/developper/man_model.tex @@ -0,0 +1,66 @@ +\subsection{Synopsys} + +\begin{verbatim} +class myClass ( Model ) : + ... + +exemple = myClass ( name, param ) +\end{verbatim} + +\subsection{Description} + +Every cell made is a class herited from class \verb-Model-.\\ +\indent Some methods have to be created, like \verb-Interface-, \verb-Netlist- ... Some methods are inherited from the class \verb-Model-. + +\subsection{Parameters} + +\begin{itemize} + \item \verb-name- : The name of the cell (which is the name of the files which will be created) + \item \verb-param- : A dictionnary which gives all the parameters useful in order to create the cell +\end{itemize} + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the cell + \item \verb-_st_insts- : List of all the instances of the cell + \item \verb-_st_ports- : List of all the external nets of the cell (except for alimentations and clock) + \item \verb-_st_sigs- : List of all the internal nets of the cell + \item \verb-_st_vdds-, \verb-_st_vsss- : Two tabs of the nets which are instancied as \verb-VddIn- and \verb-VssIn- + \item \verb-_st_cks- : List of all the nets which are instancied as \verb-CkIn- + \item \verb-_st_merge- : List of all the internal nets which have to be merged + \item \verb-_param- : The map given as argument at the creation of the cell + \item \verb-_underCells- : List of all the instances which are cells that have to be created + \item \verb-_and-, \verb-_or-, \verb-_xor-, \verb-_not-, \verb-_buff-, \verb-_mux-, \verb-_reg-, \verb-_shift-, \verb-_comp-, \verb-_add-, \verb-_mult-, \verb-_div- : tells which generator to use when using overloard + \item \verb-_NB_INST- : The number of instances of the cell (useful in order to automatically give a name to the instances) + \item \verb-_TAB_NETS_OUT- and \verb-_TAB_NETS_CAT- : Lists of all the nets automatically created + \item \verb-_insref- : The reference instance (for placement)\\ +\end{itemize} + +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_cell- : The hurricane cell (None by default) + \item \verb-_db- : The database + \item \verb-_lib0- : \verb-self._db.Get_CATA_LIB ( 0 )- + \item \verb-_nb_alims_verticales-, \verb-_nb_pins-, \verb-_nb_vdd_pins-, \verb-_nb_vss_pins-, \verb-standard_instances_list-, \verb-pad_north-, \verb-pad_south-, \verb-pad_east-, \verb-pad_west- : all place and route stuffs ... + +\end{itemize} + +\subsection{Methods} + +Methods of class \verb-Model- are listed below : +\begin{itemize} + \item \verb-HurricanePlug- : Creates the Hurricane cell thanks to the stratus cell.\\Before calling this method, only the stratus cell is created, after this method, both cells are created. This method has to be called before View and Save, and before Layout. + \item \verb-View- : Opens/Refreshes the editor in order to see the created layout + \item \verb-Quit- : Finishes a cell without saving + \item \verb-Save- : Saves the created cell\\If several cells have been created, they are all going to be saved in separated files\\ +\end{itemize} + +Some of those methods have to be defined in order to create a new cell : +\begin{itemize} + \item \verb-Interface- : Description of the external ports of the cell + \item \verb-Netlist- : Description of the netlist of the cell + \item \verb-Layout- : Description of the layout of the cell + \item \verb-Vbe- : Description of the behavior of the cell + \item \verb-Pattern- : Description of the patterns in order to test the cell +\end{itemize} diff --git a/stratus1/doc/developper/man_net.tex b/stratus1/doc/developper/man_net.tex new file mode 100644 index 00000000..67717248 --- /dev/null +++ b/stratus1/doc/developper/man_net.tex @@ -0,0 +1,73 @@ +\subsection{Synopsys} + +\begin{verbatim} +netInput = SignalIn ( name, arity ) +\end{verbatim} + +\subsection{Description} + +Instanciation of net. Differents kind of nets are listed below : +\begin{itemize} + \item \verb-SignalIn- : Creation of an input port + \item \verb-SignalOut- : Creation of an output port + \item \verb-SignalInOut- : Creation of an inout port + \item \verb-SignalUnknown- : Creation of an input/output port which direction is not defined + \item \verb-TriState- : Creation of a tristate port + \item \verb-CkIn- : Creation of a clock port + \item \verb-VddIn- : Creation of the vdd alimentation + \item \verb-VssIn- : Creation of the vss alimentation + \item \verb-Signal- : Creation of an internal net +\end{itemize} + +\subsection{Parameters} + +\begin{itemize} + \item \verb-name- : Name of the net (mandatory argument) + \item \verb-arity- : Arity of the net (mandatory argument) + \item \verb-indice- : For buses only : the LSB bit (optional argument : set to 0 by default)\\ +\end{itemize} + +\indent Only \verb-CkIn, -\verb-VddIn- and \verb-VssIn- do not have the same parameters : there is only the \verb-name- parameter (they are 1 bit nets). + +\subsection{Attributes} + +\begin{itemize} + \item \verb-_name- : Name of the net + \item \verb-_arity- : Arity of the net (by default set to 0) + \item \verb-_ind- : LSB of the net + \item \verb-_ext- : Tells if the net is external or not (True/False) + \item \verb-_direct- : If the net is external, tells the direction ("IN", "OUT", "INOUT", "TRISTATE", "UNKNOWN") + \item \verb-_h_type- : If the net is an alimentation or a clock, tells the type ("POWER", "GROUND", "CLOCK") + \item \verb-_type- : The arithmetic type of the net ( "nr" ) + \item \verb-_st_cell- : The stratus cell which the net is instanciated in + \item \verb-_real_net- : If the net is a part of a net (Sig) it is the real net corresponding + \item \verb-_alias- : [] by default. When the net has an alias, it's a tab. Each element of the tab correspond to a bit of the net (from the LSB to the MSB), it'a a dictionnary : the only key is the net which this net is an alias from, the value is the bit of the net + \item \verb-_to_merge- : [] by default. The same as \_alias + \item \verb-_to_cat- : [] by default. The same as \_alias\\ +\end{itemize} + +\indent And, in connection with Hurricane : +\begin{itemize} + \item \verb-_hur_net- : A tab with all the hurricane nets corresponding to the stratus net ; From the LSB to the MSB (for example, with a 1 bit net, one gets the hurricane net by doing : \verb-net._hur_net[0]- ). +\end{itemize} + +\subsection{Methods} + +\begin{itemize} + \item \verb-Buffer- : Instanciation of a Buffer + \item \verb-Shift- : Instanciation of a shifter + \item \verb-Mux- : Instanciation of a multiplexor + \item \verb-Reg- : Instanciation of a register + \item \verb-Eq/Ne- : Instanciation of comparison generator + \item \verb-Extend- : A net is extended + \item \verb-Alias- : A net is an alias of another net + \item \verb-Delete- : Deletion of the Hurricane nets\\ +\end{itemize} +\indent And the overloards : +\begin{itemize} + \item \_\_init\_\_ : Initialisation of nets + \item \_\_le\_\_ : initialisation of a net thanks to <= notation + \item \_\_getitem\_\_, \_\_geslice\_\_ : Creation of "Sig" nets : which are part of nets (use of \verb-[]- and \verb-[:]-) + \item \_\_and\_\_, \_\_or\_\_, \_\_xor\_\_, \_\_invert\_\_ : boolean operation with \&, |, \^ , ~ + \item \_\_add\_\_, \_\_mul\_\_, \_\_div\_\_ : arithmetic operators with +, * and / +\end{itemize} diff --git a/stratus1/doc/developper/man_stratus.tex b/stratus1/doc/developper/man_stratus.tex new file mode 100644 index 00000000..840123c7 --- /dev/null +++ b/stratus1/doc/developper/man_stratus.tex @@ -0,0 +1,119 @@ +\subsubsection{Name} + +Stratus -- Procedural design language based upon \emph{Python} + +\subsubsection{Description} + +\emph{Stratus} is a set of \emph{Python} methods/functions dedicated to procedural generation purposes. From a user point of view, \emph{Stratus} is a circuit's description language that allows \emph{Python} programming flow control, variable use, and specialized functions in order to handle vlsi objects.\\ + +\indent Based upon the \emph{Hurricane} data structures, the \emph{Stratus} language gives the user the ability to describe netlist and layout views. + +\subsubsection{Creation of a cell} + +A cell is a hierachical structural description of a circuit in terms of ports (I/Os), signals (nets) and instances : + +\begin{itemize} +\item Method \verb-Interface- + \begin{itemize} + \item LogicIn + \item LogicOut + \item LogicInOut + \item TriState + \item VddIn + \item VssIn + \end{itemize} +\item Method \verb-Netlist- + \begin{itemize} + \item Signal + \item Inst + \item Facilities : \&, |, +, Mux, Shift, Eq/Ne ... + \end{itemize} +\item Method \verb-Layout- + \begin{itemize} + \item Place, PlaceTop, PlaceBottom, PlaceRight, PlaceLeft + \item SetRefIns + \item DefAb, ResizeAb + \item PlaceCentric + \item PlaceGlue, FillCell + \item PadNorth, PadSouth, PadEast, PadWest + \item AlimVerticalRail, AlimHorizontalRail + \item AlimConnectors + \item PowerRing + \item RouteCk + \end{itemize} + \item Method \verb-Pattern- + \item Method \verb-View- + \item Method \verb-Save- +\end{itemize} + +\subsubsection{Syntax highlighting} + +This chapter describes what to do to have the right syntax highlighting when using vi. + +\begin{itemize} + \item Commands to do when you want to change once the coloration of your file : +\end{itemize} +\begin{small} +\begin{verbatim} +:syntax off +:source /asim/coriolis/share/etc/stratus.vim +\end{verbatim} +\end{small} +\begin{itemize} + \item Modification of your .vimrc in order to have the syntax highlighting each time you open a file : +\end{itemize} +\begin{small} +\begin{verbatim} +syntax off +autocmd BufRead,BufNewfile *.py so /asim/coriolis/share/etc/stratus.vim +syntax on +\end{verbatim} +\end{small} + +\subsubsection{Environment variables} + +\begin{itemize} + \item CRL\_IN\_LO, default value : \verb-def- + \item CRL\_OUT\_LO, default value : \verb-def- + \item CRL\_IN\_PH, default value : \verb-def- + \item CRL\_OUT\_PH, default value : \verb-def- + \item CRL\_CATA\_LIB, default value : \verb-.- + \item CRL\_CATAL\_NAME, default value : \verb-CATAL- +\end{itemize} + +\subsubsection{Syntax} + +A \emph{Stratus} file must have a .py extension and must begin as follow : +\begin{verbatim} +#!/usr/bin/python + +from stratus import * +\end{verbatim} + +\indent In order to execute a \emph{Stratus} file (named \verb-file- for example), one has two choices : +\begin{verbatim} +python file.py +\end{verbatim} +\indent Or : +\begin{verbatim} +chmod u+x file.py +./file.py +\end{verbatim} + +\indent The names used in \emph{Stratus}, as arguments to \emph{Stratus} functions, should be alphanumerical, including the underscore. The arguments of \emph{Stratus} are case sensitive, so \textsc{VDD} is not equivalent to \textsc{vdd}.\\ + +\indent Vectorized connectors or signal can be used using the \textsc{[n:m]} construct.\\ + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Model}}{}{Model}{secmodel} +\hyperref[ref]{\emph{Param}}{}{Param}{secparam} +\hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/doc/developper/see_also.tex b/stratus1/doc/developper/see_also.tex new file mode 100644 index 00000000..32299cf7 --- /dev/null +++ b/stratus1/doc/developper/see_also.tex @@ -0,0 +1,3 @@ +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} diff --git a/stratus1/doc/developper/stratus.out b/stratus1/doc/developper/stratus.out new file mode 100644 index 00000000..fa61b7db --- /dev/null +++ b/stratus1/doc/developper/stratus.out @@ -0,0 +1,18 @@ +\BOOKMARK [1][-]{section.1}{Class Model}{} +\BOOKMARK [2][-]{subsection.1.1}{Synopsys}{section.1} +\BOOKMARK [2][-]{subsection.1.2}{Description}{section.1} +\BOOKMARK [2][-]{subsection.1.3}{Parameters}{section.1} +\BOOKMARK [2][-]{subsection.1.4}{Attributes}{section.1} +\BOOKMARK [2][-]{subsection.1.5}{Methods}{section.1} +\BOOKMARK [1][-]{section.2}{Nets}{} +\BOOKMARK [2][-]{subsection.2.1}{Synopsys}{section.2} +\BOOKMARK [2][-]{subsection.2.2}{Description}{section.2} +\BOOKMARK [2][-]{subsection.2.3}{Parameters}{section.2} +\BOOKMARK [2][-]{subsection.2.4}{Attributes}{section.2} +\BOOKMARK [2][-]{subsection.2.5}{Methods}{section.2} +\BOOKMARK [1][-]{section.3}{Instances}{} +\BOOKMARK [2][-]{subsection.3.1}{Synopsys}{section.3} +\BOOKMARK [2][-]{subsection.3.2}{Description}{section.3} +\BOOKMARK [2][-]{subsection.3.3}{Parameters}{section.3} +\BOOKMARK [2][-]{subsection.3.4}{Attributes}{section.3} +\BOOKMARK [2][-]{subsection.3.5}{Methods}{section.3} diff --git a/stratus1/doc/developper/stratus.tex b/stratus1/doc/developper/stratus.tex new file mode 100644 index 00000000..2b331604 --- /dev/null +++ b/stratus1/doc/developper/stratus.tex @@ -0,0 +1,90 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyhdr} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage[french]{babel} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{color} +\usepackage{url} +\usepackage{html} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +%\setlength{\hoffset}{-18pt} +%\setlength{\oddsidemargin}{0pt} % Marge gauche sur pages impaires +%\setlength{\evensidemargin}{9pt} % Marge gauche sur pages paires +%\setlength{\marginparwidth}{54pt} % Largeur de note dans la marge +%\setlength{\textwidth}{481pt} % Largeur de la zone de texte (17cm) +%\setlength{\voffset}{-18pt} % Bon pour DOS +%\setlength{\marginparsep}{7pt} % Séparation de la marge +%\setlength{\topmargin}{0pt} % Pas de marge en haut +%\setlength{\headheight}{13pt} % Haut de page +%\setlength{\headsep}{10pt} % Entre le haut de page et le texte +%\setlength{\footskip}{27pt} % Bas de page + séparation +%\setlength{\textheight}{708pt} % Hauteur de la zone de texte (25cm) +\sloppy + +\newcommand{\image}[4] +% {\begin{figure}[htbp] + {\begin{figure}[h!] + \includegraphics[width=#2\textwidth]{#1} + \end{figure} + } +% \image{fig.eps}{scale} + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +%---------------------------------- document --------------------------------- +\date {} +\title {Stratus Developper's Manual} +\author {Sophie Belloeil} + +\begin{document} + +\setlength{\footrulewidth}{0.6pt} +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{Class Model} +\label{secmodel} +\input{man_model} + +\section{Nets} +\label{secnet} +\input{man_net} + +\section{Instances} +\label{secinst} +\input{man_inst} + +\end{document} diff --git a/stratus1/doc/developper/stratus/ASIM.css b/stratus1/doc/developper/stratus/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/developper/stratus/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/developper/stratus/WARNINGS b/stratus1/doc/developper/stratus/WARNINGS new file mode 100644 index 00000000..90f53c20 --- /dev/null +++ b/stratus1/doc/developper/stratus/WARNINGS @@ -0,0 +1,9 @@ +No implementation found for style `fontenc' +No implementation found for style `palatino' +No implementation found for style `fancyheadings' +No implementation found for style `subfigure' +No implementation found for style `graphicx' +No implementation found for style `url' +couldn't convert character ,circ into available encodings + + ...set $ACCENT_IMAGES to get an image diff --git a/stratus1/doc/developper/stratus/index.html b/stratus1/doc/developper/stratus/index.html new file mode 100644 index 00000000..cf04f88b --- /dev/null +++ b/stratus1/doc/developper/stratus/index.html @@ -0,0 +1,130 @@ + + + + + +Stratus Developper's Manual + + + + + + + + + + + + + + + + + + + +

    +

    Stratus Developper's Manual

    +
    + +

    Sophie Belloeil

    +
    + +

    +
    + + + +

    + +
    +
    +

    + +

    + +
    +Sophie BELLOEIL
    20051116.1 +
    + + diff --git a/stratus1/doc/developper/stratus/internals.pl b/stratus1/doc/developper/stratus/internals.pl new file mode 100644 index 00000000..d67a73ff --- /dev/null +++ b/stratus1/doc/developper/stratus/internals.pl @@ -0,0 +1,18 @@ +# LaTeX2HTML 2002-2-1 (1.70) +# Associate internals original text with physical files. + + +$key = q/secmodel/; +$ref_files{$key} = "$dir".q|node1.html|; +$noresave{$key} = "$nosave"; + +$key = q/secnet/; +$ref_files{$key} = "$dir".q|node2.html|; +$noresave{$key} = "$nosave"; + +$key = q/secinst/; +$ref_files{$key} = "$dir".q|node3.html|; +$noresave{$key} = "$nosave"; + +1; + diff --git a/stratus1/doc/developper/stratus/labels.pl b/stratus1/doc/developper/stratus/labels.pl new file mode 100644 index 00000000..1948454f --- /dev/null +++ b/stratus1/doc/developper/stratus/labels.pl @@ -0,0 +1,25 @@ +# LaTeX2HTML 2002-2-1 (1.70) +# Associate labels original text with physical files. + + +$key = q/secmodel/; +$external_labels{$key} = "$URL/" . q|node1.html|; +$noresave{$key} = "$nosave"; + +$key = q/secnet/; +$external_labels{$key} = "$URL/" . q|node2.html|; +$noresave{$key} = "$nosave"; + +$key = q/secinst/; +$external_labels{$key} = "$URL/" . q|node3.html|; +$noresave{$key} = "$nosave"; + +1; + + +# LaTeX2HTML 2002-2-1 (1.70) +# labels from external_latex_labels array. + + +1; + diff --git a/stratus1/doc/developper/stratus/node1.html b/stratus1/doc/developper/stratus/node1.html new file mode 100644 index 00000000..3581a5d6 --- /dev/null +++ b/stratus1/doc/developper/stratus/node1.html @@ -0,0 +1,227 @@ + + + + + +Class Model + + + + + + + + + + + + + + + + + + + + + + +Sous-sections + + + +
    + +

    + +
    +Class Model +

    + +

    +Synopsys +

    + +

    +

    +class myClass ( Model ) :
    +    ...
    +    
    +exemple = myClass ( name, param )
    +
    + +

    + +

    +Description +

    + +

    +Every cell made is a class herited from class Model. +
    +Some methods have to be created, like Interface, Netlist ... Some methods are inherited from the class Model. + +

    + +

    +Parameters +

    + +

    + +

      +
    • name : The name of the cell (which is the name of the files which will be created) +
    • +
    • param : A dictionnary which gives all the parameters useful in order to create the cell +
    • +
    + +

    + +

    +Attributes +

    + +

    + +

      +
    • _name : Name of the cell +
    • +
    • _st_insts : List of all the instances of the cell +
    • +
    • _st_ports : List of all the external nets of the cell (except for alimentations and clock) +
    • +
    • _st_sigs : List of all the internal nets of the cell +
    • +
    • _st_vdds, _st_vsss : Two tabs of the nets which are instancied as VddIn and VssIn +
    • +
    • _st_cks : List of all the nets which are instancied as CkIn +
    • +
    • _st_merge : List of all the internal nets which have to be merged +
    • +
    • _param : The map given as argument at the creation of the cell +
    • +
    • _underCells : List of all the instances which are cells that have to be created +
    • +
    • _and, _or, _xor, _not, _buff, _mux, _reg, _shift, _comp, _add, _mult, _div : tells which generator to use when using overloard +
    • +
    • _NB_INST : The number of instances of the cell (useful in order to automatically give a name to the instances) +
    • +
    • _TAB_NETS_OUT and _TAB_NETS_CAT : Lists of all the nets automatically created +
    • +
    • _insref : The reference instance (for placement) +
    • +
    + +

    +And, in connection with Hurricane : + +

      +
    • _hur_cell : The hurricane cell (None by default) +
    • +
    • _db : The database +
    • +
    • _lib0 : self._db.Get_CATA_LIB ( 0 ) +
    • +
    • _nb_alims_verticales, _nb_pins, _nb_vdd_pins, _nb_vss_pins, standard_instances_list, pad_north, pad_south, pad_east, pad_west : all place and route stuffs ... + +

      +

    • +
    + +

    + +

    +Methods +

    + +

    +Methods of class Model are listed below : + +

      +
    • HurricanePlug : Creates the Hurricane cell thanks to the stratus cell. +
      +Before calling this method, only the stratus cell is created, after this method, both cells are created. This method has to be called before View and Save, and before Layout. +
    • +
    • View : Opens/Refreshes the editor in order to see the created layout +
    • +
    • Quit : Finishes a cell without saving +
    • +
    • Save : Saves the created cell +
      +If several cells have been created, they are all going to be saved in separated files +
    • +
    + +

    +Some of those methods have to be defined in order to create a new cell : + +

      +
    • Interface : Description of the external ports of the cell +
    • +
    • Netlist : Description of the netlist of the cell +
    • +
    • Layout : Description of the layout of the cell +
    • +
    • Vbe : Description of the behavior of the cell +
    • +
    • Pattern : Description of the patterns in order to test the cell +
    • +
    + +

    + +

    + +
    +Sophie BELLOEIL
    20051116.1 +
    + + diff --git a/stratus1/doc/developper/stratus/node2.html b/stratus1/doc/developper/stratus/node2.html new file mode 100644 index 00000000..04124489 --- /dev/null +++ b/stratus1/doc/developper/stratus/node2.html @@ -0,0 +1,239 @@ + + + + + +Nets + + + + + + + + + + + + + + + + + + + + + + +Sous-sections + + + +
    + +

    + +
    +Nets +

    + +

    +Synopsys +

    + +

    +

    +netInput = LogicIn ( name, arity )
    +
    + +

    + +

    +Description +

    + +

    +Instanciation of net. Differents kind of nets are listed below : + +

      +
    • LogicIn : Creation of an input port +
    • +
    • LogicOut : Creation of an output port +
    • +
    • LogicInOut : Creation of an inout port +
    • +
    • LogicUnknown : Creation of an input/output port which direction is not defined +
    • +
    • TriState : Creation of a tristate port +
    • +
    • CkIn : Creation of a clock port +
    • +
    • VddIn : Creation of the vdd alimentation +
    • +
    • VssIn : Creation of the vss alimentation +
    • +
    • Signal : Creation of an internal net +
    • +
    + +

    + +

    +Parameters +

    + +

    + +

      +
    • name : Name of the net (mandatory argument) +
    • +
    • arity : Arity of the net (mandatory argument) +
    • +
    • indice : For buses only : the LSB bit (optional argument : set to 0 by default) +
    • +
    + +

    +Only CkIn, VddIn and VssIn do not have the same parameters : there is only the name parameter (they are 1 bit nets). + +

    + +

    +Attributes +

    + +

    + +

      +
    • _name : Name of the net +
    • +
    • _arity : Arity of the net (by default set to 0) +
    • +
    • _ind : LSB of the net +
    • +
    • _ext : Tells if the net is external or not (True/False) +
    • +
    • _direct : If the net is external, tells the direction ("IN", "OUT", "INOUT", "TRISTATE", "UNKNOWN") +
    • +
    • _h_type : If the net is an alimentation or a clock, tells the type ("POWER", "GROUND", "CLOCK") +
    • +
    • _type : The arithmetic type of the net ( "nr" ) +
    • +
    • _st_cell : The stratus cell which the net is instanciated in +
    • +
    • _real_net : If the net is a part of a net (Sig) it is the real net corresponding +
    • +
    • _alias : [] by default. When the net has an alias, it's a tab. Each element of the tab correspond to a bit of the net (from the LSB to the MSB), it'a a dictionnary : the only key is the net which this net is an alias from, the value is the bit of the net +
    • +
    • _to_merge : [] by default. The same as _alias +
    • +
    • _to_cat : [] by default. The same as _alias +
    • +
    + +

    +And, in connection with Hurricane : + +

      +
    • _hur_net : A tab with all the hurricane nets corresponding to the stratus net ; From the LSB to the MSB (for example, with a 1 bit net, one gets the hurricane net by doing : net._hur_net[0] ). +
    • +
    + +

    + +

    +Methods +

    + +

    + +

      +
    • Buffer : Instanciation of a Buffer +
    • +
    • Shift : Instanciation of a shifter +
    • +
    • Mux : Instanciation of a multiplexor +
    • +
    • Reg : Instanciation of a register +
    • +
    • Eq/Ne : Instanciation of comparison generator +
    • +
    • Extend : A net is extended +
    • +
    • Alias : A net is an alias of another net +
    • +
    • Delete : Deletion of the Hurricane nets +
    • +
    +And the overloards : + +
      +
    • __init__ : Initialisation of nets +
    • +
    • __le__ : initialisation of a net thanks to <= notation +
    • +
    • __getitem__, __geslice__ : Creation of "Sig" nets : which are part of nets (use of [] and [:]) +
    • +
    • __and__, __or__, __xor__, __invert__ : boolean operation with &, |, ,  +
    • +
    • __add__, __mul__, __div__ : arithmetic operators with +, * and / +
    • +
    + +

    + +

    + +
    +Sophie BELLOEIL
    20051116.1 +
    + + diff --git a/stratus1/doc/developper/stratus/node3.html b/stratus1/doc/developper/stratus/node3.html new file mode 100644 index 00000000..2acdd748 --- /dev/null +++ b/stratus1/doc/developper/stratus/node3.html @@ -0,0 +1,193 @@ + + + + + +Instances + + + + + + + + + + + + + + + + + + + + +Sous-sections + + + +
    + +

    + +
    +Instances +

    + +

    +Synopsys +

    + +

    +

    +Inst ( model
    +     , name
    +     , param = myParam
    +     , map = myMap
    +     )
    +
    + +

    + +

    +Description +

    + +

    +Instantiation of an instance. The type of the instance is given by the model parameter. The connexions are made thanks to the map parameters. + +

    + +

    +Parameters +

    + +

    + +

      +
    • model : Name of the mastercell of the instance to create (mandatory argument) +
    • +
    • name : Name of the instance (optional) +
      +When this argument is not defined, the instance has a name created by default. This argument is usefull when one wants to create a layout as well. Indeed, the placement of the instances is much easier when the conceptor has chosen himself the name f the instances. +
    • +
    • param : Dictionnary for parameters of the mastercell (optional : only for mastercells which require it) +
    • +
    • map : Dictionnary for connexions in order to make the netlist +
    • +
    + +

    + +

    +Attributes +

    + +

    + +

      +
    • _name : Name of the instance (the name given as parameter if there's one, a name created otherwise) +
    • +
    • _model : Name of the model given as argument +
    • +
    • _real_model : Name of the model created thanks to _model and all the parameters +
    • +
    • _map : Dictionnary map given at the instanciation +
    • +
    • _param : Dictionnary param given at the instanciation +
    • +
    • _st_cell : The stratus cell which the instance is instanciated in +
    • +
    • _st_masterCell : The stratus master cell of the instance +
    • +
    +For placement : + +
      +
    • _plac : tells if the instance is placed or not (UNPLACED by default) +
    • +
    • _x, _y : the coordinates of the instance (only for placed instances) +
    • +
    • _sym : the symetry of the instance (only for placed instances) +
    • +
    +And, in connection with Hurricane : + +
      +
    • _hur_instance : The hurricane instance (None by default) +
    • +
    • _hur_masterCell : The Hurricane master cell of the instance (None by default) +
    • +
    + +

    + +

    +Methods +

    + +

    + +

      +
    • Delete : Deletion of the Hurricane instance +
    • +
    + +

    + +

    + +
    +Sophie BELLOEIL
    20051116.1 +
    + + diff --git a/stratus1/doc/developper/stratus/stratus.css b/stratus1/doc/developper/stratus/stratus.css new file mode 100644 index 00000000..83b8aa7d --- /dev/null +++ b/stratus1/doc/developper/stratus/stratus.css @@ -0,0 +1,33 @@ +/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ +.MATH { font-family: "Century Schoolbook", serif; } +.MATH I { font-family: "Century Schoolbook", serif; font-style: italic } +.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold } + +/* implement both fixed-size and relative sizes */ +SMALL.XTINY { font-size : xx-small } +SMALL.TINY { font-size : x-small } +SMALL.SCRIPTSIZE { font-size : smaller } +SMALL.FOOTNOTESIZE { font-size : small } +SMALL.SMALL { } +BIG.LARGE { } +BIG.XLARGE { font-size : large } +BIG.XXLARGE { font-size : x-large } +BIG.HUGE { font-size : larger } +BIG.XHUGE { font-size : xx-large } + +/* heading styles */ +H1 { } +H2 { } +H3 { } +H4 { } +H5 { } + +/* mathematics styles */ +DIV.displaymath { } /* math displays */ +TD.eqno { } /* equation-number cells */ + + +/* document-specific styles come next */ +DIV.navigation { } +PRE.preform { } +SPAN.arabic { } diff --git a/stratus1/doc/developper/stratus/stratus.html b/stratus1/doc/developper/stratus/stratus.html new file mode 100644 index 00000000..cf04f88b --- /dev/null +++ b/stratus1/doc/developper/stratus/stratus.html @@ -0,0 +1,130 @@ + + + + + +Stratus Developper's Manual + + + + + + + + + + + + + + + + + + + +

    +

    Stratus Developper's Manual

    +
    + +

    Sophie Belloeil

    +
    + +

    +
    + + + +

    + +
    +
    +

    + +

    + +
    +Sophie BELLOEIL
    20051116.1 +
    + + diff --git a/stratus1/doc/dpgen/.latex2html-init b/stratus1/doc/dpgen/.latex2html-init new file mode 100644 index 00000000..df1398eb --- /dev/null +++ b/stratus1/doc/dpgen/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 5; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
    \n$address_data[1]
    "; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "

    \n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
    ' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
    \n"; +} + + +sub bot_navigation_panel { + return "\n

    \n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
    20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/doc/dpgen/ASIM.css b/stratus1/doc/dpgen/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/dpgen/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/dpgen/Makefile.am b/stratus1/doc/dpgen/Makefile.am new file mode 100644 index 00000000..2930b867 --- /dev/null +++ b/stratus1/doc/dpgen/Makefile.am @@ -0,0 +1,98 @@ + +doc_en_latex_stratusdir = $(datadir)/doc/en/latex/dpgen +doc_en_html_stratusdir = $(datadir)/doc/en/html/dpgen +doc_en_pdf_stratusdir = $(datadir)/doc/en/pdf/dpgen + + +doc_en_stratus_EXTRA = dpgen.tex \ + man_dpgenadsb2f.tex \ + man_dpgenand2.tex \ + man_dpgenand3.tex \ + man_dpgenand4.tex \ + man_dpgenbuff.tex \ + man_dpgenbuse.tex \ + man_dpgenconst.tex \ + man_dpgendff.tex \ + man_dpgendfft.tex \ + man_dpgenfifo.tex \ + man_dpgeninv.tex \ + man_dpgenmux2.tex \ + man_dpgennand2mask.tex \ + man_dpgennand2.tex \ + man_dpgennand3.tex \ + man_dpgennand4.tex \ + man_dpgennbuse.tex \ + man_dpgennmux2.tex \ + man_dpgennor2mask.tex \ + man_dpgennor2.tex \ + man_dpgennor3.tex \ + man_dpgennor4.tex \ + man_dpgennul.tex \ + man_dpgenor2.tex \ + man_dpgenor3.tex \ + man_dpgenor4.tex \ + man_dpgenram.tex \ + man_dpgenrf1d.tex \ + man_dpgenrf1.tex \ + man_dpgenrom2.tex \ + man_dpgenrom4.tex \ + man_dpgensff.tex \ + man_dpgensfft.tex \ + man_dpgenshift.tex \ + man_dpgenshrot.tex \ + man_dpgenxnor2mask.tex \ + man_dpgenxnor2.tex \ + man_dpgenxor2.tex \ + html.entry \ + ASIM.css \ + .latex2html-init + +install-data-hook: + @if [ `which latex2html 2>/dev/null` ]; then \ + for file in `ls $(srcdir)/*.tex`; do \ + filename=`basename $$file`; \ + if [ ! -L $$filename -a ! -f $$filename ]; then \ + ln -sf $(srcdir)/$$filename . ; \ + fi ; \ + done ; \ + if [ ! -L ASIM.css -a ! -f ASIM.css ]; then \ + ln -sf $(srcdir)/*.css . ; \ + ln -sf $(srcdir)/.latex2html-init . ; \ + fi ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_html_stratusdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_pdf_stratusdir) ; \ + cp -r *.tex $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + cp -r *.css $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + cp -r .latex2html-init $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + rm -f *.aux *.lof *.log *.out *.toc *.dvi ; \ + latex2html -no_math -html_version 4.0,math -style ./ASIM.css dpgen.tex ; \ + cp -pr dpgen/* $(DESTDIR)$(doc_en_html_stratusdir) ; \ + cp -p ASIM.css $(DESTDIR)$(doc_en_html_stratusdir)/ASIM.css ; \ + pdflatex dpgen.tex ; \ + pdflatex dpgen.tex ; \ + cp dpgen.pdf $(DESTDIR)$(doc_en_pdf_stratusdir) ; \ + cp $(srcdir)/html.entry $(DESTDIR)$(doc_en_html_stratusdir); \ + if [ -x $(datadir)/doc/en/html/generateIndex.sh ]; then \ + $(datadir)/doc/en/html/generateIndex.sh \ + --prefix=${prefix} --destdir=$(DESTDIR) ; \ + fi ; \ + else \ + echo "[WARNING] latex2html not found, skipping doc generation."; \ + fi + + +EXTRA_DIST = $(doc_en_stratus_EXTRA) + +CLEANFILES = *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS diff --git a/stratus1/doc/dpgen/dpgen.tex b/stratus1/doc/dpgen/dpgen.tex new file mode 100644 index 00000000..4271928a --- /dev/null +++ b/stratus1/doc/dpgen/dpgen.tex @@ -0,0 +1,142 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyhdr} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{color} +\usepackage{url} +\usepackage{html} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +\sloppy + +\newcommand{\image}[4] +% {\begin{figure}[htbp] + {\begin{figure}[h!] + \includegraphics[width=#2\textwidth]{#1} + \end{figure} + } +% \image{fig.eps}{scale} + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +%---------------------------------- document --------------------------------- +\date {} +\title {Dpgen generators User's Manual} +\author {Sophie Belloeil} + +\begin{document} + +\setlength{\footrulewidth}{0.6pt} +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{DpgenInv} +\input{man_dpgeninv} +\section{DpgenBuff} +\input{man_dpgenbuff} +\section{DpgenNand2} +\input{man_dpgennand2} +\section{DpgenNand3} +\input{man_dpgennand3} +\section{Dpgennand4} +\input{man_dpgennand4} +\section{DpgenAnd2} +\input{man_dpgenand2} +\section{DpgenAnd3} +\input{man_dpgenand3} +\section{DpgenAnd4} +\input{man_dpgenand4} +\section{DpgenNor2} +\input{man_dpgennor2} +\section{DpgenNor3} +\input{man_dpgennor3} +\section{DpgenNor4} +\input{man_dpgennor4} +\section{DpgenOr2} +\input{man_dpgenor2} +\section{DpgenOr3} +\input{man_dpgenor3} +\section{DpgenOr4} +\input{man_dpgenor4} +\section{DpgenXor2} +\input{man_dpgenxor2} +\section{DpgenXnor2} +\input{man_dpgenxnor2} +\section{DpgenNmux2} +\input{man_dpgennmux2} +\section{DpgenMux2} +\input{man_dpgenmux2} +\section{DpgenNbuse} +\input{man_dpgennbuse} +\section{DpgenBuse} +\input{man_dpgenbuse} +\section{DpgenNand2mask} +\input{man_dpgennand2mask} +\section{DpgenNor2mask} +\input{man_dpgennor2mask} +\section{DpgenXnor2mask} +\input{man_dpgenxnor2mask} +\section{DpgenAdsb2f} +\input{man_dpgenadsb2f} +\section{DpgenShift} +\input{man_dpgenshift} +\section{DpgenShrot} +\input{man_dpgenshrot} +\section{DpgenNul} +\input{man_dpgennul} +\section{DpgenConst} +\input{man_dpgenconst} +\section{DpgenRom2} +\input{man_dpgenrom2} +\section{DpgenRom4} +\input{man_dpgenrom4} +\section{DpgenRam} +\input{man_dpgenram} +\section{DpgenRf1} +\input{man_dpgenrf1} +\section{DpgenRf1d} +\input{man_dpgenrf1d} +\section{DpgenFifo} +\input{man_dpgenfifo} +\section{DpgenDff} +\input{man_dpgendff} +\section{DpgenDfft} +\input{man_dpgendfft} +\section{DpgenSff} +\input{man_dpgensff} +\section{DpgenSfft} +\input{man_dpgensfft} + +\end{document} diff --git a/stratus1/doc/dpgen/html.entry b/stratus1/doc/dpgen/html.entry new file mode 100644 index 00000000..3fd44ded --- /dev/null +++ b/stratus1/doc/dpgen/html.entry @@ -0,0 +1 @@ +

  • DpGen
    Data-Path Macro-Blocs Generators

    diff --git a/stratus1/doc/dpgen/man_dpgenadsb2f.tex b/stratus1/doc/dpgen/man_dpgenadsb2f.tex new file mode 100644 index 00000000..01edd455 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenadsb2f.tex @@ -0,0 +1,76 @@ +\begin{itemize} + \item \textbf{Name} : DpgenAdsb2f -- Adder/Substractor Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenAdsb2f', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits adder/substractor named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : First operand (input, \verb-n- bits) + \item \textbf{i1} : Second operand (input, \verb-n- bits) + \item \textbf{q} : Output operand (ouput, \verb-n- bits) + \item \textbf{add\_sub} : Select addition or substraction (input, 1 bit) + \item \textbf{c31} : Sarry out. In unsigned mode, this is the overflow (output, 1 bit) + \item \textbf{c30} : Used to compute overflow in signed mode : \verb-overflow = c31 xor c30- (output, 1 bit) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-add_sub- signal is set to \verb-zero-, an addition is performed, otherwise it's a substraction. + \item Operation can be either signed or unsigned. In unsigned mode \verb-c31- is the overflow ; in signed mode you have to compute overflow by \emph{XORing} \verb-c31- and \verb-c30- + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_ADSB2F ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.out = SignalOut ( "o", 8 ) + self.as = SignalIn ( "as", 1 ) + self.c0 = SignalOut ( "c0", 1 ) + self.c1 = SignalOut ( "c1", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenAdsb2f', 'adder_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'adder_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'add_sub' : self.as + , 'q' : self.out + , 'c30' : self.c0 + , 'c31' : self.c1 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenand2.tex b/stratus1/doc/dpgen/man_dpgenand2.tex new file mode 100644 index 00000000..061a3ddc --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenand2.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenAnd2 -- And2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenAnd2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs AND with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 and i1 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_and2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.out = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenAnd2', 'and2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'and2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'q' : self.out + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenand3.tex b/stratus1/doc/dpgen/man_dpgenand3.tex new file mode 100644 index 00000000..cce8abf4 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenand3.tex @@ -0,0 +1,72 @@ +\begin{itemize} + \item \textbf{Name} : DpgenAnd3 -- And3 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenAnd3', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits three inputs AND with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional): Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False): In order to generate a layout + \item \textbf{behavioral} (optional, default value : False): In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 and i1 and i2 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_and3 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 16 ) + self.in2 = SignalIn ( "in2", 16 ) + self.in3 = SignalIn ( "in3", 16 ) + self.out = SignalOut ( "o", 16 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenAnd3', "and3_16" + , param = { 'nbit' : 16 + , 'physical' : True + } + ) + self.I = Inst ( 'and3_16', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'q' : self.out + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref (0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenand4.tex b/stratus1/doc/dpgen/man_dpgenand4.tex new file mode 100644 index 00000000..2a45dc69 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenand4.tex @@ -0,0 +1,75 @@ +\begin{itemize} + \item \textbf{Name} : DpgenAnd4 -- And4 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenAnd4', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits four inputs AND with an output power of \verb-d- named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{i3} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 and i1 and i2 and i3 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_and4 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 2 ) + self.in2 = SignalIn ( "in2", 2 ) + self.in3 = SignalIn ( "in3", 2 ) + self.in4 = SignalIn ( "in4", 2 ) + self.out = SignalOut ( "o", 2 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenAnd4', 'and4_2' + , param = { 'nbit' : 2 + , 'physical' : True + } + ) + self.I = Inst ( 'and4_2', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'i3' : self.in4 + , 'q' : self.out + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenbuff.tex b/stratus1/doc/dpgen/man_dpgenbuff.tex new file mode 100644 index 00000000..9d5314e4 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenbuff.tex @@ -0,0 +1,66 @@ +\begin{itemize} + \item \textbf{Name} : DpgenBuff -- Buffer Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenBuff', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits inverter with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2, 4 or 8 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_buff ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 32 ) + self.o = SignalOut ( "o", 32 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenBuff', 'buff_32' + , param = { 'nbit' : 32 + , 'physical' : True + } + ) + self.I = Inst ( 'buff_32', 'inst' + , map = { 'i0' : self.i + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenbuse.tex b/stratus1/doc/dpgen/man_dpgenbuse.tex new file mode 100644 index 00000000..5473691e --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenbuse.tex @@ -0,0 +1,65 @@ +\begin{itemize} + \item \textbf{Name} : DpgenBuse -- Tristate Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenBuse', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits tristate named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : select ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{q} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nts:BLOCK(cmd = '1') BEGIN + q <= GUARDED i0; +END +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_buse ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 8 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenBuse', 'buse_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'buse_8', 'inst' + , map = { 'i0' : self.i + , 'cmd' : self.cmd + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenconst.tex b/stratus1/doc/dpgen/man_dpgenconst.tex new file mode 100644 index 00000000..458497b0 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenconst.tex @@ -0,0 +1,60 @@ +\begin{itemize} + \item \textbf{Name} : DpgenConst -- Constant Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenConst', modelname + , param = { 'nbit' : n + , 'const' : constVal + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits constant named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{q} : the constant (output, \verb-n- bit) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit } (mandatory) : Defines the size of the generator + \item \textbf{const} (mandatory) : Defines the constant (string beginning with 0b, 0x or 0o functions of the basis) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +q <= constVal +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_const ( Model ) : + + def Interface ( self ) : + self.o = SignalOut ( "o", 32 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenConst', 'const_0x0000ffff' + , param = { 'nbit' : 32 + , 'const' : "0x0000FFFF" + , 'physical' : True + } + ) + self.I = Inst ( 'const_0x0000ffff', 'inst' + , map = { 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgendff.tex b/stratus1/doc/dpgen/man_dpgendff.tex new file mode 100644 index 00000000..b6671e0b --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgendff.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenDff -- Dynamic Flip-Flop Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenDff', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a n bits dynamic flip-flop named \verb-modelname-. The two latches of this flip-flop are dynamic, i.e. the data is stored in a capacitor. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{wen} : write enable (1 bit) + \item \textbf{ck} : clock signal (1 bit) + \item \textbf{i0} : data input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item When wen is set to \verb-one-, enables the writing of the flip-flop + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_dff ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.wen = SignalIn ( "wen", 1 ) + self.i = SignalIn ( "i", 4 ) + self.o = SignalOut ( "o", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenDff', 'dff_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'dff_4', 'inst' + , map = { "wen" : self.wen + , "ck" : self.ck + , "i0" : self.i + , "q" : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgendfft.tex b/stratus1/doc/dpgen/man_dpgendfft.tex new file mode 100644 index 00000000..0ecb7001 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgendfft.tex @@ -0,0 +1,77 @@ +\begin{itemize} + \item \textbf{Name} : DpgenDfft -- Dynamic Flip-Flop with Scan-Path Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenDfft', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a n bits dynamic flip-flop with scan-path named \verb-modelname-. The two latches of this flip-flop are dynamic, i.e. the data is stored in a capacitor. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{scan} : scan-path mode (input, 1 bit) + \item \textbf{scin} : scan path in (input, 1 bit) + \item \textbf{wen} : write enable (1 bit) + \item \textbf{ck} : clock signal (1 bit) + \item \textbf{i0} : data input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item When scan is set to \verb-one-, it enables the scan-path mode. Note that in scan-path mode, the wen signal is not effective + \item scin is the input of the scan-path. This terminal is different from \verb-i0[0]-. The scout is q[N-1] (in the following example this is \verb-q[31]-) + \item When wen is set to \verb-one- enables the writing of the flip-flop + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_dfft ( Model ) : + + def Interface ( self ) : + self.scan = SignalIn ( "scin", 1 ) + self.scin = SignalIn ( "scan", 1 ) + self.ck = SignalIn ( "ck", 1 ) + self.wen = SignalIn ( "wen", 1 ) + self.i = SignalIn ( "i", 4 ) + self.o = SignalOut ( "o", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenDfft', 'dfft_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'dfft_4', 'inst' + , map = { "wen" : self.wen + , "ck" : self.ck + , "scan" : self.scan + , "scin" : self.scin + , "i0" : self.i + , "q" : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenfifo.tex b/stratus1/doc/dpgen/man_dpgenfifo.tex new file mode 100644 index 00000000..9d5b8ff2 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenfifo.tex @@ -0,0 +1,91 @@ +\begin{itemize} + \item \textbf{Name} : DpgenFifo -- Fifo Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenFifo', modelname + , param = { 'nbit' : n + , 'nword' : regNumber + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a FIFO of \verb-regNumber- words of \verb-n- bits named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{ck} : clock signal (input, 1 bit) + \item \textbf{reset} : reset signal (input, 1 bit) + \item \textbf{r} : read requested (input, 1 bit) + \item \textbf{w} : write requested (input, 1 bit) + \item \textbf{rok} : read acknowledge (output, 1 bit) + \item \textbf{wok} : write acknowledge (output, 1 bit) + \item \textbf{sel} : select the write bus (input, 1 bit) + \item \textbf{datain0} : first write bus (input, \verb-n- bits) + \item \textbf{datain1} : second write bus (input, \verb-n- bits) + \item \textbf{dataout} : read bus (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the words (even, between 2 and 64) + \item \textbf{nword} (mandatory) : Defines the number of words (even, between 4 and 32) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item datain0 and datain1 : the two write busses. Only one is used to actually write the FIFO, it is selected by the sel signal. + \item sel : when set to \verb-zero- the datain0 is used to write the register word, otherwise it will be datain1. + \item r, rok : set r when a word is requested, rok tells that a word has effectively been popped (rok == not empty). + \item w, wok : set w when a word is pushed, wok tells that the word has effectively been pushed (wok == not full). + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_fifo ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.reset = SignalIn ( "reset", 1 ) + self.r = SignalIn ( "r", 1 ) + self.w = SignalIn ( "w", 1 ) + self.rok = SignalInOut ( "rok", 1 ) + self.wok = SignalInOut ( "wok", 1 ) + self.sel = SignalIn ( "sel", 1 ) + self.datain0 = SignalIn ( "datain0", 4 ) + self.datain1 = SignalIn ( "datain1", 4 ) + self.dataout = SignalOut ( "dataout", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenFifo', 'fifo_4_16' + , param = { 'nbit' : 4 + , 'nword' : 16 + , 'physical' : True + } + ) + self.I = Inst ( 'fifo_4_16', 'inst' + , map = { 'ck' : self.ck + , 'reset' : self.reset + , 'r' : self.r + , 'w' : self.w + , 'rok' : self.rok + , 'wok' : self.wok + , 'sel' : self.sel + , 'datain0' : self.datain0 + , 'datain1' : self.datain1 + , 'dataout' : self.dataout + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgeninv.tex b/stratus1/doc/dpgen/man_dpgeninv.tex new file mode 100644 index 00000000..b95e3f57 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgeninv.tex @@ -0,0 +1,66 @@ +\begin{itemize} + \item \textbf{Name} : DpgenInv -- Inverter Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenInv', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits inverter with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1, 2, 4 or 8 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_inv ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 54 ) + self.o = SignalOut ( "o", 54 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenInv', 'inv_54' + , param = { 'nbit' : 54 + , 'physical' : True + } + ) + self.I = Inst ( 'inv_54', 'inst' + , map = { 'i0' : self.i + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenmux2.tex b/stratus1/doc/dpgen/man_dpgenmux2.tex new file mode 100644 index 00000000..c9c94920 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenmux2.tex @@ -0,0 +1,74 @@ +\begin{itemize} + \item \textbf{Name} : DpgenMux2 -- Multiplexer Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenMux2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs multiplexer with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : select ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{i1} : input ( \verb-n- bits ) + \item \textbf{q} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{nbit\_cmd} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= WITH cmd SELECT i0 WHEN '0', + i1 WHEN '1'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_mux2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenMux2', 'mux2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'mux2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'cmd' : self.cmd + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennand2.tex b/stratus1/doc/dpgen/man_dpgennand2.tex new file mode 100644 index 00000000..e34dc41f --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennand2.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNand2 -- Nand2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNand2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs NAND with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 and i1 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nand2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNand2', 'nand2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'nand2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennand2mask.tex b/stratus1/doc/dpgen/man_dpgennand2mask.tex new file mode 100644 index 00000000..0b9c616f --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennand2mask.tex @@ -0,0 +1,74 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNand2mask -- Programmable Mask Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNand2mask', modelname + , param = { 'nbit' : n + , 'const' : constVal + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits conditionnal NAND mask named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : mask control ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{nq} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{const} (mandatory) : Defines the constant (string beginning with 0b, 0x or 0o functions of the basis) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item If the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{ANDed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 and constVal) WHEN '1'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nand2mask ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 32 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 32 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNand2mask', 'nand2mask_0x0000ffff' + , param = { 'nbit' : 32 + , 'const' : "0x0000FFFF" + , 'physical' : True + } + ) + self.I = Inst ( 'nand2mask_0x0000ffff', 'inst' + , map = { 'i0' : self.i + , 'cmd' : self.cmd + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennand3.tex b/stratus1/doc/dpgen/man_dpgennand3.tex new file mode 100644 index 00000000..1dfef887 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennand3.tex @@ -0,0 +1,72 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNand3 -- Nand3 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNand3', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits three inputs NAND with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 and i1 and i2 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nand3 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 20 ) + self.in2 = SignalIn ( "in2", 20 ) + self.in3 = SignalIn ( "in3", 20 ) + self.o = SignalOut ( "o", 20 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNand3', 'nand3_20' + , param = { 'nbit' : 20 + , 'physical' : True + } + ) + self.I = Inst ( 'nand3_20', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennand4.tex b/stratus1/doc/dpgen/man_dpgennand4.tex new file mode 100644 index 00000000..a1057b73 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennand4.tex @@ -0,0 +1,75 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNand4 -- Nand4 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNand4', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits four inputs NAND with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{i3} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 and i1 and i2 and i3 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nand4 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 9 ) + self.in2 = SignalIn ( "in2", 9 ) + self.in3 = SignalIn ( "in3", 9 ) + self.in4 = SignalIn ( "in4", 9 ) + self.o = SignalOut ( "o", 9 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNand4', 'nand4_9' + , param = { 'nbit' : 9 + , 'physical' : True + } + ) + self.I = Inst ( 'nand4_9', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'i3' : self.in4 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennbuse.tex b/stratus1/doc/dpgen/man_dpgennbuse.tex new file mode 100644 index 00000000..e5da167d --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennbuse.tex @@ -0,0 +1,65 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNbuse -- Tristate Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNbuse', modelname + , param = { 'nbit' : n + , 'physical' : true + , 'behavioral' : true + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits tristate with an complemented output named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : select ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{nq} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nts:BLOCK(cmd = '1') BEGIN + nq <= GUARDED not(i0); +END +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nbuse ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 29 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 29 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNbuse', 'nbuse29' + , param = { 'nbit' : 29 + , 'physical' : True + } + ) + self.I = Inst ( 'nbuse29', 'inst' + , map = { 'i0' : self.i + , 'cmd' : self.cmd + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennmux2.tex b/stratus1/doc/dpgen/man_dpgennmux2.tex new file mode 100644 index 00000000..e7300a0d --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennmux2.tex @@ -0,0 +1,67 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNmux2 -- Multiplexer Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNmux2', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs multiplexer named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : select ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{i1} : input ( \verb-n- bits ) + \item \textbf{nq} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= WITH cmd SELECT not i0 WHEN '0', + not i1 WHEN '1'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nmux2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 5 ) + self.in2 = SignalIn ( "in2", 5 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 5 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNmux2', 'nmux2_5' + , param = { 'nbit' : 5 + , 'physical' : True + } + ) + self.I = Inst ( 'nmux2_5', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'cmd' : self.cmd + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennor2.tex b/stratus1/doc/dpgen/man_dpgennor2.tex new file mode 100644 index 00000000..7c79468d --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennor2.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNor2 -- Nor2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNor2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs NOR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 or i1 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nor2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNor2', 'nor2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'nor2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennor2mask.tex b/stratus1/doc/dpgen/man_dpgennor2mask.tex new file mode 100644 index 00000000..4327f164 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennor2mask.tex @@ -0,0 +1,74 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNor2mask -- Programmable Mask Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNor2mask', modelname + , param = { 'nbit' : n + , 'const' : constVal + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits conditionnal NOR mask named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : mask control ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{nq} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{const} (mandatory) : Defines the constant (string beginning with 0b, 0x or 0o functions of the basis) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item If the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{ORed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 or constVal) WHEN '1'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nor2mask ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 8 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNor2mask', 'nor2mask_000111' + , param = { 'nbit' : 8 + , 'const' : "0b000111" + , 'physical' : True + } + ) + self.I = Inst ( 'nor2mask_000111', 'inst' + , map = { 'i0' : self.i + , 'cmd' : self.cmd + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennor3.tex b/stratus1/doc/dpgen/man_dpgennor3.tex new file mode 100644 index 00000000..33cdcd41 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennor3.tex @@ -0,0 +1,72 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNor3 -- Nor3 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNor3', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits three inputs NOR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 or i1 or i2 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nor3 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 3 ) + self.in2 = SignalIn ( "in2", 3 ) + self.in3 = SignalIn ( "in3", 3 ) + self.o = SignalOut ( "out", 3 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNor3', 'nor3_3' + , param = { 'nbit' : 3 + , 'physical' : True + } + ) + self.I = Inst ( 'nor3_3', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennor4.tex b/stratus1/doc/dpgen/man_dpgennor4.tex new file mode 100644 index 00000000..cb45bc99 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennor4.tex @@ -0,0 +1,76 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNor4 -- Nor4 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNor4', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits four inputs NOR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{i3} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 or i1 or i2 or i3 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nor4 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 15 ) + self.in2 = SignalIn ( "in2", 15 ) + self.in3 = SignalIn ( "in3", 15 ) + self.in4 = SignalIn ( "in4", 15 ) + self.out = SignalOut ( "o", 15 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNor4', 'nor4_15' + , param = { 'nbit' : 15 + , 'physical' : True + } + ) + self.I = Inst ( 'nor4_15', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'i3' : self.in4 + , 'nq' : self.out + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgennul.tex b/stratus1/doc/dpgen/man_dpgennul.tex new file mode 100644 index 00000000..4a60747b --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgennul.tex @@ -0,0 +1,58 @@ +\begin{itemize} + \item \textbf{Name} : DpgenNul -- Zero Detector Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenNul', modelname + , param = { 'nbit' : n + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits zero detector named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : value to check (input, \verb-n- bits) + \item \textbf{q} : null flag (1 bit) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +q <= '1' WHEN ( i0 = X"00000000" ) ELSE '0'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_nul ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 4 ) + self.o = SignalOut ( "o", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenNul', 'nul_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'nul_4', 'inst' + , map = { 'i0' : self.i + , 'nul' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenor2.tex b/stratus1/doc/dpgen/man_dpgenor2.tex new file mode 100644 index 00000000..690082f7 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenor2.tex @@ -0,0 +1,70 @@ +\begin{itemize} + \item \textbf{Name} : DpgenOr2 -- Or2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenOr2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs OR with an output power of \verb-drive- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the a map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, the \verb-drive- is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 or i1 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_or2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenOr2', 'or2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'or2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenor3.tex b/stratus1/doc/dpgen/man_dpgenor3.tex new file mode 100644 index 00000000..f557ac75 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenor3.tex @@ -0,0 +1,72 @@ +\begin{itemize} + \item \textbf{Name} : DpgenOr3 -- Or3 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenOr3', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits three inputs OR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 or i1 or i2 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_or3 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 5 ) + self.in2 = SignalIn ( "in2", 5 ) + self.in3 = SignalIn ( "in3", 5 ) + self.o = SignalOut ( "o", 5 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenOr3', 'or3_5' + , param = { 'nbit' : 5 + , 'physical' : True + } + ) + self.I = Inst ( 'or3_5', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenor4.tex b/stratus1/doc/dpgen/man_dpgenor4.tex new file mode 100644 index 00000000..0b31576a --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenor4.tex @@ -0,0 +1,75 @@ +\begin{itemize} + \item \textbf{Name} : DpgenOr4 -- Or4 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenOr4', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits four inputs OR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{i2} : input (\verb-n- bits) + \item \textbf{i3} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 or i1 or i2 or i3 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_or4 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 16 ) + self.in2 = SignalIn ( "in2", 16 ) + self.in3 = SignalIn ( "in3", 16 ) + self.in4 = SignalIn ( "in4", 16 ) + self.out = SignalOut ( "o", 16 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenOr4', 'or4_16' + , param = { 'nbit' : 16 + , 'physical' : True + } + ) + self.I = Inst ( 'or4_16', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'i2' : self.in3 + , 'i3' : self.in4 + , 'q' : self.out + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenram.tex b/stratus1/doc/dpgen/man_dpgenram.tex new file mode 100644 index 00000000..bdb25865 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenram.tex @@ -0,0 +1,72 @@ +\begin{itemize} + \item \textbf{Name} : DpgenRam -- RAM Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenRam', modelname + , param = { 'nbit' : n + , 'nword' : regNumber + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a RAM of \verb-regNumber- words of \verb-n- bits named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{ck} : clock signal (input, 1 bit) + \item \textbf{w} : write requested (input, 1 bit) + \item \textbf{selram} : select the write bus (input, 1 bit) + \item \textbf{ad} : the address (input, \verb-Y- bits) + \item \textbf{datain} : write bus (input, \verb-n- bits) + \item \textbf{dataout} : read bus (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{nword} (mandatory) : Defines the size of the words + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_ram ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.w = SignalIn ( "w", 1 ) + self.selram = SignalIn ( "selram", 1 ) + self.ad = SignalIn ( "ad", 5 ) + self.datain = SignalIn ( "datain", 32 ) + self.dataout = TriState ( "dataout", 32 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenRam', 'ram_32_32' + , param = { 'nbit' : 32 + , 'nword' : 32 + , 'physical' : True + } + ) + self.I = Inst ( 'ram_32_32', 'inst' + , map = { 'ck' : self.ck + , 'w' : self.w + , 'selram' : self.selram + , 'ad' : self.ad + , 'datain' : self.datain + , 'dataout' : self.dataout + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenrf1.tex b/stratus1/doc/dpgen/man_dpgenrf1.tex new file mode 100644 index 00000000..a96f8f91 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenrf1.tex @@ -0,0 +1,82 @@ +\begin{itemize} + \item \textbf{Name} : DpgenRf1, DpgenRf1r0 -- Register File Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenRf1', modelname + , param = { 'nbit' : n + , 'nword' : regNumber + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a register file of \verb-regNumber- words of \verb-n- bits without decoder named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{ckok} : clock signal (input, 1 bit) + \item \textbf{sel} : select the write bus (input, 1 bit) + \item \textbf{selr} : the decoded read address (input, \verb-regNumber- bits) + \item \textbf{selw} : the decoded write address (input, \verb-regNumber- bits) + \item \textbf{datain0} : first write bus (input, \verb-n- bits) + \item \textbf{datain1} : second write bus (input, \verb-n- bits) + \item \textbf{dataout} : read bus (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the words (even, between 2 and 64) + \item \textbf{nword} (mandatory) : Defines the number of the words (even, between 4 and 32) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item datain0 and datain1 are the two write busses. Only one is used to actually write the register word, it is selected by the sel signal. + \item When sel is set to zero datain0 is used to write the register word, otherwise it will be datain1 + \item selr, selw : this register file have no decoder, so selr have a bus width equal to \verb-regNumber-. One bit for each word + \item The DpgenRf1r0 variant differs from the DpgenRf1 in that the register of address zero is stuck to zero. You can write into it, it will not change the value. When read, it will always return zero + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_rf1 ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.sel = SignalIn ( "sel", 1 ) + self.selr = SignalIn ( "selr", 16 ) + self.selw = SignalIn ( "selw", 16 ) + self.datain0 = SignalIn ( "datain0", 4 ) + self.datain1 = SignalIn ( "datain1", 4 ) + self.dataout = SignalOut ( "dataout", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenRf1', 'rf1_4_16' + , param = { 'nbit' : 4 + , 'nword' : 16 + , 'physical' : True + } + ) + self.I = Inst ( 'rf1_4_16', 'inst' + , map = { 'ck' : self.ck + , 'sel' : self.sel + , 'selr' : self.selr + , 'selw' : self.selw + , 'datain0' : self.datain0 + , 'datain1' : self.datain1 + , 'dataout' : self.dataout + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenrf1d.tex b/stratus1/doc/dpgen/man_dpgenrf1d.tex new file mode 100644 index 00000000..67a207d7 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenrf1d.tex @@ -0,0 +1,89 @@ +\begin{itemize} + \item \textbf{Name} : DpgenRf1d, DpgenRf1dr0 -- Register File with Decoder Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenRf1d', modelname + , param = { 'nbit' : n + , 'nword' : regNumber + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a register file of \verb-regNumber- words of \verb-n- bits with decoder named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{ck} : clock signal (input, 1 bit) + \item \textbf{sel} : select the write bus (input, 1 bit) + \item \textbf{wen} : write enable (input, 1 bit) + \item \textbf{ren} : read enable (input, 1 bit) + \item \textbf{adr} : the read address (input, \verb-Y- bits) + \item \textbf{adw} : the write address (input, \verb-Y- bits) + \item \textbf{datain0} : first write bus (input, \verb-n- bits) + \item \textbf{datain1} : second write bus (input, \verb-n- bits) + \item \textbf{dataout} : read bus (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the words (even, between 2 and 64) + \item \textbf{nword} (mandatory) : Defines the number of the words (even, between 6 and 32) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item datain0 and datain1 are the two write busses. Only one is used to actually write the register word, it is selected by the sel signal. + \item When sel is set to zero datain0 is used to write the register word, otherwise it will be datain1 + \item adr, adw : the width (Y) of those signals is computed from regNumber : \verb-Y = log2(regNumber)- + \item wen and ren : write enable and read enable, allows reading and writing when sets to \verb-one- + \item The DpgenRf1dr0 variant differs from the DpgenRf1d in that the register of address zero is stuck to zero. You can write into it, it will not change the value. When read, it will always return zero + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_rf1d ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.sel = SignalIn ( "sel", 1 ) + self.wen = SignalIn ( "wen", 1 ) + self.ren = SignalIn ( "ren", 1 ) + self.adr = SignalIn ( "adr", 4 ) + self.adw = SignalIn ( "adw", 4 ) + self.datain0 = SignalIn ( "datain0", 4 ) + self.datain1 = SignalIn ( "datain1", 4 ) + self.dataout = SignalOut ( "dataout", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenRf1d', 'rf1d_4_16' + , param = { 'nbit' : 4 + , 'nword' : 16 + , 'physical' : True + } + ) + self.I = Inst ( 'rf1d_4_16', 'inst' + , map = { 'ck' : self.ck + , 'sel' : self.sel + , 'wen' : self.wen + , 'ren' : self.ren + , 'adr' : self.adr + , 'adw' : self.adw + , 'datain0' : self.datain0 + , 'datain1' : self.datain1 + , 'dataout' : self.dataout + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenrom2.tex b/stratus1/doc/dpgen/man_dpgenrom2.tex new file mode 100644 index 00000000..b6bb432b --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenrom2.tex @@ -0,0 +1,66 @@ +\begin{itemize} + \item \textbf{Name} : DpgenRom2 -- 2 words ROM Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenRom2', modelname + , param = { 'nbit' : n + , 'val0' : constVal0 + , 'val1' : constVal1 + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits 2 words optimized ROM named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{sel0} : address of the value (input, 1 bit) + \item \textbf{q} : the selected word (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{val0} (mandatory) : Defines the first word + \item \textbf{val1} (mandatory) : Defines the second word + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +q <= WITH sel0 SELECT + constVal0 WHEN B"0", + constVal1 WHEN B"1"; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_rom2 ( Model ) : + + def Interface ( self ) : + self.sel0 = SignalIn ( "sel0", 1 ) + self.q = SignalOut ( "dataout", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenRom2', 'rom2_0b1010_0b1100' + , param = { 'nbit' : 4 + , 'val0' : "0b1010" + , 'val1' : "0b1100" + , 'physical' : True + } + ) + self.I = Inst ( 'rom2_0b1010_0b1100', 'inst' + , map = { 'sel0' : self.sel0 + , 'q' : self.q + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenrom4.tex b/stratus1/doc/dpgen/man_dpgenrom4.tex new file mode 100644 index 00000000..2347ad11 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenrom4.tex @@ -0,0 +1,76 @@ +\begin{itemize} + \item \textbf{Name} : DpgenRom4 -- 4 words ROM Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenRom4', modelname + , param = { 'nbit' : n + , 'val0' : constVal0 + , 'val1' : constVal1 + , 'val2' : constVal2 + , 'val3' : constVal3 + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits 4 words optimized ROM named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{sel1} : upper bit of the address of the value (input, 1 bit) + \item \textbf{sel0} : lower bit of the address of the value (input, 1 bit) + \item \textbf{q} : the selected word (output, \verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{val0} (mandatory) : Defines the first word + \item \textbf{val1} (mandatory) : Defines the second word + \item \textbf{val2} (mandatory) : Defines the third word + \item \textbf{val3} (mandatory) : Defines the fourth word + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +q <= WITH sel1 & sel0 SELECT constVal0 WHEN B"00", + constVal1 WHEN B"01", + constVal2 WHEN B"10", + constVal3 WHEN B"11"; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_rom4 ( Model ) : + + def Interface ( self ) : + self.sel0 = SignalIn ( "sel0", 1 ) + self.sel1 = SignalIn ( "sel1", 1 ) + self.q = SignalOut ( "dataout", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenRom4', 'rom4_0b1010_0b1100_0b1111_0b0001' + , param = { 'nbit' : 4 + , 'val0' : "0b1010" + , 'val1' : "0b1100" + , 'val2' : "0b1111" + , 'val3' : "0b0001" + , 'physical' : True + } + ) + self.I = Inst ( 'rom4_0b1010_0b1100_0b1111_0b0001', 'inst' + , map = { 'sel0' : self.sel0 + , 'sel1' : self.sel1 + , 'q' : self.q + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgensff.tex b/stratus1/doc/dpgen/man_dpgensff.tex new file mode 100644 index 00000000..5f311107 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgensff.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenSff -- Static Flip-Flop Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenSff', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a n bits static flip-flop named \verb-modelname-. The two latches of this flip-flop are static, i.e. each one is made of two interters looped together. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{wen} : write enable (1 bit) + \item \textbf{ck} : clock signal (1 bit) + \item \textbf{i0} : data input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item When wen is set to \verb-one-, enables the writing of the flip-flop + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_sff ( Model ) : + + def Interface ( self ) : + self.ck = SignalIn ( "ck", 1 ) + self.wen = SignalIn ( "wen", 1 ) + self.i = SignalIn ( "i", 4 ) + self.o = SignalOut ( "o", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenSff', 'sff_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'sff_4', 'inst' + , map = { "wen" : self.wen + , "ck" : self.ck + , "i0" : self.i + , "q" : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgensfft.tex b/stratus1/doc/dpgen/man_dpgensfft.tex new file mode 100644 index 00000000..90db45dd --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgensfft.tex @@ -0,0 +1,77 @@ +\begin{itemize} + \item \textbf{Name} : DpgenSfft -- Static Flip-Flop with Scan-Path Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenSfft', modelname + , param = { 'nbit' : n + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a n bits static flip-flop with scan-path named \verb-modelname-. The two latches of this flip-flop are static i.e. each one is made of two interters looped togethers. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{scan} : scan-path mode (input, 1 bit) + \item \textbf{scin} : scan path in (input, 1 bit) + \item \textbf{wen} : write enable (1 bit) + \item \textbf{ck} : clock signal (1 bit) + \item \textbf{i0} : data input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the a map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item When scan is set to \verb-one-, it enables the scan-path mode. Note that in scan-path mode, the wen signal is not effective + \item scin : the input of the scan-path. This terminal is different from \verb-i0[0]-. The scout is \verb-q[N--\verb-1]- (in the following example this is \verb-q[3]-) + \item When wen is set to \verb-one-, it enables the writing of the flip-flop + \end{itemize} +% \item \textbf{Behavior} : +% \begin{verbatim} +% \end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_sfft ( Model ) : + + def Interface ( self ) : + self.scan = SignalIn ( "scin", 1 ) + self.scin = SignalIn ( "scan", 1 ) + self.ck = SignalIn ( "ck", 1 ) + self.wen = SignalIn ( "wen", 1 ) + self.i = SignalIn ( "in", 4 ) + self.o = SignalOut ( "out", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenSfft', 'sfft_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'sfft_4', 'inst' + , map = { "wen" : self.wen + , "ck" : self.ck + , "scan" : self.scan + , "scin" : self.scin + , "i0" : self.i + , "q" : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenshift.tex b/stratus1/doc/dpgen/man_dpgenshift.tex new file mode 100644 index 00000000..a965068e --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenshift.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenShift -- Shifter Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenShift', modelname + , param = { 'nbit' : n + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits shifter named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{op} : select the kind of shift (input, 2 bits) + \item \textbf{shamt} : the shift amount (input, \verb-Y- bits) + \item \textbf{i} : value to shift (input, \verb-n- bits) + \item \textbf{o} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-op[0]- signal is set to \verb-one-, performs a right shift, performs a left shift otherwise. + \item If the \verb-op[1]- signal is set to \verb-one-, performs an arithmetic shift (only meaningful in case of a right shift). + \item shamt : specifies the shift amount. The width of this signal (\verb-Y-) is computed from the operator's width : \verb-Y = ceil(log2(n)) -- 1 + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_shifter ( Model ) : + + def Interface ( self ) : + self.instop = SignalIn ( "instop", 2 ) + self.instshamt = SignalIn ( "instshamt", 2 ) + self.insti = SignalIn ( "insti", 4 ) + self.insto = SignalOut ( "insto", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenShifter', 'shifter_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'shifter_4', 'inst' + , map = { 'op' : self.instop + , 'shamt' : self.instshamt + , 'i' : self.insti + , 'o' : self.insto + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenshrot.tex b/stratus1/doc/dpgen/man_dpgenshrot.tex new file mode 100644 index 00000000..0781929c --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenshrot.tex @@ -0,0 +1,70 @@ +\begin{itemize} + \item \textbf{Name} : DpgenShrot -- Shift/Rotation Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenShrot', modelname + , param = { 'nbit' : n + , 'physical' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits shift/rotation operator named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{op} : select the kind of shift/rotation (input, 3 bits) + \item \textbf{shamt} : the shift amount (input, \verb-Y- bits) + \item \textbf{i} : value to shift (input, \verb-n- bits) + \item \textbf{o} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-op[0]- signal is set to \verb-one-, performs a right shift/rotation , otherwise left shift/rotation occurs. + \item If the \verb-op[1]- signal is set to \verb-one-, performs an arithmetic shift (only meaningful in case of a right shift). + \item If the \verb-op[2]- signal is set to \verb-one-, performs a rotation, otherwise performs a shift.. + \item \verb-shamt- specifies the shift amount. The width of this signal (\verb-Y-) is computed from the operator's width : \verb-Y = ceil(log2(n))- - 1 + \end{itemize} +% \item \textbf{Behavior} : +%\begin{verbatim} +%\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_shrot ( Model ) : + + def Interface ( self ) : + self.rotop = SignalIn ( "rotop", 3 ) + self.instshamt = SignalIn ( "instshamt", 2 ) + self.insti = SignalIn ( "insti", 4 ) + self.insto = SignalOut ( "insto", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenShrot', 'shrot_4' + , param = { 'nbit' : 4 + , 'physical' : True + } + ) + self.I = Inst ( 'shrot_4', 'inst' + , map = { 'op' : self.rotop + , 'shamt' : self.instshamt + , 'i' : self.insti + , 'o' : self.insto + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenxnor2.tex b/stratus1/doc/dpgen/man_dpgenxnor2.tex new file mode 100644 index 00000000..485414b8 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenxnor2.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenXnor2 -- Xnor2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenXnor2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs XNOR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{nq} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 1 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= not ( i0 xor i1 ) +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_xnor2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenXnor2', 'xnor2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'xnor2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenxnor2mask.tex b/stratus1/doc/dpgen/man_dpgenxnor2mask.tex new file mode 100644 index 00000000..257e34fd --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenxnor2mask.tex @@ -0,0 +1,74 @@ +\begin{itemize} + \item \textbf{Name} : DpgenXnor2mask -- Programmable Mask Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenXnor2mask', modelname + , param = { 'nbit' : n + , 'const' : constVal + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits conditionnal XNOR mask named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{cmd} : mask control ( 1 bit ) + \item \textbf{i0} : input ( \verb-n- bits ) + \item \textbf{nq} : output ( \verb-n- bits ) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{const} (mandatory) : Defines the constant (string beginning with 0b, 0x or 0o functions of the basis) + \item \textbf{physical} (optional, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optional, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{How it works} : + \begin{itemize} + \item If the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item If the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{XORed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 xor constVal) WHEN '1'; +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_xnor2mask ( Model ) : + + def Interface ( self ) : + self.i = SignalIn ( "i", 8 ) + self.cmd = SignalIn ( "cmd", 1 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenXnor2mask', 'xnor2mask_0b000111' + , param = { 'nbit' : 8 + , 'const' : "0b000111" + , 'physical' : True + } + ) + self.I = Inst ( 'xnor2mask_0b000111', 'inst' + , map = { 'i0' : self.i + , 'cmd' : self.cmd + , 'nq' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/dpgen/man_dpgenxor2.tex b/stratus1/doc/dpgen/man_dpgenxor2.tex new file mode 100644 index 00000000..dab83383 --- /dev/null +++ b/stratus1/doc/dpgen/man_dpgenxor2.tex @@ -0,0 +1,69 @@ +\begin{itemize} + \item \textbf{Name} : DpgenXor2 -- Xor2 Macro-Generator + \item \textbf{Synopsys} : +\begin{verbatim} +Generate ( 'DpgenXor2', modelname + , param = { 'nbit' : n + , 'drive' : d + , 'physical' : True + , 'behavioral' : True + } + ) +\end{verbatim} + \item \textbf{Description} : Generates a \verb-n- bits two inputs XOR with an output power of \verb-d- named \verb-modelname-. + \item \textbf{Terminal Names} : + \begin{itemize} + \item \textbf{i0} : input (\verb-n- bits) + \item \textbf{i1} : input (\verb-n- bits) + \item \textbf{q} : output (\verb-n- bits) + \item \textbf{vdd} : power + \item \textbf{vss} : ground + \end{itemize} + \item \textbf{Parameters} : Parameters are given in the map \verb-param-. + \begin{itemize} + \item \textbf{nbit} (mandatory) : Defines the size of the generator + \item \textbf{drive} (optional) : Defines the output power of the gates + \begin{itemize} + \item Valid drive are : 2 or 4 + \item If this parameter is not defined, it's value is the smallest one permitted + \end{itemize} + \item \textbf{physical} (optionnal, default value : False) : In order to generate a layout + \item \textbf{behavioral} (optionnal, default value : False) : In order to generate a behavior + \end{itemize} + \item \textbf{Behavior} : +\begin{verbatim} +nq <= i0 xor i1 +\end{verbatim} + \item \textbf{Example} : +\begin{verbatim} +from stratus import * + +class inst_xor2 ( Model ) : + + def Interface ( self ) : + self.in1 = SignalIn ( "in1", 8 ) + self.in2 = SignalIn ( "in2", 8 ) + self.o = SignalOut ( "o", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Generate ( 'DpgenXor2', 'xor2_8' + , param = { 'nbit' : 8 + , 'physical' : True + } + ) + self.I = Inst ( 'xor2_8', 'inst' + , map = { 'i0' : self.in1 + , 'i1' : self.in2 + , 'q' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.I, NOSYM, Ref(0, 0) ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/html.entry b/stratus1/doc/html.entry new file mode 100644 index 00000000..239ad936 --- /dev/null +++ b/stratus1/doc/html.entry @@ -0,0 +1 @@ +
  • Stratus
    Netlist / Layout description language

    diff --git a/stratus1/doc/images/Makefile.am b/stratus1/doc/images/Makefile.am new file mode 100644 index 00000000..9689089a --- /dev/null +++ b/stratus1/doc/images/Makefile.am @@ -0,0 +1,11 @@ + +doc_en_latex_imagesdir = $(datadir)/doc/en/latex/stratus/images + +doc_en_latex_images_DATA = add1.png \ + add2.png \ + addaccu.png \ + editor.png \ + test.png \ + xml.png + +EXTRA_DIST = $(doc_en_latex_images_DATA) diff --git a/stratus1/doc/images/add1.png b/stratus1/doc/images/add1.png new file mode 100644 index 0000000000000000000000000000000000000000..8270f2d4c8cf990124dc03f8583f6c376687ba5f GIT binary patch literal 5500 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 QO&I`HgQ=D%zxlxYKi=2_r~m)} literal 0 HcmV?d00001 diff --git a/stratus1/doc/images/add2.png b/stratus1/doc/images/add2.png new file mode 100644 index 0000000000000000000000000000000000000000..08ac408bef89074615347ddc3c6b03e99944d4e8 GIT binary patch literal 15347 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�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�Ui#fi;DGpd*QeUI0w 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 LLW!R91H^v;BC+=3 literal 0 HcmV?d00001 diff --git a/stratus1/doc/images/test.png b/stratus1/doc/images/test.png new file mode 100644 index 0000000000000000000000000000000000000000..2b4f5751886e4baa0f6e6cce1024e2f073ae46bb GIT binary patch literal 23992 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 literal 0 HcmV?d00001 diff --git a/stratus1/doc/images/xml.png b/stratus1/doc/images/xml.png new file mode 100644 index 0000000000000000000000000000000000000000..35a496ada34acda5335b838e1e9074c5c7254dee GIT binary patch literal 44214 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 literal 0 HcmV?d00001 diff --git a/stratus1/doc/man_alias.tex b/stratus1/doc/man_alias.tex new file mode 100644 index 00000000..158c1e60 --- /dev/null +++ b/stratus1/doc/man_alias.tex @@ -0,0 +1,62 @@ +\subsubsection{Name} + Alias -- A net has an "alias name" + +\subsubsection{Synopsys} + +\verb-myNet.Alias ( net )- + +\subsubsection{Description} + +This method is applied to a net. This net has an "alias name". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : a net which is going to be an alias for the net which this method is applied to +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class myripple ( Model ) : + + def Interface ( self ) : + self.a = LogicIn ( "a", 4 ) + self.b = LogicIn ( "b", 4 ) + + self.cin = LogicIn ( "cin", 1 ) + + self.sout = LogicOut ( "sout", 4 ) + + self.cout = LogicOut ( "cout", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VddIn ( "vss" ) + + def Netlist ( self ) : + c_temp = Signal ( "c_temp", 5 ) + + self.cin.Alias ( c_temp[0] ) + self.cout.Alias ( c_temp[4] ) + + for i in range ( 4 ) : + Inst ( "Fulladder" + , map = { 'a' : self.a[i] + , 'b' : self.b[i] + , 'cin' : c_temp[i] + , 'sout' : self.sout[i] + , 'cout' : c_temp[i+1] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) +\end{verbatim} + +\indent The net \verb-cin- has the alias \verb-c_temp[0]- and the net cout has the alias \verb-c_temp[4]-. Thanks to this method, all the instanciations can be done in one unique \verb-for- loop. + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Nets}}{}{Nets}{secnet} +\hyperref[ref]{\emph{Extend}}{}{Extend}{secextend} +\hyperref[ref]{\emph{Cat}}{}{Cat}{seccat} diff --git a/stratus1/doc/man_alim_connectors.tex b/stratus1/doc/man_alim_connectors.tex new file mode 100644 index 00000000..6830d9c2 --- /dev/null +++ b/stratus1/doc/man_alim_connectors.tex @@ -0,0 +1,23 @@ +\subsubsection{Name} + +AlimConnectors -- Creation of connectors at the periphery of the core of a circuit + +\subsubsection{Synopsys} + +\begin{verbatim} +AlimConnectors() +\end{verbatim} + +\subsubsection{Description} + +This function creates the connectors in Alu 1 at the periphery of the core. + + +%\subsubsection{Errors} + +%Some errors may occur : +%\begin{itemize} + %\item \verb-[Stratus ERROR] AlimConnectors : can't get net ...- +%\end{itemize} + +\input{see_also} diff --git a/stratus1/doc/man_alim_rail.tex b/stratus1/doc/man_alim_rail.tex new file mode 100644 index 00000000..9204883f --- /dev/null +++ b/stratus1/doc/man_alim_rail.tex @@ -0,0 +1,52 @@ +\subsubsection{Name} + +AlimVerticalRail, AlimHorizontalRail -- Placement of a vertical/horizontal alimentation call back + +\subsubsection{Synopsys} + +\begin{verbatim} +AlimVerticalRail ( nb ) +\end{verbatim} + +\subsubsection{Description} + +These functions place a vertical/horizontal alimentation call back. It's position is given by the parameter given. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-nb- : coordinate of the rail + \begin{itemize} + \item For AlimVerticalRail, \verb-nb- is in pitches i.e. 5 lambdas + \item For AlimHorizontalRail, \verb-nb- is in slices i.e. 50 lambdas + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +AlimVerticalRail ( 50 ) +AlimVerticalRail ( 150 ) + +AlimHorizontalRail ( 10 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] AlimHorizontalRail :-\\\verb-Illegal argument y, y must be between ... and ...-\\The argument given is wrong : the call back would not be in the abutment box. + \item \verb-[Stratus ERROR] Placement of cells :-\\\verb-please check your file of layout with DRUC.-\\The placement of the cell needs to be correct in order to place a call back. Check the errors of placement. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_arithmetic.tex b/stratus1/doc/man_arithmetic.tex new file mode 100644 index 00000000..d6a9dba6 --- /dev/null +++ b/stratus1/doc/man_arithmetic.tex @@ -0,0 +1,73 @@ + \subsubsection{Description} + +Most common arithmetic operators can be instantiated without the \verb-Inst- constructor. + +\subsubsection{List} + +Arithmetical operators are listed below : +\begin{itemize} + \item \verb-Addition- : \verb-q <= i0 + i1- + \item \verb-Substraction- : \verb-q <= i0- - \verb-i1- + \item \verb-Multiplication- : \verb-q <= i0 * i1- + \item \verb-Division- : \verb-q <= i0 / i1- +\end{itemize} + +\subsubsection{Generators to instantiate} + +One can choose the generator to be used. Some methods are applied to the cell and set the generator used when using overloard. +\indent Methods are : +\begin{itemize} + \item \verb-SetAdd- (for addition and substraction) + \item \verb-SetMult- + \item \verb-SetDiv- +\end{itemize} + +\indent The generators used by default are : +\begin{itemize} + \item \verb-Addition- : Slansky adder + \item \verb-Substraction- : Slansky adder + inversor + cin = '1' + \item \verb-Multiplication- : CA2 multiplier (signed, modified booth/Wallace tree) + \item \verb-Division- : not available yet +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + self.B = LogicIn ( "b", 4 ) + + self.S = LogicOut ( "s", 4 ) + + self.T = LogicOut ( "t", 8 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= self.A + self.B + + self.T <= self.A * self.B +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] + : the nets must have the same lenght.-\\When one uses arithmetic expressions, one has to check that the sizes of both nets are equivalent. + \item \verb-[Stratus ERROR] : there is no alim.-\\The cell being created does not have the alimentation nets. The instanciation is impossible. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_boolean.tex b/stratus1/doc/man_boolean.tex new file mode 100644 index 00000000..25086cca --- /dev/null +++ b/stratus1/doc/man_boolean.tex @@ -0,0 +1,65 @@ +\subsubsection{Description} + +Most common boolean operators can be instantiated without the \verb-Inst- constructor. + +\subsubsection{List} + +Boolean operators are listed below : +\begin{itemize} + \item \verb-And2- : \verb-q <= i0 & i1- + \item \verb-Or2- : \verb-q <= i0 | i1- + \item \verb-Xor2- : \verb-q <= i0 ^ i1- + \item \verb-Inv- : \verb-q <= ~i0- +\end{itemize} + + +\subsubsection{Generators to instantiate} + +One can choose the generator to be used. Some methods are applied to the cell and set the generator used when using \verb-&-, \verb-|-, \verb-^- and \verb-~-. The generators used by default are the ones from the virtual library.\\ + +\indent Methods are : +\begin{itemize} + \item \verb-SetAnd- + \item \verb-SetOr- + \item \verb-SetXor- + \item \verb-SetNot- +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + self.B = LogicIn ( "b", 4 ) + self.B = LogicIn ( "c", 4 ) + + self.S = LogicOut ( "s", 4 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= ( ~self.A & self.B ) | self.C +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] & : the nets must have the same lenght.-\\When one uses boolean expressions, one has to check that the sizes of both nets are equivalent. + \item \verb-[Stratus ERROR] : there is no alim.-\\The cell being created does not have the alimentation nets. The instanciation is impossible. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_buff.tex b/stratus1/doc/man_buff.tex new file mode 100644 index 00000000..c5ecebbe --- /dev/null +++ b/stratus1/doc/man_buff.tex @@ -0,0 +1,44 @@ +\subsubsection{Name} + +Buffer -- Easy way to instantiate a buffer + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netIn.Buffer() +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the input net of the buffer. The method returns a net : the output net.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetBuff- method. + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + + self.S = LogicOut ( "s", 4 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= self.A.Buffer() +\end{verbatim} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_cat.tex b/stratus1/doc/man_cat.tex new file mode 100644 index 00000000..bf1ab5a1 --- /dev/null +++ b/stratus1/doc/man_cat.tex @@ -0,0 +1,47 @@ +\subsubsection{Name} + +Cat -- Concatenation of nets + +\subsubsection{Synopsys} + +\begin{verbatim} +Cat ( net1, net2 ) +\end{verbatim} + +\subsubsection{Description} + +Concatenation of nets. The nets are given as parameters, the concatenation starts with the MSB. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-nets- : list of nets to be concatened (tuple or array) +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +myNet <= Cat ( A, B ) +\end{verbatim} +\indent Or : +\begin{verbatim} +tab = [] +tab.append ( A ) +tab.append ( B ) +myNet <= Cat ( tab ) +\end{verbatim} + +\indent If A and B are 2 bits nets, the net \verb-myNet- will be such as : +\begin{verbatim} +myNet[3] = A[1] +myNet[2] = A[0] +myNet[1] = B[1] +myNet[0] = B[0] +\end{verbatim} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Nets}}{}{Nets}{secnet} +\hyperref[ref]{\emph{Alias}}{}{Alias}{secalias} +\hyperref[ref]{\emph{Extend}}{}{Extend}{secextend} diff --git a/stratus1/doc/man_comp.tex b/stratus1/doc/man_comp.tex new file mode 100644 index 00000000..c38777be --- /dev/null +++ b/stratus1/doc/man_comp.tex @@ -0,0 +1,67 @@ +\subsubsection{Name} + +Eq/Ne : Easy way to test the value of the nets + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= net.Eq ( "n" ) +\end{verbatim} + +\subsubsection{Description} + +Comparaison functions are listed below : +\begin{itemize} + \item \verb-Eq- : returns \verb-true- if the value of the net is equal to \verb-n-. + \item \verb-Ne- : returns \verb-true- if the value of the net is different from \verb-n-. +\end{itemize} +\indent Note that it is possible to change the generator instanciated with the \verb-SetComp- method. + +\subsubsection{Parameters} + +The constant given as argument must be a string representing : +\begin{itemize} + \item A decimal number + \item A binary number : the string must begin with "0b" + \item An hexadecimal number : the string must begin with "0x" +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + + self.S = LogicOut ( "s", 1 ) + self.T = LogicOut ( "t", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= self.A.Eq ( "4" ) + + self.T <= self.A.Ne ( "1" ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Eq : the number does not match with the net's lenght.-\\When one uses comparaison functions on one net, one has to check that the number corresponds to the size of the net. + \item \verb-[Stratus ERROR] Eq :-\\\verb-the argument must be a string representing a number in decimal, binary (0b) or hexa (0x).-\\The string given as argument does not have the right form. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multipliexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a shifter}}{Shifter}{}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{Constant}{}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} diff --git a/stratus1/doc/man_const.tex b/stratus1/doc/man_const.tex new file mode 100644 index 00000000..c16a5b30 --- /dev/null +++ b/stratus1/doc/man_const.tex @@ -0,0 +1,81 @@ +\subsubsection{Name} + +Constant -- Easy way to instantiate constants + +\subsubsection{Synopsys} + +\begin{verbatim} +netOne <= One ( 2 ) + +net8 <= "8" +\end{verbatim} + +\subsubsection{Description} + +These functions simplify the way to instanciate constants. +\begin{itemize} + \item The functions \verb-One- and\verb-Zero- permits to initialise all the bits of a net to 'one' or 'zero'. + \item The instanciation of a constant thanks to a string can be done in decimal, hecadecimal or binary. +\end{itemize} + +\subsubsection{Parameters} + +\begin{itemize} + \item For \verb-One- and \verb-Zero- : + \begin{itemize} + \item \verb-n- : the arity of the net + \end{itemize} + \item For the instanciation of a constant : + \begin{itemize} + \item the constant given must be a string representing : + \begin{itemize} + \item A decimal number + \item A binary number : the string must begin with "0b" + \item An hexadecimal number : the string must begin with "0x" + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.Ones = LogicOut ( "ones", 2 ) + self.Zeros = LogicOut ( "zeros", 4 ) + + self.Eight = LogicOut ( "eight", 4 ) + self.Twentu = LogicOut ( "twenty", 5 ) + self.Two = LogicOut ( "two", 5 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.Ones <= One ( 2 ) + self.Zero <= Zero ( 4 ) + + self.Eight <= "8" + self.Twenty <= "0x14" + self.Two <= "0b10" +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Const :-\\\verb-the argument must be a string representing a number in decimal, binary (0b) or hexa (0x).-\\The string given as argument does not have the right form. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_def_ab.tex b/stratus1/doc/man_def_ab.tex new file mode 100644 index 00000000..b92e81b1 --- /dev/null +++ b/stratus1/doc/man_def_ab.tex @@ -0,0 +1,49 @@ +\subsubsection{Name} + +DefAb -- Creates the abutment box of the current cell + +\subsubsection{Synopsys} + +\begin{verbatim} +DefAb ( x1, y1, x2, y2 ) +\end{verbatim} + +\subsubsection{Description} + +This function creates the abutment box of the current cell.\\ + +\indent Note that one does not have to call this function before saving in order to create the abutment box. The abutment box is created nevertheless (given to placed instances). This function is usefull if one wants to create an abutment before placing the instances. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-( x1, y1)- : coordinates of the bottom left corner of the created abutment box. + \item \verb-( x2, y2)- : coordinates of the top right corner of the created abutment box. +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +DefAb ( 0, 0, 500, 100 ) + +Place ( Inv, NOSYM, 0, 0 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] DefAb : an abutment box already exists.-\\\verb- Maybe you should use ResizeAb function.-\\One has called DefAb but the current cell already has an abutment box.\\In order to modify the current abutment box, the function to call is ResizeAb. + \item \verb-[Stratus ERROR] DefAb :-\\\verb-Coordinates of an abutment Box in y must be multiple of the slice.-\\\verb-Coordinates of an abutment Box in x must be multiple of the pitch.-\\One has called DefAb with non authorized values. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_dpgenadsb2f.tex b/stratus1/doc/man_dpgenadsb2f.tex new file mode 100644 index 00000000..a43041df --- /dev/null +++ b/stratus1/doc/man_dpgenadsb2f.tex @@ -0,0 +1,58 @@ +\begin{itemize} + \item Name : DpgenAdsb2f -- Adder/Substractor Macro-Generator + \item Description : Generates a \verb-n- bits adder/substractor named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-add_sub- signal is set to \verb-zero- an addition is performed, otherwise it's a substraction. + \item Operation can be either signed or unsigned. In unsigned mode \verb-c31- is the overflow. in signed mode you have to compute overflow by \emph{XORing} \verb-c31- and \verb-c30- + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item add\_sub : select addition or substraction (input, 1 bit) + \item c31 : carry out. In unsigned mode, this is the overflow (output, 1 bit) + \item c30 : used to compute overflow in signed mode : \verb-overflow = c31 xor c30- (output, 1 bit) + \item i0 : first operand (input, \verb-n- bits) + \item i1 : second operand (input, \verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 8 ) + self._in2 = LogicIn ( "in2", 8 ) + + self._out = LogicOut ( "out", 8 ) + + self._as = LogicIn ( "as", 1 ) + self._c0 = LogicOut ( "c0", 1 ) + self._c1 = LogicOut ( "c1", 1 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenAdsb2f' + , param = { 'nbit' : 8 } + , map = { 'i0' : self._in + , 'i1' : self._in2 + , 'add_sub' : self._as + , 'q' : self._out + , 'c30' : self._c0 + , 'c31' : self._c1 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenand2.tex b/stratus1/doc/man_dpgenand2.tex new file mode 100644 index 00000000..83dc5a11 --- /dev/null +++ b/stratus1/doc/man_dpgenand2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenAnd2 -- And2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs AND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 and i1 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenAnd2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenand3.tex b/stratus1/doc/man_dpgenand3.tex new file mode 100644 index 00000000..2c008f75 --- /dev/null +++ b/stratus1/doc/man_dpgenand3.tex @@ -0,0 +1,51 @@ +\begin{itemize} + \item Name : DpgenAnd3 -- And3 Macro-Generator + \item Description : Generates a \verb-n- bits three inputs AND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 and i1 and i2 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenAnd3' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenand4.tex b/stratus1/doc/man_dpgenand4.tex new file mode 100644 index 00000000..2fc00f09 --- /dev/null +++ b/stratus1/doc/man_dpgenand4.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenAnd4 -- And4 Macro-Generator + \item Description : Generates a \verb-n- bits four inputs AND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item i3 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 and i1 and i2 and i3 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + self._in3 = LogicIn ( "in3", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenAnd4' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'i3' : self._in3 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenbuff.tex b/stratus1/doc/man_dpgenbuff.tex new file mode 100644 index 00000000..78e1ed04 --- /dev/null +++ b/stratus1/doc/man_dpgenbuff.tex @@ -0,0 +1,45 @@ +\begin{itemize} + \item Name : DpgenBuff -- Buffer Macro-Generator + \item Description : Generates a \verb-n- bits inverter with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2, 4 or 8 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenBuff' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenbuse.tex b/stratus1/doc/man_dpgenbuse.tex new file mode 100644 index 00000000..54eb3a71 --- /dev/null +++ b/stratus1/doc/man_dpgenbuse.tex @@ -0,0 +1,49 @@ +\begin{itemize} + \item Name : DpgenBuse -- Tristate Macro-Generator + \item Description : Generates a \verb-n- bits tristate with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 4 or 8 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : select ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item q : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} + \item Behavior : +\begin{verbatim} +nts:BLOCK(cmd = '1') BEGIN + q <= GUARDED i0; +END +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 32 ) + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = TriState ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenBuse' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in + , 'cmd' : self._cmd + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenconst.tex b/stratus1/doc/man_dpgenconst.tex new file mode 100644 index 00000000..c2658547 --- /dev/null +++ b/stratus1/doc/man_dpgenconst.tex @@ -0,0 +1,38 @@ +\begin{itemize} + \item Name : DpgenConst -- Constant Macro-Generator + \item Description : Generates a \verb-n- bits constant named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item q : the constant (output, \verb-n- bit) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item const : Defines the constant + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._out = LogicOut ( "out", 8 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + Inst ( 'DpgenConst' + , param = { 'nbit' : 8 + , 'const' : "0xA1" + } + , map = { 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgendff.tex b/stratus1/doc/man_dpgendff.tex new file mode 100644 index 00000000..f8483c22 --- /dev/null +++ b/stratus1/doc/man_dpgendff.tex @@ -0,0 +1,50 @@ +\begin{itemize} + \item Name : DpgenDff -- Dynamic Flip-Flop Macro-Generator + \item Description : Generates a n bits dynamic flip-flop named \verb-modelname-. The two latches of this flip-flop are dynamic, i.e. the data is stored in a capacitor. + \item How it works : + \begin{itemize} + \item when wen is set to \verb-one-, enables the writing of the flip-flop + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item wen : write enable (1 bit) + \item ck : clock signal (1 bit) + \item i0 : data input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._ck = LogicIn ( "ck", 1 ) + self._wen = LogicIn ( "wen", 1 ) + self._in = LogicIn ( "in", 4 ) + + self._out = LogicOut ( "out", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenDff' + , param = { 'nbit' : 4 } + , map = { "wen" : self._wen + , "ck" : self._ck + , "i0" : self._in + , "q" : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgendfft.tex b/stratus1/doc/man_dpgendfft.tex new file mode 100644 index 00000000..65d3de90 --- /dev/null +++ b/stratus1/doc/man_dpgendfft.tex @@ -0,0 +1,58 @@ +\begin{itemize} + \item Name : DpgenDfft -- Dynamic Flip-Flop with Scan-Path Macro-Generator + \item Description : Generates a n bits dynamic flip-flop with scan-path named \verb-modelname-. The two latches of this flip-flop are dynamic, i.e. the data is stored in a capacitor. + \item How it works : + \begin{itemize} + \item scan : when set to \verb-one- enables the scan-path mode. Note that in scan-path mode, the wen signal is not effective + \item scin : the input of the scan-path. This terminal is different from \verb-i0[0]-. The scout is q[N-1] (in the following example this is \verb-q[31]-) + \item when wen is set to \verb-one- enables the writing of the flip-flop + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item scan : scan-path mode (input, 1 bit) + \item scin : scan path in (input, 1 bit) + \item wen : write enable (1 bit) + \item ck : clock signal (1 bit) + \item i0 : data input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._scan = LogicIn ( "scin", 1 ) + self._scin = LogicIn ( "scan", 1 ) + self._ck = LogicIn ( "ck", 1 ) + self._wen = LogicIn ( "wen", 1 ) + self._in = LogicIn ( "in", 4 ) + + self._out = LogicOut ( "out", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenDfft' + , param = { 'nbit' : 4 } + , map = { "wen" : self._wen + , "ck" : self._ck + , "scan" : self._scan + , "scin" : self._scin + , "i0" : self._in + , "q" : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenfifo.tex b/stratus1/doc/man_dpgenfifo.tex new file mode 100644 index 00000000..8da737fd --- /dev/null +++ b/stratus1/doc/man_dpgenfifo.tex @@ -0,0 +1,79 @@ +\begin{itemize} + \item Name : DpgenFifo -- Fifo Macro-Generator + \item Description : Generates a FIFO pf \verb-ergNumber- words of \verb-n- bits named \verb-modelname-. + \item How it works : + \begin{itemize} + \item datain0 and datain1 : the two write busses. Only one is used to actually write the FIFO, it is selected by the sel signal. + \item sel : when set to \verb-zero- the datain0 is used to write the register word, otherwise it will be datain1. + \item r, rok : set r when a word is requested, rok tells that a word has effectively been popped (rok == not empty). + \item w, wok : set w when a word is pushed, wok tells that the word has effectively been pushed (wok == not full). + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item ck : clock signal (input, 1 bit) + \item reset : reset signal (input, 1 bit) + \item r : read requested (input, 1 bit) + \item w : write requested (input, 1 bit) + \item rok : read acknowledge (output, 1 bit) + \item wok : write acknowledge (output, 1 bit) + \item sel : select the write bus (input, 1 bit) + \item datain0 : first write bus (input, \verb-n- bits) + \item datain1 : second write bus (input, \verb-n- bits) + \item dataout : read bus (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the words (even, between 2 and 64) + \item nword : Defines the number of words (even, between 4 and 32) + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + global nbit, nword + nbit = 4 + nword = 16 + + def Interface ( self ) : + + self._ck = LogicIn ( "ck", 1 ) + self._reset = LogicIn ( "reset", 1 ) + self._r = LogicIn ( "r", 1 ) + self._w = LogicIn ( "w", 1 ) + self._rok = LogicInOut ( "rok", 1 ) + self._wok = LogicInOut ( "wok", 1 ) + self._sel = LogicIn ( "sel", 1 ) + + self._datain0 = LogicIn ( "datain0", nbit ) + self._datain1 = LogicIn ( "datain1", nbit ) + self._dataout = LogicOut ( "dataout", nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenFifo' + , param = { 'nword' : nword + , 'nbit' : nbit + } + , map = { 'ck' : self._ck + , 'reset' : self._reset + , 'r' : self._r + , 'w' : self._w + , 'rok' : self._rok + , 'wok' : self._wok + , 'sel' : self._sel + , 'datain0' : self._datain0 + , 'datain1' : self._datain1 + , 'dataout' : self._dataout + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgeninv.tex b/stratus1/doc/man_dpgeninv.tex new file mode 100644 index 00000000..5198b454 --- /dev/null +++ b/stratus1/doc/man_dpgeninv.tex @@ -0,0 +1,45 @@ +\begin{itemize} + \item Name : DpgenInv -- Inverter Macro-Generator + \item Description : Generates a \verb-n- bits inverter with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1, 2, 4 or 8 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item \verb-i0- : input (\verb-n- bits) + \item \verb-nq- : output (\verb-n- bits) + \item \verb-vdd- : power + \item \verb-vss- : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenInv' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenmux2.tex b/stratus1/doc/man_dpgenmux2.tex new file mode 100644 index 00000000..1f0f6cf1 --- /dev/null +++ b/stratus1/doc/man_dpgenmux2.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenMux2 -- Multiplexer Macro-Generator + \item Description : Generates a \verb-n- bits two inputs multiplexer with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : select ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item i1 : input ( \verb-n- bits ) + \item q : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item nbit\_cmd : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= WITH cmd SELECT i0 WHEN '0', + i1 WHEN '1'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenMux2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennand2.tex b/stratus1/doc/man_dpgennand2.tex new file mode 100644 index 00000000..2dfaf8fd --- /dev/null +++ b/stratus1/doc/man_dpgennand2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenNand2 -- Nand2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs NAND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 and i1 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNand2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennand2mask.tex b/stratus1/doc/man_dpgennand2mask.tex new file mode 100644 index 00000000..5a228ae3 --- /dev/null +++ b/stratus1/doc/man_dpgennand2mask.tex @@ -0,0 +1,55 @@ +\begin{itemize} + \item Name : DpgenNand2mask -- Programmable Mask Macro-Generator + \item Description : Generates a \verb-n- bits conditionnal NAND mask named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item if the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{ANDed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : mask control ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item nq : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item const : Defines the constant + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 and X"0000FFFF") WHEN '1'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 8 ) + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = LogicOut ( "out", 8 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNand2mask' + , param = { 'nbit' : 8 + , 'const' : "0b000111" + } + , map = { 'i0' : self._in + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennand3.tex b/stratus1/doc/man_dpgennand3.tex new file mode 100644 index 00000000..c8fa1fd1 --- /dev/null +++ b/stratus1/doc/man_dpgennand3.tex @@ -0,0 +1,51 @@ +\begin{itemize} + \item Name : DpgenNand3 -- Nand3 Macro-Generator + \item Description : Generates a \verb-n- bits three inputs NAND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 and i1 and i2 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNand3' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennand4.tex b/stratus1/doc/man_dpgennand4.tex new file mode 100644 index 00000000..3880243a --- /dev/null +++ b/stratus1/doc/man_dpgennand4.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenNand4 -- Nand4 Macro-Generator + \item Description : Generates a \verb-n- bits four inputs NAND with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item i3 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 and i1 and i2 and i3 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + self._in3 = LogicIn ( "in3", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNand4' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'i3' : self._in3 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennbuse.tex b/stratus1/doc/man_dpgennbuse.tex new file mode 100644 index 00000000..f2882a14 --- /dev/null +++ b/stratus1/doc/man_dpgennbuse.tex @@ -0,0 +1,46 @@ +\begin{itemize} + \item Name : DpgenNbuse -- Tristate Macro-Generator + \item Description : Generates a \verb-n- bits tristate with an complemented output named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item cmd : select ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item nq : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} + \item Behavior : +\begin{verbatim} +nts:BLOCK(cmd = '1') BEGIN + nq <= GUARDED not(i0); +END +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 32 ) + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = TriState ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNbuse' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennmux2.tex b/stratus1/doc/man_dpgennmux2.tex new file mode 100644 index 00000000..bb7ddd76 --- /dev/null +++ b/stratus1/doc/man_dpgennmux2.tex @@ -0,0 +1,55 @@ +\begin{itemize} + \item Name : DpgenNmux2 -- Multiplexer Macro-Generator +% \item Description : Generates a \verb-n- bits two inputs multiplexer with an output power of \verb-drive- named \verb-modelname-. + \item Description : Generates a \verb-n- bits two inputs multiplexer named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : select ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item i1 : input ( \verb-n- bits ) + \item nq : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item nbit\_cmd : Defines the size of the generator +% \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= WITH cmd SELECT not i0 WHEN '0', + not i1 WHEN '1'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNmux2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennor2.tex b/stratus1/doc/man_dpgennor2.tex new file mode 100644 index 00000000..f9501895 --- /dev/null +++ b/stratus1/doc/man_dpgennor2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenNor2 -- Nor2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs NOR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 or i1 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNor2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennor2mask.tex b/stratus1/doc/man_dpgennor2mask.tex new file mode 100644 index 00000000..34394014 --- /dev/null +++ b/stratus1/doc/man_dpgennor2mask.tex @@ -0,0 +1,55 @@ +\begin{itemize} + \item Name : DpgenNor2mask -- Programmable Mask Macro-Generator + \item Description : Generates a \verb-n- bits conditionnal NOR mask named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item if the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{ORed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : mask control ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item nq : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item const : Defines the constant + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 or X"0000FFFF") WHEN '1'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 8 ) + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = LogicOut ( "out", 8 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNor2mask' + , param = { 'nbit' : 8 + , 'const' : "0b000111" + } + , map = { 'i0' : self._in + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennor3.tex b/stratus1/doc/man_dpgennor3.tex new file mode 100644 index 00000000..caa845a0 --- /dev/null +++ b/stratus1/doc/man_dpgennor3.tex @@ -0,0 +1,51 @@ +\begin{itemize} + \item Name : DpgenNor3 -- Nor3 Macro-Generator + \item Description : Generates a \verb-n- bits three inputs NOR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 or i1 or i2 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNor3' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennor4.tex b/stratus1/doc/man_dpgennor4.tex new file mode 100644 index 00000000..a7a3f0bb --- /dev/null +++ b/stratus1/doc/man_dpgennor4.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenNor4 -- Nor4 Macro-Generator + \item Description : Generates a \verb-n- bits four inputs NOR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item i3 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 or i1 or i2 or i3 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + self._in3 = LogicIn ( "in3", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNor4' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'i3' : self._in3 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgennul.tex b/stratus1/doc/man_dpgennul.tex new file mode 100644 index 00000000..be68a6b6 --- /dev/null +++ b/stratus1/doc/man_dpgennul.tex @@ -0,0 +1,41 @@ +\begin{itemize} + \item Name : DpgenNul -- Zero Detector Macro-Generator + \item Description : Generates a \verb-n- bits zero detector named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item i0 : value to check (input, \verb-n- bits) + \item q : null flag (1 bit) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} + \item Behavior : +\begin{verbatim} +q <= '1' WHEN ( i0 = X"00000000" ) ELSE '0'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 32 ) + + self._out = LogicOut ( "out", 1 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenNul' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in + , 'nul' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenor2.tex b/stratus1/doc/man_dpgenor2.tex new file mode 100644 index 00000000..5fbe5bef --- /dev/null +++ b/stratus1/doc/man_dpgenor2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenOr2 -- Or2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs OR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 or i1 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenOr2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenor3.tex b/stratus1/doc/man_dpgenor3.tex new file mode 100644 index 00000000..6c99bfd6 --- /dev/null +++ b/stratus1/doc/man_dpgenor3.tex @@ -0,0 +1,51 @@ +\begin{itemize} + \item Name : DpgenOr3 -- Or3 Macro-Generator + \item Description : Generates a \verb-n- bits three inputs OR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 or i1 or i2 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenOr3' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenor4.tex b/stratus1/doc/man_dpgenor4.tex new file mode 100644 index 00000000..ceb6e381 --- /dev/null +++ b/stratus1/doc/man_dpgenor4.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenOr4 -- Or4 Macro-Generator + \item Description : Generates a \verb-n- bits four inputs OR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 2 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item i2 : input (\verb-n- bits) + \item i3 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 or i1 or i2 or i3 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + self._in2 = LogicIn ( "in2", 32 ) + self._in3 = LogicIn ( "in3", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenOr4' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'i2' : self._in2 + , 'i3' : self._in3 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenram.tex b/stratus1/doc/man_dpgenram.tex new file mode 100644 index 00000000..45b7c58d --- /dev/null +++ b/stratus1/doc/man_dpgenram.tex @@ -0,0 +1,56 @@ +\begin{itemize} + \item Name : DpgenRam -- RAM Macro-Generator + \item Description : Generates a RAM of \verb-regNumber- words of \verb-n- bits named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item ck : clock signal (input, 1 bit) + \item w : write requested (input, 1 bit) + \item selram : select the write bus (input, 1 bit) + \item ad : the address (input, \verb-Y- bits) + \item datain : write bus (input, \verb-n- bits) + \item dataout : read bus (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item nword : Defines the size of the words + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._ck = LogicIn ( "ck", 1 ) + self._w = LogicIn ( "w", 1 ) + self._selram = LogicIn ( "selram", 1 ) + + self._ad = LogicIn ( "ad", 5 ) + self._datain = LogicIn ( "datain", 32 ) + + self._dataout = TriState ( "dataout", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenRam' + , param = { 'nword' : 32 + , 'nbit' : 32 + } + , map = { 'ck' : self._ck + , 'w' : self._w + , 'selram' : self._selram + , 'ad' : self._ad + , 'datain' : self._datain + , 'dataout' : self._dataout + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenrf1.tex b/stratus1/doc/man_dpgenrf1.tex new file mode 100644 index 00000000..7b332c1d --- /dev/null +++ b/stratus1/doc/man_dpgenrf1.tex @@ -0,0 +1,70 @@ +\begin{itemize} + \item Name : DpgenRf1, DpgenRf1r0 -- Register File Macro-Generator + \item Description : Generates a register file of \verb-regNumber- words of \verb-n- bits without decoder named \verb-modelname-. + \item How it works : + \begin{itemize} + \item datain0 and datain1 are the two write busses. Only one is used to actually write the register word, it is selected by the sel signal. + \item when sel is set to zero datain0 is used to write the register word, otherwise it will be datain1 + \item selr, selw : this register file have no decoder, so selr have a bus width equal to \verb-regNumber-. One bit for each word + \item The DpgenRf1r0 variant differs from the DpgenRf1 in that the register of address zero is stuck to zero. You can write into it, it will not change the value. When read, it will always return zero + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item ckok : clock signal (input, 1 bit) + \item sel : select the write bus (input, 1 bit) + \item selr : the decoded read address (input, \verb-regNumber- bits) + \item selw : the decoded write address (input, \verb-regNumber- bits) + \item datain0 : first write bus (input, \verb-n- bits) + \item datain1 : second write bus (input, \verb-n- bits) + \item dataout : read bus (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the words (even, between 2 and 64) + \item nword : Defines the number of the words (even, between 4 and 32) + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + + def Interface ( self ) : + + self.nbit = self._param['nbit'] + self.nword = self._param['nword'] + + self._ck = LogicIn ( "ck", 1 ) + self._sel = LogicIn ( "sel", 1 ) + + self._selr = LogicIn ( "selr", self.nword ) + self._selw = LogicIn ( "selw", self.nword ) + self._datain0 = LogicIn ( "datain0", self.nbit ) + self._datain1 = LogicIn ( "datain1", self.nbit ) + self._dataout = LogicOut ( "dataout", self.nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenRf1' + , param = { 'nword' : self.nword + , 'nbit' : self.nbit + } + , map = { 'ck' : self._ck + , 'sel' : self._sel + , 'selr' : self._selr + , 'selw' : self._selw + , 'datain0' : self._datain0 + , 'datain1' : self._datain1 + , 'dataout' : self._dataout + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenrf1d.tex b/stratus1/doc/man_dpgenrf1d.tex new file mode 100644 index 00000000..705cdd9b --- /dev/null +++ b/stratus1/doc/man_dpgenrf1d.tex @@ -0,0 +1,81 @@ +\begin{itemize} + \item Name : DpgenRf1d, DpgenRf1dr0 -- Register File with Decoder Macro-Generator + \item Description : Generates a register file of \verb-regNumber- words of \verb-n- bits with decoder named \verb-modelname-. + \item How it works : + \begin{itemize} + \item datain0 and datain1 are the two write busses. Only one is used to actually write the register word, it is selected by the sel signal. + \item when sel is set to zero datain0 is used to write the register word, otherwise it will be datain1 + \item adr, adw : the width (Y) of those signals is computed from regNumber : \verb-Y = log2(regNumber)- + \item wen and ren : write enable and read enable, allows reading and writing when sets to \verb-one- + \item The DpgenRf1dr0 variant differs from the DpgenRf1d in that the register of address zero is stuck to zero. You can write into it, it will not change the value. When read, it will always return zero + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item ck : clock signal (input, 1 bit) + \item sel : select the write bus (input, 1 bit) + \item wen : write enable (input, 1 bit) + \item ren : read enable (input, 1 bit) + \item adr : the read address (input, \verb-Y- bits) + \item adw : the write address (input, \verb-Y- bits) + \item datain0 : first write bus (input, \verb-n- bits) + \item datain1 : second write bus (input, \verb-n- bits) + \item dataout : read bus (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the words (even, between 2 and 64) + \item nword : Defines the number of the words (even, between 6 and 32) + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + + def Interface ( self ) : + self.nbit = self._param['nbit'] + self.nword = self._param['nword'] + + adrange = 2 + if self.nword > 4 : adrange = 3 + if self.nword > 8 : adrange = 4 + if self.nword > 16 : adrange = 5 + + self._ck = LogicIn ( "ck", 1 ) + self._sel = LogicIn ( "sel", 1 ) + self._wen = LogicIn ( "wen", 1 ) + self._ren = LogicIn ( "ren", 1 ) + + self._adr = LogicIn ( "adr", adrange ) + self._adw = LogicIn ( "adw", adrange ) + self._datain0 = LogicIn ( "datain0", self.nbit ) + self._datain1 = LogicIn ( "datain1", self.nbit ) + self._dataout = LogicOut ( "dataout", self.nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenRf1d' + , param = { 'nword' : self.nword + , 'nbit' : self.nbit + } + , map = { 'ck' : self._ck + , 'sel' : self._sel + , 'wen' : self._wen + , 'ren' : self._ren + , 'adr' : self._adr + , 'adw' : self._adw + , 'datain0' : self._datain0 + , 'datain1' : self._datain1 + , 'dataout' : self._dataout + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenrom2.tex b/stratus1/doc/man_dpgenrom2.tex new file mode 100644 index 00000000..15c9d746 --- /dev/null +++ b/stratus1/doc/man_dpgenrom2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenRom2 -- 2 words ROM Macro-Generator + \item Description : Generates a \verb-n- bits 2 words optimized ROM named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item sel0 : address of the value (input, 1 bit) + \item q : the selected word (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item val0 : Defines the first word + \item val1 : Defines the second word + \end{itemize} + \item Behavior : +\begin{verbatim} +q <= WITH sel0 SELECT + contsVal0 WHEN B"0", + constVal1 WHEN B"1"; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._sel0 = LogicIn ( "sel0", 1 ) + + self._q = LogicOut ( "dataout", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenRom2' + , param = { 'val0' : "0b1010" + , 'val1' : "0b1100" + , 'nbit' : 4 + } + , map = { 'sel0' : self._sel0 + , 'q' : self._q + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenrom4.tex b/stratus1/doc/man_dpgenrom4.tex new file mode 100644 index 00000000..ddec0d67 --- /dev/null +++ b/stratus1/doc/man_dpgenrom4.tex @@ -0,0 +1,56 @@ +\begin{itemize} + \item Name : DpgenRom4 -- 4 words ROM Macro-Generator + \item Description : Generates a \verb-n- bits 4 words optimized ROM named \verb-modelname-. + \item Terminal Names : + \begin{itemize} + \item sel1 : upper bit of the address of the value (input, 1 bit) + \item sel0 : lower bit of the address of the value (input, 1 bit) + \item q : the selected word (output, \verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item val0 : Defines the first word + \item val1 : Defines the second word + \item val0 : Defines the third word + \item val1 : Defines the fourth word + \end{itemize} + \item Behavior : +\begin{verbatim} +q <= WITH sel1 & sel0 SELECT contsVal0 WHEN B"00", + contsVal1 WHEN B"01", + contsVal2 WHEN B"10", + constVal3 WHEN B"11"; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._sel0 = LogicIn ( "sel0", 1 ) + self._sel1 = LogicIn ( "sel1", 1 ) + + self._q = LogicOut ( "dataout", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenRom4' + , param = { 'val0' : "0b1010" + , 'val1' : "0b1100" + , 'val2' : "0b1111" + , 'val3' : "0b0001" + , 'nbit' : 4 + } + , map = { 'sel0' : self._sel0 + , 'sel1' : self._sel1 + , 'q' : self._q + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgensff.tex b/stratus1/doc/man_dpgensff.tex new file mode 100644 index 00000000..5e229161 --- /dev/null +++ b/stratus1/doc/man_dpgensff.tex @@ -0,0 +1,50 @@ +\begin{itemize} + \item Name : DpgenSff -- Static Flip-Flop Macro-Generator + \item Description : Generates a n bits static flip-flop named \verb-modelname-. The two latches of this flip-flop are static, i.e. each one is made of two interters looped together. + \item How it works : + \begin{itemize} + \item when wen is set to \verb-one-, enables the writing of the flip-flop + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item wen : write enable (1 bit) + \item ck : clock signal (1 bit) + \item i0 : data input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._ck = LogicIn ( "ck", 1 ) + self._wen = LogicIn ( "wen", 1 ) + self._in = LogicIn ( "in", 4 ) + + self._out = LogicOut ( "out", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenSff' + , param = { 'nbit' : 4 } + , map = { "wen" : self._wen + , "ck" : self._ck + , "i0" : self._in + , "q" : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgensfft.tex b/stratus1/doc/man_dpgensfft.tex new file mode 100644 index 00000000..c87cce5f --- /dev/null +++ b/stratus1/doc/man_dpgensfft.tex @@ -0,0 +1,58 @@ +\begin{itemize} + \item Name : DpgenSfft -- Static Flip-Flop with Scan-Path Macro-Generator + \item Description : Generates a n bits static flip-flop with scan-path named \verb-modelname-. The two latches of this flip-flop are static i.e. each one is made of two interters looped togethers. + \item How it works : + \begin{itemize} + \item scan : when set to \verb-one- enables the scan-path mode. Note that in scan-path mode, the wen signal is not effective + \item scin : the input of the scan-path. This terminal is different from \verb-i0[0]-. The scout is verb-q[N-i1] (in the following example this is \verb-q[31]-) + \item when wen is set to \verb-one- enables the writing of the flip-flop + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item scan : scan-path mode (input, 1 bit) + \item scin : scan path in (input, 1 bit) + \item wen : write enable (1 bit) + \item ck : clock signal (1 bit) + \item i0 : data input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +% \begin{verbatim} +% \end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._scan = LogicIn ( "scin", 1 ) + self._scin = LogicIn ( "scan", 1 ) + self._ck = LogicIn ( "ck", 1 ) + self._wen = LogicIn ( "wen", 1 ) + self._in = LogicIn ( "in", 4 ) + + self._out = LogicOut ( "out", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenSfft' + , param = { 'nbit' : 4 } + , map = { "wen" : self._wen + , "ck" : self._ck + , "scan" : self._scan + , "scin" : self._scin + , "i0" : self._in + , "q" : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenshift.tex b/stratus1/doc/man_dpgenshift.tex new file mode 100644 index 00000000..22d67640 --- /dev/null +++ b/stratus1/doc/man_dpgenshift.tex @@ -0,0 +1,54 @@ +\begin{itemize} + \item Name : DpgenShift -- Shifter Macro-Generator + \item Description : Generates a \verb-n- bits shifter named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-op[0]- signal is set to \verb-one-, performs a right shift, performs a left shift otherwise. + \item if the \verb-op[1]- signal is set to \verb-one-, performs an arithmetic shift (only meaningful in case of a right shift). + \item \verb-shamt- specifies the shift amount. The width of this signal (\verb-Y-) is computed from the operator's width : \verb-Y = ceil(log2(n)) -- 1 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item op : select the kind of shift (input, 2 bits) + \item shamt : the shift amount (input, \verb-Y- bits) + \item i : value to shift (input, \verb-n- bits) + \item o : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._instop = LogicIn ( "instop", 2 ) + + self._instshamt = LogicIn ( "instshamt", 2 ) + + self._insti = LogicIn ( "insti", 4 ) + + self._insto = LogicOut ( "insto", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenShifter' + , param = { 'nbit' : 4 } + , map = { 'op' : self._instop + , 'shamt' : self._instshamt + , 'i' : self._insti + , 'o' : self._insto + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenshrot.tex b/stratus1/doc/man_dpgenshrot.tex new file mode 100644 index 00000000..5d6a8f7a --- /dev/null +++ b/stratus1/doc/man_dpgenshrot.tex @@ -0,0 +1,55 @@ +\begin{itemize} + \item Name : DpgenShrot -- Shift/Rotation Macro-Generator + \item Description : Generates a \verb-n- bits shift/rotation operator named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-op[0]- signal is set to \verb-one-, performs a right shift/rotation , otherwise left shift/rotation occurs. + \item if the \verb-op[1]- signal is set to \verb-one-, performs an arithmetic shift (only meaningful in case of a right shift). + \item if the \verb-op[2]- signal is set to \verb-one-, performs a rotation, otherwise performs a shift.. + \item \verb-shamt- specifies the shift amount. The width of this signal (\verb-Y-) is computed from the operator's width : \verb-Y = ceil(log2(n)) -- 1 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item op : select the kind of shift/rotation (input, 3 bits) + \item shamt : the shift amount (input, \verb-Y- bits) + \item i : value to shift (input, \verb-n- bits) + \item o : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \end{itemize} +% \item Behavior : +%\begin{verbatim} +%\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._rotop = LogicIn ( "rotop", 3 ) + + self._instshamt = LogicIn ( "instshamt", 3 ) + + self._insti = LogicIn ( "insti", 8 ) + + self._insto = LogicOut ( "insto", 8 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenShrot' + , param = { 'nbit' : 8 } + , map = { 'op' : self._rotop + , 'shamt' : self._instshamt + , 'i' : self._insti + , 'o' : self._insto + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenxnor2.tex b/stratus1/doc/man_dpgenxnor2.tex new file mode 100644 index 00000000..318d56ae --- /dev/null +++ b/stratus1/doc/man_dpgenxnor2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenXnor2 -- Xnor2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs XNOR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item nq : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= not ( i0 xor i1 ) +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenXnor2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenxnor2mask.tex b/stratus1/doc/man_dpgenxnor2mask.tex new file mode 100644 index 00000000..f884e9f3 --- /dev/null +++ b/stratus1/doc/man_dpgenxnor2mask.tex @@ -0,0 +1,55 @@ +\begin{itemize} + \item Name : DpgenXnor2mask -- Programmable Mask Macro-Generator + \item Description : Generates a \verb-n- bits conditionnal XNOR mask named \verb-modelname-. + \item How it works : + \begin{itemize} + \item if the \verb-cmd- signal is set to \verb-zero-, the mask is NOT applied, so the whole operator behaves like an inverter. + \item if the \verb-cmd- signal is set to \verb-one-, the mask is applied, the output is the \emph{complemented} result of the input value \emph{XORed} with the mask (suplied by \verb-constVal-). + \item The constant \verb-constVal- is given to the macro-generator call, therefore the value cannot be changed afterward : it's hard wired in the operator. + \item A common error is to give a real constant for the \verb-constVal- argument. Be aware that it is a character string. + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item cmd : mask control ( 1 bit ) + \item i0 : input ( \verb-n- bits ) + \item nq : output ( \verb-n- bits ) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item const : Defines the constant + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= WITH cmd SELECT not(i0) WHEN '0', + not(i0 xor X"0000FFFF") WHEN '1'; +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in = LogicIn ( "in", 8 ) + self._cmd = LogicIn ( "cmd", 1 ) + + self._out = LogicOut ( "out", 8 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenXnor2mask' + , param = { 'nbit' : 8 + , 'const' : "0b000111" + } + , map = { 'i0' : self._in + , 'cmd' : self._cmd + , 'nq' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_dpgenxor2.tex b/stratus1/doc/man_dpgenxor2.tex new file mode 100644 index 00000000..f1244f59 --- /dev/null +++ b/stratus1/doc/man_dpgenxor2.tex @@ -0,0 +1,48 @@ +\begin{itemize} + \item Name : DpgenXor2 -- Xor2 Macro-Generator + \item Description : Generates a \verb-n- bits two inputs XOR with an output power of \verb-drive- named \verb-modelname-. + \begin{itemize} + \item Valid drive are : 1 or 4 + \end{itemize} + \item Terminal Names : + \begin{itemize} + \item i0 : input (\verb-n- bits) + \item i1 : input (\verb-n- bits) + \item q : output (\verb-n- bits) + \item vdd : power + \item vss : ground + \end{itemize} + \item Parameters : Parameters are given with a map called \verb-param-. + \begin{itemize} + \item nbit : Defines the size of the generator + \item drive (optional) : Defines the output power of the gates\\If this parameter is not defined, the \verb-drive- is the smallest one permitted. + \end{itemize} + \item Behavior : +\begin{verbatim} +nq <= i0 xor i1 +\end{verbatim} + \item Example : +\begin{verbatim} +class myClass ( Model ) : + def Interface ( self ) : + self._in0 = LogicIn ( "in0", 32 ) + self._in1 = LogicIn ( "in1", 32 ) + + self._out = LogicOut ( "out", 32 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + Inst ( 'DpgenXor2' + , param = { 'nbit' : 32 } + , map = { 'i0' : self._in0 + , 'i1' : self._in1 + , 'q' : self._out + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +\end{verbatim} +\end{itemize} diff --git a/stratus1/doc/man_example.tex b/stratus1/doc/man_example.tex new file mode 100644 index 00000000..c2baee39 --- /dev/null +++ b/stratus1/doc/man_example.tex @@ -0,0 +1,63 @@ +\subsubsection{Addaccu circuit} + +\begin{figure}[h!] +\centering +\includegraphics[width=.9\textwidth]{images/add1.png} +\end{figure} + +\newpage + +\subsubsection{Data-path} + +\begin{figure}[h!] +\centering +\includegraphics[width=.9\textwidth]{images/add2.png} +\end{figure} + +\subsubsection{Description of the circuit with \emph{Stratus}} + +\begin{figure}[hbp] +\centering +\includegraphics[width=1.2\textwidth]{images/addaccu.png} +\end{figure} + +\newpage + +\subsubsection{Creation of the circuit} + +\begin{figure}[hbp] +\centering +\includegraphics[width=1.3\textwidth]{images/test.png} +\end{figure} + +%\newpage + +\subsubsection{How to execute the file} + +\begin{verbatim} +python test.py -n 4 +\end{verbatim} +\indent or : +\begin{verbatim} +chmod u+x test.py +./test -n 4 +\end{verbatim} + +\subsubsection{The editor} + +The method \verb-View- permits to open an editor in which one can see the cell being created as shown in the picture below. +\begin{figure}[hbp] +\centering +\includegraphics[width=1\textwidth]{images/editor.png} +\end{figure} + + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Stratus}}{}{Stratus}{secstratus} +\hyperref[ref]{\emph{Model}}{}{Model}{secmodel} +\hyperref[ref]{\emph{Param}}{}{Param}{secparam} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/doc/man_extend.tex b/stratus1/doc/man_extend.tex new file mode 100644 index 00000000..4eab429e --- /dev/null +++ b/stratus1/doc/man_extend.tex @@ -0,0 +1,52 @@ +\subsubsection{Name} + +Extend -- Extention of nets + +\subsubsection{Synopsys} + +\begin{verbatim} +extendA = Signal ( "extend_a", 32 ) + +extendA <= netA.Extend ( 32, 'zero' ) +\end{verbatim} + +\subsubsection{Description} + +This method creates a net which is an extension of the net which it is applied to. The number given as parameter has to be greater than the arity of the net. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-n- : the number which is the arity of the net + \item \verb-type- : the type of the extension + \begin{itemize} + \item 'zero' : the extension nets are set to zero + \item 'one' : the extension nets are set to one + \item 'signed' : the extension nets are set thanks to the value of the msb bit + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +temp = Signal ( "temp", 5 ) +tempExt = Signal ( "temp_ext", 8 ) + +tempExt <= temp.Extand ( 8, 'one' ) +\end{verbatim} + +\indent The arity of the net \verb-tempExt- is 8 and 3 MSB of the net are "1". + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Extend :-\\\verb-the net can not be extended to n bits, it's arity is already m.-\\The number one wants must be greater than the arity of the net. Otherwise, the net can not be extended. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Nets}}{}{Nets}{secnet} +\hyperref[ref]{\emph{Alias}}{}{Alias}{secalias} +\hyperref[ref]{\emph{Cat}}{}{Cat}{seccat} diff --git a/stratus1/doc/man_fill_cell.tex b/stratus1/doc/man_fill_cell.tex new file mode 100644 index 00000000..6c4c5b8b --- /dev/null +++ b/stratus1/doc/man_fill_cell.tex @@ -0,0 +1,44 @@ +\subsubsection{Name} + +FillCell -- Automatic placement of ties. + +\subsubsection{Synopsys} + +\begin{verbatim} +FillCell ( cell ) +\end{verbatim} + +\subsubsection{Description} + +This function places automatically ties. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-cell- : the cell which the fonction is applied to +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%FillCell ( core ) +%\end{verbatim} +% +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] FillCell : Given cell doesn't exist.-\\The argument is wrong. Check if one has created the cell correctly. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_generators.tex b/stratus1/doc/man_generators.tex new file mode 100644 index 00000000..5a511c48 --- /dev/null +++ b/stratus1/doc/man_generators.tex @@ -0,0 +1,82 @@ +\subsubsection{Description} + +One can create a generator and instantiate it in another generator.\\ +\indent To do that, the name given when instantiating the generator must have the form : "file\_name.class\_name".\\ + +\indent Note that if the two generators are not in the same directory, the directory of the generator to be instantiated has to be added in the CRL\_CATA\_LIB environment variable. + +\subsubsection{Example} + +\begin{itemize} + \item File describing the generator which is going to instanciated later : +\end{itemize} + +\begin{verbatim} +#!/usr/bin/python + +from stratus import * + +class class_function ( Model ) : + + def Interface ( self ) : + self.n = self._param['nbit'] + + self._A = LogicIn ( "a", self.n ) + self._B = LogicIn ( "b", self.n ) + self._C = LogicIn ( "c", self.n ) + + self._S = LogicOut ( "s", self.n ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + self._S <= ( self._A | self._B ) & self._C +\end{verbatim} + +\begin{itemize} + \item File instanciating the generator : +\end{itemize} + +\begin{verbatim} +#!/usr/bin/python + +from stratus import * + +class mycell ( Model ) : + + def Interface ( self ) : + self._in1 = LogicIn ( "in1", 4 ) + self._in2 = LogicIn ( "in2", 4 ) + self._in3 = LogicIn ( "in3", 4 ) + + self._out = LogicOut ( "out", 4 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + temp = Signal ( "temp", 4 ) + + Inst ( "myfunc.class_function" + , param = { 'nbit' : 4 } + , map = { 'a' : self._in1 + , 'b' : self._in2 + , 'c' : self._in3 + , 's' : temp + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self._out <= ~temp +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Inst : the model ... does not exist.-\\\verb-Check CRL_CATA_LIB.-\\One has to check the environment variable because the model is not found. +\end{itemize} + +\input{see_also} diff --git a/stratus1/doc/man_inst.tex b/stratus1/doc/man_inst.tex new file mode 100644 index 00000000..f2292d3c --- /dev/null +++ b/stratus1/doc/man_inst.tex @@ -0,0 +1,56 @@ +\subsubsection{Name} + +Inst -- Creation of instances + +\subsubsection{Synopsys} + +\begin{verbatim} +Inst ( model + , name + , param + , map + ) +\end{verbatim} + +\subsubsection{Description} + +Instantiation of an instance. The type of the instance is given by the \verb-model- parameter. The connexions are made thanks to the \verb-map- parameters. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-Model- : Name of the mastercell of the instance to create (mandatory argument) + \item \verb-name- : Name of the instance (optional)\\ +When this argument is not defined, the instance has a name created by default. This argument is usefull when one wants to create a layout as well. Indeed, the placement of the instances is much easier when the conceptor has chosen himself the name f the instances. + \item \verb-param- : Arguments of the mastercell (optional : only for mastercells which require it) + \item \verb-map- : Connexions in order to make the netlist\\ +\end{itemize} +\indent \verb-param- and \verb-map- are dictionnaries as shown in the example below. + +\subsubsection{Example} + +\begin{verbatim} +Inst ( 'DpgenAnd2' + , param = { 'nbit' : 4 + } + , map = { 'i0' : in0 + , 'i1' : in1 + , 'q' : out + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-Error in Inst : the model Model does not exist.-\\\verb-Check CRL_CATA_LIB.-\\Either one has made a mistake in the name of the model, either the environment variable is not correct. + \item \verb-Error in Inst : port does not exist in model Model.-\\One port in map is not correct. + \item \verb-Error in Inst : one input net is not dimensionned.-\\The size of the output nets is automatically calculated bus the input nets must be dimensionned before being connected. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} diff --git a/stratus1/doc/man_library.tex b/stratus1/doc/man_library.tex new file mode 100644 index 00000000..de0dcd4d --- /dev/null +++ b/stratus1/doc/man_library.tex @@ -0,0 +1,68 @@ +\subsubsection{Description} + +All the cells that can be instantiated are listed below.\\ +\indent These cells are generators which are proportionned thanks to parameters. + +\subsubsection{List} + +\begin{itemize} + \item \verb-And2- : \verb-q <= i0 & i1- + \item \verb-And3- : \verb-q <= i0 & i1 & i2- + \item \verb-And4- : \verb-q <= i0 & i1 & i2 & i3- + \item \verb-Nand2- : \verb-nq <= ~ ( i0 & i1 )- + \item \verb-Nand3- : \verb-nq <= ~ ( i0 & i1 & i2 )- + \item \verb-Nand4- : \verb-nq <= ~ ( i0 & i1 & i2 & i3 )- + \item \verb-Or2- : \verb-q <= i0 & i1- + \item \verb-Or3- : \verb-q <= i0 & i1 & i2- + \item \verb-Or4- : \verb-q <= i0 & i1 & i2 & i3- + \item \verb-Nor2- : \verb-nq <= ~ ( i0 & i1 )- + \item \verb-Nor3- : \verb-nq <= ~ ( i0 & i1 & i2 )- + \item \verb-Nor4- : \verb-nq <= ~ ( i0 & i1 & i2 & i3 )- + \item \verb-Inv- : \verb-nq <= ~ i- + \item \verb-Buf- : \verb-q <= i- + \item \verb-Xor2- : \verb-q <= i0 ^ i1- + \item \verb-Nxor2- : \verb-nq <= ~ ( i0 ^ i1 )- + \item \verb-Zero- : \verb-nq <= '0'- + \item \verb-One- : \verb-q <= '1'- + \item \verb-Halfadder- : \verb-sout <= a ^ b- and \verb-cout <= a & b- + \item \verb-Fulladder- : \verb-sout <= a ^ b ^ cin-\\\indent and \verb-cout <= ( a & b ) | ( a & cin ) | ( b & cin )- + \item \verb-Sff- : \verb-if RISE ( ck ) : q <= i- +\end{itemize} + +\subsubsection{Parameters} + +The parameter \verb-'nbit'- gives the size of the generator. It is given through the dictionnary named \verb-param- (the default value is 1). + +\subsubsection{Mapping file} + +In order to map the virtual library, on has to write a .xml file which makes correspond models and interfaces. Note that the interfaces of the cells must be the same (except for the names of the ports). Otherwise, one has to create .vst files in order to make the interfaces match.\\ +\indent By default, the mapping is done with sxlib library. There is an example of the .xml file below.\\ +\indent The environment variable used to point the right file is \verb-STRATUS_MAPPING_NAME-. +\begin{figure}[hbp] +\centering +\includegraphics[width=1.3\textwidth]{images/xml.png} +\end{figure} + +\subsubsection{Example} + +\begin{verbatim} +Inst ( 'And2' + , param = { 'nbit' : 4 } + , map = { 'i0' : A + , 'i1' : B + , 'q' : S + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Inst : the model ... does not exist.-\\\verb-Check CRL_CATA_LIB.-\\The model of the cell has not been found. One has to check the environment variable. + \item \verb-[Stratus ERROR] Virtual library : No file found in order to parse.-\\\verb-Check STRATUS_MAPPING_NAME.-\\The mapping faile is not given in the environment variable. +\end{itemize} + +\input{see_also} diff --git a/stratus1/doc/man_model.tex b/stratus1/doc/man_model.tex new file mode 100644 index 00000000..b5ce12ff --- /dev/null +++ b/stratus1/doc/man_model.tex @@ -0,0 +1,47 @@ +\subsubsection{Name} + +Model -- Master class + +\subsubsection{Description} + +Every cell made is a class herited from class \verb-Model-.\\ +\indent Some methods have to be created, like \verb-Interface-, \verb-Netlist- ... Some methods are inherited from the class \verb-Model-. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-name- : The name of the cell (which is the name of the files which will be created) + \item \verb-param- : A dictionnary which gives all the parameters usefull in order to create the cell +\end{itemize} + +\subsubsection{Methods} + +Methods of class \verb-Model- are listed below : +\begin{itemize} + \item \verb-View- : Opens/Refreshes the editor in order to see the created layout + \item \verb-Quit- : Finishes a cell without saving + \item \verb-Save- : Saves the created cell\\If several cells have been created, they are all going to be saved in separated files\\ +\end{itemize} + +Some of those methods have to be defined in order to create a new cell : +\begin{itemize} + \item \verb-Interface- : Description of the external ports of the cell + \item \verb-Netlist- : Description of the netlist of the cell + \item \verb-Layout- : Description of the layout of the cell + \item \verb-Vbe- : Description of the behavior of the cell + \item \verb-Pattern- : Description of the patterns in order to test the cell +\end{itemize} + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Stratus}}{}{Stratus}{secstratus} +\hyperref[ref]{\emph{Param}}{}{Param}{secparam} +\hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/doc/man_mux.tex b/stratus1/doc/man_mux.tex new file mode 100644 index 00000000..441b37d4 --- /dev/null +++ b/stratus1/doc/man_mux.tex @@ -0,0 +1,131 @@ +\subsubsection{Name} + +Mux -- Easy way to instantiate a multiplexor + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCmd.Mux ( arg ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the command of the multiplexor. The nets given as parameters are all the input nets. This method returns a net : the output net.\\ +There are two ways to describe the multiplexor : the argument \verb-arg- can be a list or a dictionnary.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetMux- method. + +\subsubsection{Parameters} + +\begin{itemize} + \item List :\\ + \indent For each value of the command, the corresponding net is specified. All values must be specified.\\ + \indent For example : + \begin{verbatim} +out <= cmd.mux ( [in0, in1, in2, in3] ) + \end{verbatim} + \indent The net out is then initialised like this : + \begin{verbatim} +if cmd == 0 : out <= in0 +if cmd == 1 : out <= in1 +if cmd == 2 : out <= in2 +if cmd == 3 : out <= in3 + \end{verbatim} + \item Dictionnary :\\ + \indent A dictionnary makes the correspondance between a value of the command and the corresponding net.\\ + \indent For example : + \begin{verbatim} +out <= cmd.mux ( {"0" : in0, "1" : in1, "2" : in2, "3" : in3} ) + \end{verbatim} + \indent This initialisation corresponds to the one before. + \indent Thanks to the use of a dictionnary, the connections can be clearer : + \begin{itemize} + \item \verb-'default'-: This key of the dictionnary corresponds to all the nets that are not specified\\ + For example : + \begin{verbatim} +out <= cmd.mux ( {"0" : in0, "default" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd == 0 : out <= in0 +else : out <= in1 + \end{verbatim} + Note that if there is no \verb-'default'- key specified and that not all the nets are specified, the non specified nets are set to 0. + \item \verb-#- and \verb-?- : When a key of the dictionnary begins with \verb-#-, the number after the \verb-#- has to be binary and each ? in the number means that this bit is not precised\\ + For example : + \begin{verbatim} +out <= cmd.mux ( {"#01?" : in0, "default" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd in ( 2, 3 ) : out <= in0 +else : out <= in1 + \end{verbatim} + \item \verb-,- and \verb"-" : When keys contains thoses symbols, it permits to enumerate intervals\\ + For example : + \begin{verbatim} +out <= cmd.mux ( {"0,4" : in0, "1-3,5" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd in ( 0, 4 ) : out <= in0 +elif cmd in ( 1, 2, 3, 5) : out <= in1 +else : out <= 0 + \end{verbatim} + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + self.B = LogicIn ( "b", 4 ) + self.C = LogicIn ( "c", 4 ) + self.D = LogicIn ( "d", 4 ) + + self.Cmd1 = LogicIn ( "cmd1", 2 ) + self.Cmd2 = LogicIn ( "cmd2", 4 ) + + self.S1 = LogicOut ( "s1", 4 ) + self.S2 = LogicOut ( "s2", 4 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S1 <= self.Cmd1.Mux ( [sefl.A, self.B, self.C, self.D] ) + + self.S2 <= self.Cmd2.Mux ( { "0" : self.A + , "1,5-7" : self.B + , "#1?1?" : self.C + , "default" : self.D + } ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Mux : all the nets must have the same lenght.-\\All the input nets pust have the same lenght. + \item \verb-[Stratus ERROR] Mux : there are no input nets.-\\The input nets seem to have been forgotten. + \item \verb-[Stratus ERROR] Mux : wrong argument type.-\\The connections of the buses are not described by a list nor a dictionnary. + \item \verb-[Stratus ERROR] Mux :-\\\verb-the number of nets does not match with the lenght of the command.-\\When using a list, the number of nets has to correspond to the number of possible values of the command. + \item \verb-[Stratus ERROR] Mux : wrong key.-\\One of the key of the dictionnary is not un number, neither a list or an interval. + \item \verb-[Stratus ERROR] Mux :-\\\verb-when an interval is specified, the second number of the interval-\\\verb-must be greater than the first one.-\\When creating an interval with "-", the second number has to be greater than the first one. + \item \verb-[Stratus ERROR] Mux :-\\\verb-the binary number does not match with the lenght of the command.-\\When using the \verb-#- notation, each digit of the binary number corresponds to a wire of the cmd. The leghts have to correspond. + \item \verb-[Stratus ERROR] Mux : after #, the number has to be binary.-\\When using the \verb-#- notation, the number has to be binary : one can use 0, 1 or ?. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_net.tex b/stratus1/doc/man_net.tex new file mode 100644 index 00000000..9a85c004 --- /dev/null +++ b/stratus1/doc/man_net.tex @@ -0,0 +1,57 @@ +\subsubsection{Name} + +LogicIn, LogicOut ... -- Creation of nets + +\subsubsection{Synopsys} + +\begin{verbatim} +netA = LogicIn ( "a", 4 ) +\end{verbatim} + +\subsubsection{Description} + +How to create and use nets. + +\subsubsection{Nets} + +Differents kind of nets are listed below : +\begin{itemize} + \item \verb-LogicIn- : Creation of an input port + \item \verb-LogicOut- : Creation of an output port + \item \verb-LogicInOut- : Creation of an inout port + \item \verb-LogicUnknown- : Creation of an input/output port which direction is not defined + \item \verb-TriState- : Creation of a tristate port + \item \verb-CkIn- : Creation of a clock port + \item \verb-VddIn- : Creation of the vdd alimentation + \item \verb-VssIn- : Creation of the vss alimentation + \item \verb-Signal- : Creation of an internal net +\end{itemize} + +\subsubsection{Parameters} + +All kind of constructors have the same parameters : +\begin{itemize} + \item \verb-name- : the name of the net (mandatory argument) + \item \verb-arity- : the arity of the net (mandatory argument) + \item \verb-indice- : for buses only : the LSB bit (optional argument : set to 0 by default) +\end{itemize} + +\indent Only \verb-CkIn-, \verb-VddIn- and \verb-VssIn- do not have the same parameters : there is only the \verb-name- parameter (they are 1 bit nets). + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-Error in LogicIn :-\\\verb-the lenght of the net must be a positive value.-\\One can not create a net with a negative lenght. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Alias}}{}{Alias}{secalias} +\hyperref[ref]{\emph{Extand}}{}{Extand}{secextend} +\hyperref[ref]{\emph{Cat}}{}{Cat}{seccat} diff --git a/stratus1/doc/man_pads.tex b/stratus1/doc/man_pads.tex new file mode 100644 index 00000000..d4d83766 --- /dev/null +++ b/stratus1/doc/man_pads.tex @@ -0,0 +1,51 @@ +\subsubsection{Name} + +PadNorth, PadSouth, PadEast, PasWest -- Placement of pads at the periphery of the cell + +\subsubsection{Synopsys} + +\begin{verbatim} +PadNorth ( args ) +\end{verbatim} + +\subsubsection{Description} + +These functions place the pads given as arguments at the given side of the cell (PadNorth : up north, PadSouth : down south ...). + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-args- : List of pads to be placed +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PadSouth ( self.p_cin, self.p_np, self.p_ng, self.p_vssick0 + , self.p_vddeck0, self.p_vsseck1, self.p_vddeck1, self.p_cout + , self.p_y[0], self.p_y[1], self.p_y[2] + ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PadNorth : not enough space for all pads.-\\The abutment box is not big enough in order to place all the pads. Maybe one could put pads on other faces of the cell. + \item \verb-[Stratus ERROR] PadNorth : one instance doesn't exist.-\\One of the pads given as arguments does not exist + \item \verb-[Stratus ERROR] PadNorth : one argument is not an instance.-\\One of the pads is not one of the pads of the cell. + \item \verb-[Stratus ERROR] PadNorth : the instance ins is already placed.-\\One is tryng to place a pad twice. + \item \verb-[Stratus ERROR] PadNorth : pad ins must be closer to the center.-\\The pad name ins must ben put closer to the center in order to route the cell +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_param.tex b/stratus1/doc/man_param.tex new file mode 100644 index 00000000..1f9045ad --- /dev/null +++ b/stratus1/doc/man_param.tex @@ -0,0 +1,50 @@ +\subsubsection{Name} + +Param -- How to use parameters + +\subsubsection{Synopsys} + +\begin{verbatim} +nbit, nword = Param ( "n", "w" ) +\end{verbatim} + +\subsubsection{Description} + +This function allows the user to give parameters when creating a cell. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-args- : letters which correspond to letter typed on the shell +\end{itemize} + +\subsubsection{Example} + +When one wants to give values to two parameters, one can type on the shell : +\begin{verbatim} +python test.py -n 4 -w 8 +\end{verbatim} + +The file \verb-test.py- has then to contain : +\begin{verbatim} +nbit, nword = Param ( "n", "w" ) +\end{verbatim} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-Error in Param : there is no parameter.-\\The parameters seem to have been forgotten. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Stratus}}{}{Stratus}{secstratus} +\hyperref[ref]{\emph{Model}}{}{Model}{secmodel} +\hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/doc/man_place.tex b/stratus1/doc/man_place.tex new file mode 100644 index 00000000..a23e6843 --- /dev/null +++ b/stratus1/doc/man_place.tex @@ -0,0 +1,60 @@ +\subsubsection{Name} + +Place -- Places an instance + +\subsubsection{Synopsys} + +\begin{verbatim} +Place ( ins, sym, x, y ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist-, in order to use the \verb-Place- function. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-x-, \verb-y- : Coordinates of the lower left corner of the abutment box on the instance in the current figure. +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst, NOSYM, 0, 0 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] Place : wrong argument for placement type.-\\The symetry given as argument is not correct. + \item \verb-[Stratus ERROR] PLace : x value must be an integer or a float.-\\One of the coordinates is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_place_bottom.tex b/stratus1/doc/man_place_bottom.tex new file mode 100644 index 00000000..eaf93acd --- /dev/null +++ b/stratus1/doc/man_place_bottom.tex @@ -0,0 +1,63 @@ +\subsubsection{Name} + +PlaceBottom -- Places an instance below the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceBottom ( ins, sym, offset ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The top left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offset- (optionnal) : An offset is put between this instance and the reference instance. The value given as argument must be a multiple of PITCH and represents the lenght of the hole between the instances +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceBottom ( myInst2, SYM_Y ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceBottom : no previous instance.-\\One can use \verb-PlaceTop- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceBottom : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_place_centric.tex b/stratus1/doc/man_place_centric.tex new file mode 100644 index 00000000..a106165d --- /dev/null +++ b/stratus1/doc/man_place_centric.tex @@ -0,0 +1,46 @@ +\subsubsection{Name} + +PlaceCentric -- Placement of an instance in the middle of an abutment box + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceCentric ( ins ) +\end{verbatim} + +\subsubsection{Description} + +This function places an instance in the middle of and abutment box.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use this function. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%PlaceCentric ( core ) +%\end{verbatim} +% +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlaceCentric: the instance does not exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] PlaceCentric :-\\\verb-the instance's size is greater than this model.-\\The instance must fit in the abutment box. The abutment box may not be big enough. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_place_glu.tex b/stratus1/doc/man_place_glu.tex new file mode 100644 index 00000000..cbfe1d68 --- /dev/null +++ b/stratus1/doc/man_place_glu.tex @@ -0,0 +1,37 @@ +\subsubsection{Name} + +PlaceGlue -- Automatic placement of non placed instances + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceGlue ( cell ) +\end{verbatim} + +\subsubsection{Description} + +This function places, thanks to the automatic placer Mistral of Coriolis, all the non placed instances of the cell. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-cell- : the cell which the fonction is applied to +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%PlaceGlue ( core ) +%\end{verbatim} +% +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_place_left.tex b/stratus1/doc/man_place_left.tex new file mode 100644 index 00000000..e44b77a4 --- /dev/null +++ b/stratus1/doc/man_place_left.tex @@ -0,0 +1,63 @@ +\subsubsection{Name} + +PlaceLeft -- Places an instance at the left of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceLeft ( ins, sym, offset ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom right corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offset- (optionnal) : An offset is put between this instance and the reference instance. The value given as argument must be a multiple of PITCH and represents the width of the hole between the instances +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceLeft ( myInst2, NOSYM ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceLeft : no previous instance.-\\One can use \verb-PlaceTop- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceLeft : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_place_right.tex b/stratus1/doc/man_place_right.tex new file mode 100644 index 00000000..4aab7cff --- /dev/null +++ b/stratus1/doc/man_place_right.tex @@ -0,0 +1,63 @@ +\subsubsection{Name} + +PlaceRight -- Places an instance at the right of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceRight ( ins, sym, offset ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom right corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offset- (optionnal) : An offset is put between this instance and the reference instance. The value given as argument must be a multiple of PITCH and represents the width of the hole between the instances +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceRight ( myInst2, NOSYM ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceRight : no previous instance.-\\One can use \verb-PlaceTop- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceRight : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_place_top.tex b/stratus1/doc/man_place_top.tex new file mode 100644 index 00000000..d9d51db3 --- /dev/null +++ b/stratus1/doc/man_place_top.tex @@ -0,0 +1,63 @@ +\subsubsection{Name} + +PlaceTop -- Places an instance at the top of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceTop ( ins, sym, offset ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the top left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offset- (optionnal) : An offset is put between this instance and the reference instance. The value given as argument must be a multiple of PITCH and represents the lenght of the hole between the instances +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceTop ( myInst2, SYM_Y ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceTop : no previous instance.-\\One can use \verb-PlaceTop- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceTop : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_power_ring.tex b/stratus1/doc/man_power_ring.tex new file mode 100644 index 00000000..fcbea685 --- /dev/null +++ b/stratus1/doc/man_power_ring.tex @@ -0,0 +1,45 @@ +\subsubsection{Name} + +PowerRing -- Placement of power rings. + +\subsubsection{Synopsys} + +\begin{verbatim} +PowerRing ( nb ) +\end{verbatim} + +\subsubsection{Description} + +This function places power rings around the core and around the plots. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-nb- : Number of pair of rings vdd/vss +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PowerRing ( 3 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PowerRing : Pads in the north haven't been placed.-\\The pads of the 4 sides of the chip must be placed before calling function PowerRing. + \item \verb-[Stratus ERROR] PowerRing : too many rings, not enough space.-\\Wether The argument of PowerRing is to big, or the abutment box of the chip is to small. There's no space to put the rings. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} diff --git a/stratus1/doc/man_reg.tex b/stratus1/doc/man_reg.tex new file mode 100644 index 00000000..0af5ffcb --- /dev/null +++ b/stratus1/doc/man_reg.tex @@ -0,0 +1,51 @@ +\subsubsection{Name} + +Reg -- Easy way to instantiate a register + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCk.Reg ( netIn ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the clock of the register. The net given as parameter is the input net. The method returns a net : the output net.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetReg- method. + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + self.S = LogicOut ( "s", 4 ) + + self.Ck = CkIn ( "ck" ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= self.Ck.Reg ( self.A ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Reg : The input net does not have a positive arity.-\\The input net must have a positive arity. + \item \verb-[Stratus ERROR] Reg : The clock does not have a positive arity.-\\The clock must have a positive arity. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_resize_ab.tex b/stratus1/doc/man_resize_ab.tex new file mode 100644 index 00000000..de142d3e --- /dev/null +++ b/stratus1/doc/man_resize_ab.tex @@ -0,0 +1,49 @@ +\subsubsection{Name} + +ResizeAb -- Modifies the abutment box of the current cell + +\subsubsection{Synopsys} + +\begin{verbatim} +ResizeAb ( dx1, dy1, dx2, dy2 ) +\end{verbatim} + +\subsubsection{Description} + +This function modifies the abutment box of the current cell.\\ +\indent The coordinates of the abutment box are the coordinates of the envelop of the abutment boxes of each instance plus the delta values given as argument.\\ + +\indent Note that one can not call this function in order to create the abutment box. This fonction only modifies the already created abutment box. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-(dx1, dy1)- : Values to be added to the lower left corner of the previous abutment box. + \item \verb-(dx2, dy2)- : Values to be added to the upper right corner of the previous abutment box. +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( Inv, NOSYM, 0, 0 ) + +ResizeAb ( 0, -100, 0, 100 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb- [Stratus ERROR] ResizeAb :-\\\verb-Coordinates of an abutment Box in y must be multiple of the slice.-\\\verb-Coordinates of an abutment Box in x must be multiple of the pitch.-\\One has called ResizeAb with non authorized values +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} diff --git a/stratus1/doc/man_route_ck.tex b/stratus1/doc/man_route_ck.tex new file mode 100644 index 00000000..1868ccd4 --- /dev/null +++ b/stratus1/doc/man_route_ck.tex @@ -0,0 +1,45 @@ +\subsubsection{Name} + +RouteCk -- Routing of signal Ck to standard cells + +\subsubsection{Synopsys} + +\begin{verbatim} +RouteCk ( net ) +\end{verbatim} + +\subsubsection{Description} + +This function routes signal Ck to standard cells. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : the net which the fonction is applied to +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%netCk = LogicIn ( "ck", 1 ) +%RouteCk ( netCk ) +%\end{verbatim} +% +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] RouteCk : Pads in the north haven't been placed-\\The pads must be placed before calling RoutageCk. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} diff --git a/stratus1/doc/man_set_ref_ins.tex b/stratus1/doc/man_set_ref_ins.tex new file mode 100644 index 00000000..404f4287 --- /dev/null +++ b/stratus1/doc/man_set_ref_ins.tex @@ -0,0 +1,53 @@ +\subsubsection{Name} + +SetRefIns -- Defines the new "reference instance" for placement + +\subsubsection{Synopsys} + +\begin{verbatim} +SetRefIns ( ins ) +\end{verbatim} + +\subsubsection{Description} + +This function defines the new "reference instance", used as starting point in the relative placement functions.\\ +\indent It's regarding the abutmentbox of the instance \verb-ins- that the next instance is going to be placed, if using the appropriate functions.\\ + +\indent Note that the more recently placed instance becomes automaticaly the "reference instance", if SetRefIns isn't called. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : defines the new "reference instance" +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceRight ( myInst2, NOSYM ) + +SetRefIns ( myInst1 ) +PlaceTop ( myInst3, SYM_Y ) +\end{verbatim} + +\indent \verb-myInst3- is on top of \verb-myInst1- instead of \verb-myInst2-. + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] SetRefIns : the instance doesn't exist.-\\If the instance has not been instanciated, it is impossible do to any placement from it. + \item \verb-[Stratus ERROR] SetRefIns : the instance ...is not placed.-\\If the instance has not been placed, it is impossible do to any placement from it. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} diff --git a/stratus1/doc/man_shift.tex b/stratus1/doc/man_shift.tex new file mode 100644 index 00000000..49867368 --- /dev/null +++ b/stratus1/doc/man_shift.tex @@ -0,0 +1,82 @@ +\subsubsection{Name} + +Shift -- Easy way to instantiate a shifter + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCmd.Shift ( netIn, direction, type ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the command of the shifter, it's the one which defines the number of bits to shift. The net given as parameter is the input net. The other arguments set the different patameters. The method returns a net : the output net.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetShift- method. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-netIn- : the net which is going to be shifted + \item \verb-direction- : this string represents the direction of the shift : + \begin{itemize} + \item "left" + \item "right" + \end{itemize} + \item \verb-type- : this string represents the type of the shift : + \begin{itemize} + \item "logical" : only "zeros" are put in the net + \item "arith" : meaningful for "right" shift, the values put in the nets are an extension of the MSB + \item "circular" : the values put in the nets are the ones which have just been taken off + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = LogicIn ( "a", 4 ) + + self.Cmd = LogicIn ( "cmd", 2 ) + + self.S1 = LogicOut ( "s1", 4 ) + self.S2 = LogicOut ( "s2", 4 ) + self.S3 = LogicOut ( "s3", 4 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S1 <= self.Cmd.Shift ( self.A, "right", "logical" ) + self.S2 <= self.Cmd.Shift ( self.A, "right", "arith" ) + + self.S3 <= self.Cmd.Shift ( self.A, "left", "circular" ) +\end{verbatim} +\indent If the value of "a" is "0b1001" and the value of "cmd" is "0b10", we will have : +\begin{itemize} + \item "s1" : "0b0010" + \item "s2" : "0b1110" + \item "s3" : "0b0110" +\end{itemize} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Shift : The input net does not have a positive arity.-\\The net which is going to be shifted must have a positive arity. + \item \verb-[Stratus ERROR] Shift :-\\\verb-The direction parameter must be "left" or "right".-\\The "direction" argument is not correct. + \item \verb-[Stratus ERROR] Shift :-\\\verb-The type parameter must be "logical" or "arith" or "circular".-\\The "type" argument is not correct. +\end{itemize} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} diff --git a/stratus1/doc/man_stratus.tex b/stratus1/doc/man_stratus.tex new file mode 100644 index 00000000..840123c7 --- /dev/null +++ b/stratus1/doc/man_stratus.tex @@ -0,0 +1,119 @@ +\subsubsection{Name} + +Stratus -- Procedural design language based upon \emph{Python} + +\subsubsection{Description} + +\emph{Stratus} is a set of \emph{Python} methods/functions dedicated to procedural generation purposes. From a user point of view, \emph{Stratus} is a circuit's description language that allows \emph{Python} programming flow control, variable use, and specialized functions in order to handle vlsi objects.\\ + +\indent Based upon the \emph{Hurricane} data structures, the \emph{Stratus} language gives the user the ability to describe netlist and layout views. + +\subsubsection{Creation of a cell} + +A cell is a hierachical structural description of a circuit in terms of ports (I/Os), signals (nets) and instances : + +\begin{itemize} +\item Method \verb-Interface- + \begin{itemize} + \item LogicIn + \item LogicOut + \item LogicInOut + \item TriState + \item VddIn + \item VssIn + \end{itemize} +\item Method \verb-Netlist- + \begin{itemize} + \item Signal + \item Inst + \item Facilities : \&, |, +, Mux, Shift, Eq/Ne ... + \end{itemize} +\item Method \verb-Layout- + \begin{itemize} + \item Place, PlaceTop, PlaceBottom, PlaceRight, PlaceLeft + \item SetRefIns + \item DefAb, ResizeAb + \item PlaceCentric + \item PlaceGlue, FillCell + \item PadNorth, PadSouth, PadEast, PadWest + \item AlimVerticalRail, AlimHorizontalRail + \item AlimConnectors + \item PowerRing + \item RouteCk + \end{itemize} + \item Method \verb-Pattern- + \item Method \verb-View- + \item Method \verb-Save- +\end{itemize} + +\subsubsection{Syntax highlighting} + +This chapter describes what to do to have the right syntax highlighting when using vi. + +\begin{itemize} + \item Commands to do when you want to change once the coloration of your file : +\end{itemize} +\begin{small} +\begin{verbatim} +:syntax off +:source /asim/coriolis/share/etc/stratus.vim +\end{verbatim} +\end{small} +\begin{itemize} + \item Modification of your .vimrc in order to have the syntax highlighting each time you open a file : +\end{itemize} +\begin{small} +\begin{verbatim} +syntax off +autocmd BufRead,BufNewfile *.py so /asim/coriolis/share/etc/stratus.vim +syntax on +\end{verbatim} +\end{small} + +\subsubsection{Environment variables} + +\begin{itemize} + \item CRL\_IN\_LO, default value : \verb-def- + \item CRL\_OUT\_LO, default value : \verb-def- + \item CRL\_IN\_PH, default value : \verb-def- + \item CRL\_OUT\_PH, default value : \verb-def- + \item CRL\_CATA\_LIB, default value : \verb-.- + \item CRL\_CATAL\_NAME, default value : \verb-CATAL- +\end{itemize} + +\subsubsection{Syntax} + +A \emph{Stratus} file must have a .py extension and must begin as follow : +\begin{verbatim} +#!/usr/bin/python + +from stratus import * +\end{verbatim} + +\indent In order to execute a \emph{Stratus} file (named \verb-file- for example), one has two choices : +\begin{verbatim} +python file.py +\end{verbatim} +\indent Or : +\begin{verbatim} +chmod u+x file.py +./file.py +\end{verbatim} + +\indent The names used in \emph{Stratus}, as arguments to \emph{Stratus} functions, should be alphanumerical, including the underscore. The arguments of \emph{Stratus} are case sensitive, so \textsc{VDD} is not equivalent to \textsc{vdd}.\\ + +\indent Vectorized connectors or signal can be used using the \textsc{[n:m]} construct.\\ + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{A concrete example}}{}{Example}{secexample} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Model}}{}{Model}{secmodel} +\hyperref[ref]{\emph{Param}}{}{Param}{secparam} +\hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Facilities}}{}{Facilities}{secfacilities} diff --git a/stratus1/doc/patterns/.latex2html-init b/stratus1/doc/patterns/.latex2html-init new file mode 100644 index 00000000..41736623 --- /dev/null +++ b/stratus1/doc/patterns/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 4; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
    \n$address_data[1]
    "; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "

    \n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
    ' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
    \n"; +} + + +sub bot_navigation_panel { + return "\n

    \n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
    20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/doc/patterns/ASIM.css b/stratus1/doc/patterns/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/patterns/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/patterns/Makefile.am b/stratus1/doc/patterns/Makefile.am new file mode 100644 index 00000000..750e420b --- /dev/null +++ b/stratus1/doc/patterns/Makefile.am @@ -0,0 +1,66 @@ + +doc_en_latex_patternsdir = $(datadir)/doc/en/latex/patterns +doc_en_html_patternsdir = $(datadir)/doc/en/html/patterns +doc_en_pdf_patternsdir = $(datadir)/doc/en/pdf/patterns + + +doc_en_patterns_EXTRA = patterns.tex \ + html.entry \ + ASIM.css \ + .latex2html-init + + +install-data-hook: + @if [ `which latex2html 2>/dev/null` ]; then \ + for file in `ls $(srcdir)/*.tex`; do \ + filename=`basename $$file`; \ + if [ ! -L $$filename -a ! -f $$filename ]; then \ + ln -sf $(srcdir)/$$filename . ; \ + fi ; \ + done ; \ + if [ ! -L ASIM.css -a ! -f ASIM.css ]; then \ + ln -sf $(srcdir)/*.css . ; \ + ln -sf $(srcdir)/.latex2html-init . ; \ + $(mkinstalldirs) images ; \ + ln -sf $(srcdir)/images/*.png ./images/ ; \ + fi ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_patternsdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_patternsdir)/images ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_html_patternsdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_pdf_patternsdir) ; \ + cp -r *.tex $(DESTDIR)$(doc_en_latex_patternsdir) ; \ + cp -r *.css $(DESTDIR)$(doc_en_latex_patternsdir) ; \ + cp -r .latex2html-init $(DESTDIR)$(doc_en_latex_patternsdir) ; \ + cp -r images/*.png $(DESTDIR)$(doc_en_latex_patternsdir)/images ; \ + rm -f *.aux *.lof *.log *.out *.toc *.dvi ; \ + latex2html -no_math -html_version 4.0,math -style ./ASIM.css patterns.tex ; \ + cp -pr patterns/* $(DESTDIR)$(doc_en_html_patternsdir) ; \ + cp -p ASIM.css $(DESTDIR)$(doc_en_html_patternsdir)/ASIM.css ; \ + pdflatex patterns.tex ; \ + pdflatex patterns.tex ; \ + cp patterns.pdf $(DESTDIR)$(doc_en_pdf_patternsdir) ; \ + cp $(srcdir)/html.entry $(DESTDIR)$(doc_en_html_patternsdir); \ + if [ -x $(datadir)/doc/en/html/generateIndex.sh ]; then \ + $(datadir)/doc/en/html/generateIndex.sh \ + --prefix=${prefix} --destdir=$(DESTDIR) ; \ + fi ; \ + else \ + echo "[WARNING] latex2html not found, skipping doc generation."; \ + fi + + +EXTRA_DIST = $(doc_en_patterns_EXTRA) + +CLEANFILES = *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS + diff --git a/stratus1/doc/patterns/html.entry b/stratus1/doc/patterns/html.entry new file mode 100644 index 00000000..902d828c --- /dev/null +++ b/stratus1/doc/patterns/html.entry @@ -0,0 +1 @@ +

  • Patterns module
    Patterns description using Stratus

    diff --git a/stratus1/doc/patterns/patterns.tex b/stratus1/doc/patterns/patterns.tex new file mode 100644 index 00000000..45009167 --- /dev/null +++ b/stratus1/doc/patterns/patterns.tex @@ -0,0 +1,269 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyhdr} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{url} +\usepackage{html} +\usepackage{color} + + \definecolor{violet}{rgb}{0.5,0,0.5} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +\sloppy + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +%---------------------------------- document --------------------------------- +\date {} +\title {Patterns Module User's Manual} +\author {Roselyne Chotin-Avot} + +\begin{document} + +\setlength{\footrulewidth}{0.6pt} +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{Description} +The patterns module of \emph{Stratus} is a set of \emph{Python} classes and +methods that allows a procedural description of input pattern file for the +logic simulator. The \emph{Stratus} \verb-Pattern- method produces a pattern +description file as output. The file generated by \verb-Pattern- method is in +pat format, so IT IS STRONGLY RECOMMENDED TO SEE pat(5) manual BEFORE TO USE +IT. + +\section{Syntax} +From a user point of view, \verb-Pattern- method is a pattern description +language using all standard \emph{Python} facilities. Here follows the +description of the \verb-Pattern- method.\\ +A pat format file can be divided in two parts : declaration and description +part.\\ +The declaration part is the list of inputs, outputs, internal signals and +registers. Inputs are to be forced to a certain value and all the others are +to be observed during simulation.\\ +The description part is a set of patterns, where each pattern defines the value +of inputs and outputs. The pattern number represents actually the absolute time +for the simulator.\\ +Similarly, a \verb-Pattern- method can be divided in two parts : declaration +and description part. Methods related to the declaration must be called +before any function related to the description part. + +\subsection{Declaration part} +The first thing you should do in this part is to instantiate the class +\verb-Patwrite- to have access to all patterns declaration and description +methods. The constructor of this class take as parameters the name of pattern +output file and the \emph{Stratus} cell that is described (see \verb-PatWrite- +\ref{patwrite}).\\ +Then, this part allows you to declare the inputs, the outputs, and internal +observing points (see \verb-declar-\ref{declar} and \verb-declar_interface- +\ref{declar_interface}). + +\subsection{Description part} +After all signals are declared, you can begin the description part (see +\verb-pattern_begin- \ref{pattern_begin}). In this part you have to define +input values which are to be applied to the inputs of the circuit or output +values which are to be compare with the values produced during the simulation. +(see \verb-affect- \ref{affect}, \verb-affect_any- \ref{affect_any}, +\verb-affect_int- \ref{affect_int} and \verb-affect_fix- \ref{affect_fix}). +\verb-Pattern- method describes the stimulus by event : only signal transitions +are described. After each event there is a new input in the pattern file (see +\verb-addpat- \ref{addpat}). Last thing you should do in this part is to +generate the output file (see \verb-pattern_end- \ref{pattern_end}). + +\section{Methods} +\subsection{PatWrite} +\label{patwrite} +This class is used to create patterns for \emph{Stratus} models. Currently +it only supports Alliance ".pat" pattern format. Patterns time stamps are in +the "absolute date" format, "relative date" isn't allowed. Legal time unit are +ps (default), ns, us and ms. The constructor takes as parameters the pattern +output filename and an optional reference to Stratus cell. + +\subsection{declar} +\label{declar} +Adds a connector from a Stratus model to the pattern interface. Writes the +corresponding connector declaration in the pattern file with name, arity and +direction automatically extracted from the connector properties.\\ +Supported Stratus connectors are: +\begin{itemize} +\item{SignalIn,} +\item{SignalOut (only supported if used as an output),} +\item{VddIn,} +\item{VssIn,} +\item{CkIn,} +\item{SignalInOut,} +\item{TriState (always an output),} +\item{Signals.} +\end{itemize} + +\subsubsection{Parameters} +\begin{itemize} +\item{connector : can either be a reference to a stratus net or a string +containing the name of the stratus net.} +\item{format : optional format for the connectors values into the pattern file, +accepted values are :} + \begin{itemize} + \item{'B': binary (default),} + \item{'X': hexadecimal,} + \item{'O': octal.} + \end{itemize} +\end{itemize} + +\subsection{declar\_interface} +\label{declar_interface} +Adds all the connectors from a Stratus model to the pattern interface. Write +the corresponding connector declaration in the pattern file with name, arity +and direction directly taken from the connector proprieties.\\ + +\subsubsection{Parameters} +\begin{itemize} +\item{cell : the tested Stratus model reference. Optional if a reference to the +tested Stratus model was given during instanciation\ref{patwrite}.} +\item{format : optional format for the connectors values into the pattern file, +accepted values are :} + \begin{itemize} + \item{'B': binary (default),} + \item{'X': hexadecimal,} + \item{'O': octal.} + \end{itemize} +\end{itemize} + +\subsection{declar} +\label{declar} +Affect a string value to a connector. + +\subsubsection{Parameters} +\begin{itemize} +\item{connector : \emph{Stratus} connector} +\item{value : string to affect to connector} +\end{itemize} + +\subsection{affect\_int} +\label{affect_int} +Affect an integer (CA2) value to a connector. Convert the 2's complement value +to the corresponding binary value. The binary size is taken from the connector +arity. If the connector is an output, the binary value is preceded by "?". + +\subsubsection{Parameters} +\begin{itemize} +\item{connector : \emph{Stratus} connector.} +\item{value : 2's complement value to affect to the connector.} +\end{itemize} + +\subsection{affect\_fix} +\label{affect_fix} +Affect a fixed point value to a connector. Convert the floating point input +value to the corresponding fixed point value with +word\_length=connector.arity() and integer\_word\_length=iwl. If the connector +is an output, the binary value is preceded by "?". + +\subsubsection{Parameters} +\begin{itemize} +\item{connector : \emph{Stratus} connector.} +\item{value : floating point value to convert and asign to connector.} +\item{iwl : integer word length} +\end{itemize} + +\subsection{affect\_any} +\label{affect_any} +Disable comparison between this connector value and the one calculated during +simulation. + +\subsubsection{Parameters} +\begin{itemize} +\item{connector : \emph{Stratus} connector.} +\end{itemize} + +\subsection{addpat} +\label{addpat} +Adds a pattern in the pattern file. + +\subsection{pattern\_begin} +\label{pattern_begin} +Mark the end of the interface declaration and the beginning of the test +vectors. + +\subsection{pattern\_end} +\label{pattern_end} +Mark the end of the test vectors and of the patterns file. + +\section{Example} +\verb-Pattern- method for an addaccu +\begin{verbatim} +def Pattern(self): + # initialisation + pat = PatWrite(self._name+'.pat',self) + + # declaration of ports + pat.declar(self.ck, 'B') + pat.declar(self.load, 'B') + pat.declar(self.input, 'X') + pat.declar(self.output, 'X') + pat.declar(self.vdd, 'B') + pat.declar(self.vss, 'B') + + # use of pat.declar_interface(self) has the same effect + + # description beginning + pat.pattern_begin() + + # affect vdd and vss values + pat.affect_int(self.vdd,1) + pat.affect_int(self.vss,0) + + # first pattern : load an initial value + pat.affect_int(self.input,5) + pat.affect_int(self.load,1) + pat.affect_int(self.ck,0) + # add the pattern in the pattern file + pat.addpat() + # compute next event + pat.affect_int(self.ck,1) + pat.addpat() + + # compute 22 cycle of accumulation + pat.affect_int(self.load,0) + for i in range(1,22): + pat.affect_int(self.ck,0) + pat.addpat() + pat.affect_int(self.ck,1) + pat.affect_int(self.output,i+5) + pat.addpat() + + # end of the description + pat.pattern_end() +\end{verbatim} + +\end{document} diff --git a/stratus1/doc/see_also.tex b/stratus1/doc/see_also.tex new file mode 100644 index 00000000..32299cf7 --- /dev/null +++ b/stratus1/doc/see_also.tex @@ -0,0 +1,3 @@ +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} diff --git a/stratus1/doc/stratus.tex b/stratus1/doc/stratus.tex new file mode 100644 index 00000000..3ff42f29 --- /dev/null +++ b/stratus1/doc/stratus.tex @@ -0,0 +1,289 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyheadings} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{color} +\usepackage{url} +\usepackage{html} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +\sloppy + +\newcommand{\image}[4] +% {\begin{figure}[htbp] + {\begin{figure}[h!] + \includegraphics[width=#2\textwidth]{#1} + \end{figure} + } +% \image{fig.eps}{scale} + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +%---------------------------------- document --------------------------------- +\date {} +\title {Stratus User's Manual} +\author {Sophie Belloeil} + +\begin{document} + +\setlength{\footrulewidth}{0.6pt} +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{Introduction} +\label{secintroduction} + + \subsection{Stratus} + \label{secstratus} + \input{man_stratus} + \subsection{Class Model} + \label{secmodel} + \input{man_model} + \subsection{Function Param} + \label{secparam} + \input{man_param} + \subsection{A concrete example} + \label{secexample} + \input{man_example} + +\newpage +\section{Description of a netlist} +\label{secnetlist} + + \subsection{Creation of nets} + \label{secnet} + \input{man_net} + \subsection{Creation of instances} + \label{secinst} + \input{man_inst} + \subsection{Method Alias} + \label{secalias} + \input{man_alias} + \subsection{Method Extend} + \label{secextend} + \input{man_extend} + \subsection{Function Cat} + \label{seccat} + \input{man_cat} + +\newpage +\section{Description of a layout} +\label{seclayout} + + \subsection{Place} + \label{secplace} + \input{man_place} + \subsection{PlaceTop} + \label{sectop} + \input{man_place_top} + \subsection{PlaceBottom} + \label{secbottom} + \input{man_place_bottom} + \subsection{PlaceRight} + \label{secright} + \input{man_place_right} + \subsection{PlaceLeft} + \label{secleft} + \input{man_place_left} + \subsection{SetRefIns} + \label{secsetrefins} + \input{man_set_ref_ins} + \subsection{DefAb} + \label{secdefab} + \input{man_def_ab} + \subsection{ResizeAb} + \label{secresizeab} + \input{man_resize_ab} + +\newpage +\section{Place and Route} +\label{secroute} + + \subsection{PlaceCentric} + \label{seccentric} + \input{man_place_centric} + \subsection{PlaceGlu} + \label{secglu} + \input{man_place_glu} + \subsection{FillCell} + \label{secfillcell} + \input{man_fill_cell} + \subsection{Pads} + \label{secpads} + \input{man_pads} + \subsection{Alimentation rails} + \label{secrails} + \input{man_alim_rail} + \subsection{Alimentation connectors} + \label{secconnectors} + \input{man_alim_connectors} + \subsection{PowerRing} + \label{secpowerring} + \input{man_power_ring} + \subsection{RouteCk} + \label{secrouteck} + \input{man_route_ck} + +\newpage +\section{Facilities} +\label{secfacilities} + + \subsection{Instanciation of a buffer} + \label{secbuff} + \input{man_buff} + \subsection{Instanciation of a multiplexor} + \label{secmux} + \input{man_mux} + \subsection{Instanciation of a shifter} + \label{secshift} + \input{man_shift} + \subsection{Instanciation of a register} + \label{secreg} + \input{man_reg} + \subsection{Instanciation of constants} + \label{secconstant} + \input{man_const} + \subsection{Logical operations} + \label{secbool} + \input{man_boolean} + \subsection{Arithmetical operations} + \label{secarithmetic} + \input{man_arithmetic} + \subsection{Comparison operations} + \label{seccomp} + \input{man_comp} + +\begin{htmlonly} +\section{Stratus' tools} + +You can have the documentation of the tools related to stratus at :\\ +file:////users/outil/arith/latest/doc/index.html +\end{htmlonly} + +\newpage +\section{Instanciation of your own generators} +\input{man_generators} + +\section{Libraries} + + \subsection{Virtual library} + \input{man_library} + + \subsection{DPGEN generators} + + \subsubsection{DpgenInv} + \input{man_dpgeninv} + \subsubsection{DpgenBuff} + \input{man_dpgenbuff} + \subsubsection{DpgenNand2} + \input{man_dpgennand2} + \subsubsection{DpgenNand3} + \input{man_dpgennand3} + \subsubsection{Dpgennand4} + \input{man_dpgennand4} + \subsubsection{DpgenAnd2} + \input{man_dpgenand2} + \subsubsection{DpgenAnd3} + \input{man_dpgenand3} + \subsubsection{DpgenAnd4} + \input{man_dpgenand4} + \subsubsection{DpgenNor2} + \input{man_dpgennor2} + \subsubsection{DpgenNor3} + \input{man_dpgennor3} + \subsubsection{DpgenNor4} + \input{man_dpgennor4} + \subsubsection{DpgenOr2} + \input{man_dpgenor2} + \subsubsection{DpgenOr3} + \input{man_dpgenor3} + \subsubsection{DpgenOr4} + \input{man_dpgenor4} + \subsubsection{DpgenXor2} + \input{man_dpgenxor2} + \subsubsection{DpgenXnor2} + \input{man_dpgenxnor2} + \subsubsection{DpgenNmux2} + \input{man_dpgennmux2} + \subsubsection{DpgenMux2} + \input{man_dpgenmux2} + \subsubsection{DpgenNbuse} + \input{man_dpgennbuse} + \subsubsection{DpgenBuse} + \input{man_dpgenbuse} + \subsubsection{DpgenNand2mask} + \input{man_dpgennand2mask} + \subsubsection{DpgenNor2mask} + \input{man_dpgennor2mask} + \subsubsection{DpgenXnor2mask} + \input{man_dpgenxnor2mask} + \subsubsection{DpgenAdsb2f} + \input{man_dpgenadsb2f} + \subsubsection{DpgenShift} + \input{man_dpgenshift} + \subsubsection{DpgenShrot} + \input{man_dpgenshrot} + \subsubsection{DpgenNul} + \input{man_dpgennul} + \subsubsection{DpgenConst} + \input{man_dpgenconst} + \subsubsection{DpgenRom2} + \input{man_dpgenrom2} + \subsubsection{DpgenRom4} + \input{man_dpgenrom4} + \subsubsection{DpgenRam} + \input{man_dpgenram} + \subsubsection{DpgenRf1} + \input{man_dpgenrf1} + \subsubsection{DpgenRf1d} + \input{man_dpgenrf1d} + \subsubsection{DpgenFifo} + \input{man_dpgenfifo} + \subsubsection{DpgenDff} + \input{man_dpgendff} + \subsubsection{DpgenDfft} + \input{man_dpgendfft} + \subsubsection{DpgenSff} + \input{man_dpgensff} + \subsubsection{DpgenSfft} + \input{man_dpgensfft} + +\begin{htmlonly} + \subsection{Arithmetic generators} + +You can have the documentation of the arithmetic library at :\\ +file:////users/outil/arith/latest/doc/index.html +\end{htmlonly} +\end{document} diff --git a/stratus1/doc/stratus/.latex2html-init b/stratus1/doc/stratus/.latex2html-init new file mode 100644 index 00000000..df1398eb --- /dev/null +++ b/stratus1/doc/stratus/.latex2html-init @@ -0,0 +1,308 @@ + +# -*- Perl -*- +# +#LaTeX2HTML Version 96.1 : dot.latex2html-init +# +### Command Line Argument Defaults ####################################### + +$MAX_SPLIT_DEPTH = 5; # Stop making separate files at this depth + +$MAX_LINK_DEPTH = 2; # Stop showing child nodes at this depth + +$NOLATEX = 0; # 1 = do not pass unknown environments to Latex + +$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document + +$ASCII_MODE = 0; # 1 = do not use any icons or internal images + +# 1 = use links to external postscript images rather than inlined bitmap +# images. +$PS_IMAGES = 0; + +#$TITLE = "Titre"; # The default is "No Title" + +$DESTDIR = ''; # Put the result in this directory + +# When this is set, the generated HTML files will be placed in the +# current directory. If set to 0 the default behaviour is to create (or reuse) +# another file directory. +$NO_SUBDIR = 0; + + +# Supply your own string if you don't like the default +$ADDRESS = "$address_data[0]
    \n$address_data[1]
    "; + +$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page + +# Put navigation links at the top of each page. +# If the page exceeds $WORDS_IN_PAGE number of words then put one at the bottom of the page. +$AUTO_NAVIGATION = 1; + +# Put a link to the index page in the navigation panel +$INDEX_IN_NAVIGATION = 1; + +# Put a link to the table of contents in the navigation panel +$CONTENTS_IN_NAVIGATION = 1; + +# Put a link to the next logical page in the navigation panel +$NEXT_PAGE_IN_NAVIGATION = 1; + +# Put a link to the previous logical page in the navigation panel +$PREVIOUS_PAGE_IN_NAVIGATION = 1; + +$INFO = 0; # 0 = do not make a "About this document..." section + +# Reuse images generated during previous runs +$REUSE = 2; + +# When this is 1, the section numbers are shown. The section numbers should +# then match those that would have bee produced by LaTeX. +# The correct section numbers are obtained from the $FILE.aux file generated +# by LaTeX. +# Hiding the seciton numbers encourages use of particular sections +# as standalone documents. In this case the cross reference to a section +# is shown using the default symbol rather than the section number. +$SHOW_SECTION_NUMBERS = 0; + +### Other global variables ############################################### +$CHILDLINE = "

    \n"; + +# This is the line width measured in pixels and it is used to right justify +# equations and equation arrays; +$LINE_WIDTH = 500; + +# Used in conjunction with AUTO_NAVIGATION +#$WORDS_IN_PAGE = 300; !!! +$WORDS_IN_PAGE = 50; + +# Affects ONLY the way accents are processed +$default_language = 'english'; + +# The value of this variable determines how many words to use in each +# title that is added to the navigation panel (see below) +# +$WORDS_IN_NAVIGATION_PANEL_TITLES = 4; + +# This number will determine the size of the equations, special characters, +# and anything which will be converted into an inlined image +# *except* "image generating environments" such as "figure", "table" +# or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$MATH_SCALE_FACTOR = 1.6; + +# This number will determine the size of +# image generating environments such as "figure", "table" or "minipage". +# Effective values are those greater than 0. +# Sensible values are between 0.1 - 4. +$FIGURE_SCALE_FACTOR = 1.6; + + +# If this is set then intermediate files are left for later inspection. +# This includes $$_images.tex and $$_images.log created during image +# conversion. +# Caution: Intermediate files can be *enormous*. +$DEBUG = 0; + +# If both of the following two variables are set then the "Up" button +# of the navigation panel in the first node/page of a converted document +# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set +# to some text which describes this external link. +$EXTERNAL_UP_LINK = ""; +$EXTERNAL_UP_TITLE = ""; + +# If this is set then the resulting HTML will look marginally better if viewed +# with Netscape. +$NETSCAPE_HTML = 0; + +# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" +# Paper sizes has no effect other than in the time it takes to create inlined +# images and in whether large images can be created at all ie +# - larger paper sizes *MAY* help with large image problems +# - smaller paper sizes are quicker to handle +$PAPERSIZE = "a4"; + +# Replace "english" with another language in order to tell LaTeX2HTML that you +# want some generated section titles (eg "Table of Contents" or "References") +# to appear in a different language. Currently only "english" and "french" +# is supported but it is very easy to add your own. See the example in the +# file "latex2html.config" +$TITLES_LANGUAGE = "english"; + +### Navigation Panel ########################################################## +# +# The navigation panel is constructed out of buttons and section titles. +# These can be configured in any combination with arbitrary text and +# HTML tags interspersed between them. +# The buttons available are: +# $PREVIOUS - points to the previous section +# $UP - points up to the "parent" section +# $NEXT - points to the next section +# $NEXT_GROUP - points to the next "group" section +# $PREVIOUS_GROUP - points to the previous "group" section +# $CONTENTS - points to the contents page if there is one +# $INDEX - points to the index page if there is one +# +# If the corresponding section exists the button will contain an +# active link to that section. If the corresponding section does +# not exist the button will be inactive. +# +# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP +# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables +# which contain the titles of their corresponding sections. +# Each title is empty if there is no corresponding section. +# +# The subroutine below constructs the navigation panels in each page. +# Feel free to mix and match buttons, titles, your own text, your logos, +# and arbitrary HTML (the "." is the Perl concatenation operator). + + +@my_icon_tags = (); +$my_icon_tags{'next'} = 'Next Page'; +$my_icon_tags{'next_page'} = 'Next Page'; +$my_icon_tags{'previous'} = 'Previous Page'; +$my_icon_tags{'previous_page'} = 'Previous Page'; +$my_icon_tags{'up'} = 'Up One Level'; +$my_icon_tags{'contents'} = 'Contents'; +$my_icon_tags{'index'} = 'Index'; +$my_icon_tags{'modules'} = 'Module Index'; + +@my_icon_names = (); +$my_icon_names{'previous_page'} = 'prev'; +$my_icon_names{'next_page'} = 'next'; + + +sub get_my_icon($) { + my $icon_file; + my $name = @_[0]; + my $text = $my_icon_tags{$name}; + if ($my_icon_names{$name}) { + $name = $my_icon_names{$name}; + } + if ($text eq '') { + $name = 'blank'; + } + $icon_file = $name . "." . $IMAGE_TYPE; + $used_icons{$icon_file} = 1; + return "\"$text\""; +} + + +sub use_my_icon($) { + my $s = @_[0]; + if ($s =~ /\/) { + my $r = get_my_icon($1); + $s =~ s/\/$r/; + } + return $s; +} + + +sub make_top_nav_panel() { + my $s; + $s = ('' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub make_bot_nav_panel() { + my $s; + $s = ('
    ' + #. "\n" + . "\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n\n" + # ... and the ``previous'' title + . "\n" + # Similarly with the ``up'' title ... + . "\n" + # If ``next'' section exists, add its title to the navigation panel + . "\n" + . "\n
    $t_title
    " + . ($PREVIOUS_TITLE ? "Previous" : " ") + . "" + . ($UP_TITLE ? "Up" : " ") + . "" + . ($NEXT_TITLE ? "Next" : " ") + . "
    " + . ($PREVIOUS_TITLE ? "$PREVIOUS_TITLE" : " ") + . "" + . ($UP_TITLE ? "$UP_TITLE" : " ") + . "" + . ($NEXT_TITLE ? "$NEXT_TITLE" : " ") + . "
    \n" + . "
    \n" + ); + # remove these; they are unnecessary and cause errors from validation + $s =~ s/ NAME="tex2html\d+"\n */ /g; + return $s; +} + + +sub top_navigation_panel { + return "\n" + . make_top_nav_panel() + . "
    \n"; +} + + +sub bot_navigation_panel { + return "\n

    \n" + . make_bot_nav_panel() + . "\n"; +} + + +#$EXTERNAL_STYLESHEET = "../ASIM.css"; + +$ADDRESS = "Sophie BELLOEIL
    20051116.1"; + +$LOCAL_ICONS = 0; + +$USING_STYLES = 1; + +$TRANSPARENT_FIGURES = 1; + +$WHITE_BACKGROUND = 0; + +$used_icons{"home." . $IMAGE_TYPE} = 1; + +1; # This must be the last line diff --git a/stratus1/doc/stratus/ASIM.css b/stratus1/doc/stratus/ASIM.css new file mode 100644 index 00000000..180cadb3 --- /dev/null +++ b/stratus1/doc/stratus/ASIM.css @@ -0,0 +1,164 @@ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + div.navigation { margin-bottom: 1em; } + div.navigation h1 { margin-top: 2em; clear: both; } + div.navigation table { margin-left: 2em; font-size: 90%; } + div.navigation img { color: white; border: none; } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + p.copyright { font-size: 90%; } + p.copyright small { font-size: 80%; } + + p.changed { + padding-left: 0.2em; + border-left: solid; + border-top: none; + border-bottom: none; + border-right: none; + border-left-width: thin; + border-color: red; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + /* + margin-left: 0em; + margin-right: 0em; + */ + margin-top: 0.8em; + margin-bottom: 0.8em; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + diff --git a/stratus1/doc/stratus/Makefile.am b/stratus1/doc/stratus/Makefile.am new file mode 100644 index 00000000..6eef8038 --- /dev/null +++ b/stratus1/doc/stratus/Makefile.am @@ -0,0 +1,106 @@ + +SUBDIRS = images + +doc_en_latex_stratusdir = $(datadir)/doc/en/latex/stratus +doc_en_html_stratusdir = $(datadir)/doc/en/html/stratus +doc_en_pdf_stratusdir = $(datadir)/doc/en/pdf/stratus + + +doc_en_stratus_EXTRA = stratus.tex \ + man_new.tex \ + man_alim_connectors.tex \ + man_alim_rail.tex \ + man_arithmetic.tex \ + man_boolean.tex \ + man_buff.tex \ + man_comp.tex \ + man_const.tex \ + man_def_ab.tex \ + man_example.tex \ + man_fill_cell.tex \ + man_generate.tex \ + man_get_ref.tex \ + man_inst.tex \ + man_library.tex \ + man_mux.tex \ + man_net.tex \ + man_pads.tex \ + man_place_bottom.tex \ + man_place_centric.tex \ + man_place_contact.tex \ + man_place_glu.tex \ + man_place_left.tex \ + man_place_ref.tex \ + man_place_right.tex \ + man_place_segment.tex \ + man_place_pin.tex \ + man_place.tex \ + man_place_top.tex \ + man_copy_up_segment.tex \ + man_power_ring.tex \ + man_reg.tex \ + man_resize_ab.tex \ + man_route_ck.tex \ + man_set_ref_ins.tex \ + man_shift.tex \ + man_stratus.tex \ + see_also.tex \ + html.entry \ + ASIM.css \ + .latex2html-init + + +install-data-hook: + @if [ `which latex2html 2>/dev/null` ]; then \ + for file in `ls $(srcdir)/*.tex`; do \ + filename=`basename $$file`; \ + if [ ! -L $$filename -a ! -f $$filename ]; then \ + ln -sf $(srcdir)/$$filename . ; \ + fi ; \ + done ; \ + if [ ! -L ASIM.css -a ! -f ASIM.css ]; then \ + ln -sf $(srcdir)/*.css . ; \ + ln -sf $(srcdir)/.latex2html-init . ; \ + $(mkinstalldirs) images ; \ + ln -sf $(srcdir)/images/*.png ./images/ ; \ + fi ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_latex_stratusdir)/images ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_html_stratusdir) ; \ + $(mkinstalldirs) $(DESTDIR)$(doc_en_pdf_stratusdir) ; \ + cp -r *.tex $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + cp -r *.css $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + cp -r .latex2html-init $(DESTDIR)$(doc_en_latex_stratusdir) ; \ + cp -r images/*.png $(DESTDIR)$(doc_en_latex_stratusdir)/images ; \ + rm -f *.aux *.lof *.log *.out *.toc *.dvi ; \ + latex2html -no_math -html_version 4.0,math -style ./ASIM.css stratus.tex ; \ + cp -pr stratus/* $(DESTDIR)$(doc_en_html_stratusdir) ; \ + cp -p ASIM.css $(DESTDIR)$(doc_en_html_stratusdir)/ASIM.css ; \ + pdflatex stratus.tex ; \ + pdflatex stratus.tex ; \ + cp stratus.pdf $(DESTDIR)$(doc_en_pdf_stratusdir) ; \ + cp $(srcdir)/html.entry $(DESTDIR)$(doc_en_html_stratusdir); \ + if [ -x $(datadir)/doc/en/html/generateIndex.sh ]; then \ + $(datadir)/doc/en/html/generateIndex.sh \ + --prefix=${prefix} --destdir=$(DESTDIR) ; \ + fi ; \ + else \ + echo "[WARNING] latex2html not found, skipping doc generation."; \ + fi + + +EXTRA_DIST = $(doc_en_stratus_EXTRA) + +CLEANFILES = *.dvi \ + *.ps \ + *.lof \ + *.log \ + *.out \ + *.toc \ + *.aux \ + *.bak \ + stratus/*.html \ + stratus/*.css \ + stratus/*.pl \ + stratus/WARNINGS + diff --git a/stratus1/doc/stratus/fichiers/Makefile b/stratus1/doc/stratus/fichiers/Makefile new file mode 100644 index 00000000..2f18881b --- /dev/null +++ b/stratus1/doc/stratus/fichiers/Makefile @@ -0,0 +1,5 @@ +test: + time ./test.py -n 4 + +clean : + rm -f *.vst *.ap *.pyc diff --git a/stratus1/doc/stratus/fichiers/addaccu.py b/stratus1/doc/stratus/fichiers/addaccu.py new file mode 100644 index 00000000..8942c77f --- /dev/null +++ b/stratus1/doc/stratus/fichiers/addaccu.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +from stratus import * + +class addaccu ( Model ) : + + def Interface ( self ) : + self.nbit = self._param['nbit'] + + self.a = SignalIn ( "a", self.nbit ) + self.b = SignalIn ( "b", self.nbit ) + self.c = SignalIn ( "c", self.nbit ) + self.v = SignalIn ( "v", 1 ) + self.cmd = SignalIn ( "cmd", 1 ) + + self.cout = SignalOut ( "cout", 1 ) + self.s = SignalOut ( "s", self.nbit ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + d_aux = Signal ( "d_aux", self.nbit ) + e_aux = Signal ( "e_aux", self.nbit ) + ovr = Signal ( "ovr", 1 ) + + + Generate ( "DpgenNand2", "nand2%d" % self.nbit + , param = { 'nbit' : self.nbit + , 'physical' : True + } + ) + temp = Cat ( self.v, self.v, self.v, self.v ) + self.instNand2 = Inst ( "nand2%d" % self.nbit, "instance_nand2" + , map = { 'i0' : temp + , 'i1' : self.a + , 'nq' : d_aux + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + Generate ( "DpgenOr2", "or2%d" % self.nbit + , param = { 'nbit' : self.nbit + , 'physical' : True + } + ) + self.instOr2 = Inst ( "or2%d" % self.nbit, "instance_or2" + , map = { 'i0' : d_aux + , 'i1' : self.b + , 'q' : e_aux + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + Generate ( "DpgenAdsb2f", "adder%d" % self.nbit + , param = { 'nbit' : self.nbit + , 'physical' : True + } + ) + self.instAdd2 = Inst ( "adder%d" % self.nbit, "instance_add2" + , map = { 'i0' : e_aux + , 'i1' : self.c + , 'q' : self.s + , 'add_sub' : self.cmd + , 'c31' : self.cout + , 'c30' : ovr + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + Place ( self.instNand2, NOSYM, XY ( 0, 0 ) ) + PlaceRight ( self.instOr2, NOSYM ) + PlaceRight ( self.instAdd2, NOSYM ) + + diff --git a/stratus1/doc/stratus/fichiers/test.py b/stratus1/doc/stratus/fichiers/test.py new file mode 100755 index 00000000..08461e93 --- /dev/null +++ b/stratus1/doc/stratus/fichiers/test.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +from stratus import * +from addaccu import addaccu + +nbit = Param ( "n" ) + +dict = { 'nbit' : nbit } + +inst_addaccu = addaccu ( "inst_addaccu", dict ) + +inst_addaccu.Interface() +inst_addaccu.Netlist() +inst_addaccu.Layout() +inst_addaccu.View() + +inst_addaccu.Save ( PHYSICAL ) + + diff --git a/stratus1/doc/stratus/html.entry b/stratus1/doc/stratus/html.entry new file mode 100644 index 00000000..239ad936 --- /dev/null +++ b/stratus1/doc/stratus/html.entry @@ -0,0 +1 @@ +

  • Stratus
    Netlist / Layout description language

    diff --git a/stratus1/doc/stratus/images/Makefile.am b/stratus1/doc/stratus/images/Makefile.am new file mode 100644 index 00000000..ad610f7c --- /dev/null +++ b/stratus1/doc/stratus/images/Makefile.am @@ -0,0 +1,13 @@ + +doc_en_latex_imagesdir = $(datadir)/doc/en/latex/stratus/images + +doc_en_latex_images_DATA = addaccu1.png \ + addaccu2.png \ + add1.png \ + add2.png \ + editor.png \ + test.png \ + resizeAb.png \ + xml.png + +EXTRA_DIST = $(doc_en_latex_images_DATA) diff --git a/stratus1/doc/stratus/images/add1.png b/stratus1/doc/stratus/images/add1.png new file mode 100644 index 0000000000000000000000000000000000000000..8270f2d4c8cf990124dc03f8583f6c376687ba5f GIT binary patch literal 5500 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 QO&I`HgQ=D%zxlxYKi=2_r~m)} literal 0 HcmV?d00001 diff --git a/stratus1/doc/stratus/images/add2.png b/stratus1/doc/stratus/images/add2.png new file mode 100644 index 0000000000000000000000000000000000000000..08ac408bef89074615347ddc3c6b03e99944d4e8 GIT binary patch literal 15347 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 literal 0 HcmV?d00001 diff --git a/stratus1/doc/stratus/images/addaccu2.png b/stratus1/doc/stratus/images/addaccu2.png new file mode 100644 index 0000000000000000000000000000000000000000..c92ca9588119bb08f7fcc62c69f3e039edbcb80d GIT binary patch literal 41878 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�HbtycUgPB8aHI`}`V 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 G{Qgfjg{kZS literal 0 HcmV?d00001 diff --git a/stratus1/doc/stratus/images/editor.png b/stratus1/doc/stratus/images/editor.png new file mode 100644 index 0000000000000000000000000000000000000000..a1f6c6df74cf412dd3cd66fc484b533c778d7c1c GIT binary patch literal 18669 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 kEq${<=-=`10E5cd!Z1I+;*R5Cw$+<;@Ej z4ez;wG{0vWlXJ(QPG`zP23A}fTyI5m#TU;{2}nu%6cl;RW`3uuY0X_%Lat9Bd{OFp zzGCh}e$B?G)>wQm)h3#=B7`*rj>)iHRZTD{ER&LtVqJ1olVoybil>gsB!`RP2irbV zOMa4mB`womcihG9p#?uVWeX_=|#sQocvh19D($DU`6I8`7>G$=E>EM?Lgqi1SHUHOYu;VfkByMy0SC%rz>bqm1Sp>3>%(QVQ7x%6t1cJk(7D?L;f?7s zFdYV3@Jd|>JRrf%YkNl(2J^mkU{=V?&+mKnosu_KJ_qKGY>ec**JR1z6r3$ZkZp1j zu=PO&``Vd0J>-?ikkgTdU9yODSXl6nrzcwte{Lt7QSdFH(udz}>T@#AaXXgR20CWB zzo;0kFk4iHF&q>`JDw1)l^AOb&&}{FDv6W!baTad^YPNv)2q_!{jQWr&vmHeJZ6B9 z?^6BeM{RH`wq@h~)Wnn7jq;gkEX8|9aOS6sm%nn~L^a)djAiL3Cs%H|`+ivS)c4Bx z5b#QAM^XW-4K$57(eh3yye_Rz#YUq{GM*=E_*fl-Tza7V(vw;pr&1Oy$@>_j7EX#Hjokof#dyy|00ri;&mC3Dq@hBFD-Sy%Nw~ivg2=61?mFyYqg;ayHCz>96@)nc*W>2X~m>Dl$IHVO8BoOR8WOH*C zb3Mmb$(y8U3gl|5QuG2Vwe_17KmuoWwx?_@f9cR`m&INb!!BS%-Lz3`kc(}LClb8x zo*%8Mi9h9$_Sg+i(Kg!Q_t!&?1|CWYZ(7`ZHS>MhB4zy}a^O5&woD2EwYr_Yt@j=D zcP&=RyWKD49_O~8iq|gsrrHiaVgCpgsn_K`v&9ZVWQHP97Xt*P3EU`cGdZKtR$N4^ zu8Ka~aQ-Th0c+8{HS{zItqL74eqW)Cb>5=kKj`W&wFpMon>w23jr`~z`_a$0?lRal zyWo;YH{%SuY3Tiw72jXj(XVD^TIC`X6LEleE=H~;OPU%S91}m?_Lw!C#2W7b)i^)K z#d9&%6()DyUP&2Lzx`cd7N-I3@%{Tc*`MMh9gA$DoTZSB;#WdEM zu_G(@KH}#5h|w=%)@62c{&+x9xt(X0qq(W=w3x3p8I9L)`m=R&!qHEB*ErisL|lXb z8$Yf5q6BKi|ITm0hV`eXXVKd7sps#j9B!Gss<_v%g@DK65d%BY-K?>DG??}h4Ml3Y z7QQ=!d7f{fKOq^nQFT#0ZAvZc(_Ay|d=A!$&TU<)wM-YJHMx#fLs_tsl$(>y&B5z8 zQ5~Pv(y?gkgGu%dK`V#k9CxkWDwXEQ@`XtnS=)M8EmpF5MbnfHWvD^&Fsnu$7Hp1B zd>4b<^?Z7+4EN7-AQ3**qH#h!-o^YLOBc_3Pd7Rqtl*(jvD0G*qlk2BP~hv8^Ji}} z+lSF-@uRd7PjhU)gzvkYS5Wd0lgB^Zh~EsR-iQ_%hFq2_c3{@ z--242bzJnbC!=)*mvzQw6w$64eUo#awsovlB^)jv_bmz1XWMPBHd+5VXodReh#V?j zb2?dhwS0Y+@ha%uH7DGdj!(NFO=DRzd(?*h1!)5%RkMNY+M2oI_jjU>1UDY)fspyx z&ZKv9Zw@$m^3)2BUCv!SozWyL94}85T|;|XG!1vx_hy+S71!_2pg~OO+=IG~2Np-S z4z=Z4gJV}8TR%hBQwfcul)MglBQ0Mwx^j+P-*BI#BOEVPv~#vB zR;4HBuvAnP{{v=XdS#W7G*FJ(V@4O3>l}ZFG+)y>ZAT@pNw!Ttn?6Vnf*$89CXrcc zm9Z^L3-U{*j7$K{&x^>i)CT{e%#tSMVNaO|gI`r@y62_}KYm*eT_{~{$mPE9#HAd0 zTCJvABYo84<%y8AS)NmjBhwdgq!vDU*9ASHYDlcQ-K_M_jA_atd{lR1L(BRQcV0u4 zp?3v;N4>pjWL#b`VO=X@s?@0Kqdu@jNRg(cy?FOXijJ@DgvuwTQ7f|axlPM0(5x+V zB})26jCFiNH|qKsFpa5OFZ^g!L5`3&&MD%&1!cu3-R)EqSf4%>aK8wKQWpe-qo;1lAoqjRM=~`8Hs!`<*okA+-1QneS1?I3ES~@k*KJW5B1Fp2&}| z*xw}LL_0l74RLX%qah$+c^^sih{mxKH_6JvLRiqzjGn%EZ6qPt7{v3#&pfBHP|oo7 zaKt94;VMjej-PY8SAUsvde_~9Dn>Q7K_o@|ZYreR26^u{ZBmugDiu}m4FxlV)0;Bb zgKx_+Rykf!MmVMN#F?P05KviTd{RN77s%})N{^f^Ck$C3I|z5F1>ZF={DwDBqOb3T z+(+@0XAD-cyaL1Vj3Gw}WTdyj@|1P>E&HZ*Z z+H88b?|@dk?r@}!r7h%ZxY??~$o3aUC%KmV#FW7I<_qaGWVhRa!#nPC zoOxqliRSbB!$L;{DWb*tVKL}O_A?`3l0yDIlM{SNRJnw91#Fa8Nw`%d5|--gLM2GI z*H^>4lE!p%d;5EWIT?sFqk*pNnmm#dNEDHglwh?TvX)M&JJIyd8e&ZUO+`odq;oS4 z9o-LD`WtO1eC?=8OddstJ31>%X<C7x#JZ17Pz@0rov2JZKASDt)Hn zcJ03Qt3&`GEmOg)?mqwk>Q(1sInZD5RHFHP%{KrV0&w)7k?LPC_C@aFzo07vAL$=l zd+)LO-Rj|MdTSdAk$0x~Q?1kjc7Syqwwj zmrrD5@?XDx^Y8$Vtx@BK&sSP-y-l2ZG4B+b%@7>GfSNNIj4tfVTecxmF9Th~(iBRO z{PT5Yc+?9t3J6IbT6;8-)y*sqD)M?AF4c>u`Y7Vlu$q)zqnT!+u-t!o_v8{UW>Rjm zt8*>gl!m^aZu37NSxDd<-)3!P*V;j94x|++8yi7-U-u1a+6eFl2ltJR(tY|AR9Wh{ z`h}62+kmyC;CDiwr3B)t>Hhs2TBOU(*{kGascggul*rVrP*XDh$F7}USN>e*a3|kU^wT@L8mLu*U z+(L?9GcckKRwn8KV!?9CmmcT1{}QazWy;p^@moN4&q%tUwTDsjOuXB>E+mIR@UJSUh48rUcsUcpmob31-guT%NNAATc!zH@)N zB&DpXs=oTJ8;x)Tu+>lvPQ6V`Uu>1UGDeDh&Hyt=7-S^w-15k852)TXuX@lMaZiJS z{CWY8y_iI!!u*l|Nk&=jj7q!drTyvg43H7<^7^FV1yOZ%svsW+C~(sExuR)Uz^y`T z(S-HKy}k_PH#X~QY7%}IT?OjHiSdK{JHn9-C*1zGC3Ol~e0~?e<-2Xe();1rA)$g| zhI8@kHyL)r8T88~DMeih*sO&dMOsg@LvA;M!v6VOwXJNz&wMp}NNvsXzkbkk4+u&$||$^C3ecCaK8ePxmu1ulby zL~m>we-GjL8wy3K@6htb8fpWXvfEo19}SHAdqI49L)o40Bi<2zudtHwz6yrHRzUFm zS?GM7QKQB!dpGW%(QM72o?PMQb-S^lIXk=F|_E< zDo?ysM}fY}=jUf^wS66M8yK+rb(1h26S582#5y@e8k_%&3Jr~|I^7Sr-GhkF%qs4U znoTyi-6&<2ByuV4&Q^_jH;D8n{AxW}DyMuFc&(W2e;yWIh96Bo8_)(rCf_qB-(2iN zOc#Z*ETySKMr%F?j)={T-+l(qK3_=kW&R(d8d`p+i&}q7; zRcpB2)08Gp>unF*v}mYO@3YVp!P1$w|%jkYrOpQ&nhZnB(GFlLy|(3EJ6g@a}E( z4KuRi+fyihUwhir_#*Aq?gezoA#kutqQuZ3h+0##-N>koAiP7LnLqcb=lKDz_R{bq zX|FcxS*VKeL)>+)*z22!TAQltwJxXA6NEoKE!&ni=u*09vL9gbXP5Sd`gy*$O{8M{ zWpw+St)=O}xF9kk;bk%euw_un8#0R*rth55ql0-fBVO|0I8qnda)otxT>Ubi$Zc=a z-NL*_E#y!2M%@(x5#HRe@9!&6En>OYsSxH;GA92sh3gEq9C6?C^Wlt+9!Qar^w}B7 z*gPrs*gtcXCMRFfG0mzl7uTNt5*&Pb32iFTK+|SpL%8jJZQVFEY#LHh9%kppa(o)E z&-rOCXQ5d2C~GKZuu-ENwSb9reo;Mub_q@;Vk zUP)_?1{eJItMP0F=;VG>ak1odnKFVj`D1oVs8$|(2^&~VtNgdQUiN0jKB;DQ>7uI` zTwb?b`N_0bs&xKQtg1lRlb6z+UYYlvzHaaPoLd~8R!$|<`R=M+pqL?C@-ibln52Kj zi6`qzC48y`k_d^5BpghU3NSVQ`C9#M+B8|0B2|Bkjs|Q}u^-2f2RpkB3=;nSwuNag z9>>2vu^L31ilq?+Ew`2;5neTVi&K*x@?}Oh9YwFAy^oGp^Msv%M`#om8^Xt-oX&|N z?GBK%ohUwYU*3e!{v4ZWYg5h$oV!ZQh=QCvlFiM{c{;Io>3CUz6CS<&3(4Gk~btoNUI_VI)IFrE6fkIGGz-VHpz zLq;KyU!@mzV*j9|kY(a`oECrG+15VfsNsA}9*VWE zZ8?+($;-*1bv4fM%CMGpM-0rIKL*cD@w$Hjg!`m2;8BgcNHmh_WdV0P<1`#6_)X=ZA%D_JlD zccsm3H$4s|H&K=34#fC}(yIeMZ7W)4ve-zU5wLLqzNZP8h3A`jWh9Fkj-XF+S6gjM73Uo-_0PA>&9ai0N%A4;(^i^!lLR0lh$gdCsXO-b<)xxot{s49i8VVbvKtF zW)W{+y*XepJs2DFBBJwWEYhH)RluV#TjR!GzJH&R5=kXA(0E#zUsXcX7y>OW z=Dj)b%1^6Nyy4dc#m?l&SHI28%`@S%u;uZ^(%_fJOcNdWNhm%0P%wE1!C;E0q)<+N zr9H?`arw1+&~W#RRLy>}`vp*{8)P7*0^ZL?fp!POkMEB{T(i>e;5jDaaT zeh79wn*O7rtP`Sgx}LL-xOT`HFkhWETam)1c0X>j;ey4*C#tlm`L1<&-Qaka(|Z^+ z7~_$p5EXO>(}zFX){je9%b0KMh5|phIQ%x&JtCNMLZzOZ&bytqAm5VnAY}iVxcDtm z*9j!y9-*f4tT+ZrGxAhpYsGzIj}lY$-zn0-H5rrh#=3eMx|VC&ohP~1=OXUm$hLR_v!6muSTRJS1!lWao1eOruN(m~d|e?sixh9iVBeD_o}=7mg^Vvraq|Pq0QSD< z7+1j+Wlq!yb>&BJVG}KTuXfC15fS=se0dWqd7+^4*#%eK4SJqN81J^Nq?~SFSom_z z1@A&XxnN+XRpZZ1Cf(JX!`U?rR>XEGbmjs*U~eT~CrXC#OzzE_N8!9&>W%!XL<@Ktwv2W?5(mbca1s@A7ksNm2Y6 zZ`Wx_&VU%b-A8U|trn^>FDv3EvVO=pS}ah#09)tKrv4=*7bkDcrNV`ZF3Hw*YN`N< z0|12{JL!5-ibVxg-H41;>|#{PUK6_Lx|}b3Sb4pl9{B}|Y3XSOo=?TFX%5zZ7MFa| zQ)-nmS0*&$q_ni*n~Y6ug1cja?r(W~$x|$JB~HJ_(eJQbru6T`@U6sFQ-0U^D?E{q zhpwwQ$Kj|keSmYh4#WmH7fx`&yglpBv<%KW|FWVzP1+z~7R;Rpj<=Jbk6>H5}!+qpdw< zUGuDBtyZpxvdXsg4cIYRP`gj~nAhMQf%P*y+qmG9|r zou4nbB~9|o2G@k8qN*4?TVV?8=|~}-8G&Yp?^Q?*5mwHLP2MsZsZAAF2Ev1@LI)D& z&ZmpGH>gO+^Q3!iX)fR9sI9K=Z62)L^X^|LhGFU>y*Hh%cAfmhBi(V9Psb}dwUvz< zJkTlTa=;e14(sH{Xw3vKKV!uckADWETCNeB_<_g?GiuzC5y}^(*A#|;LHCl;^3q|s zGh{&s@y{fNqo30_k&y6FiM}x_ySTcVYwgcpu72<;gVsi)NO?%@`Z=^tN?r8p=g;~^ ztrrUoR&`EZp3X@lCHl?R@sa0dO2UPOXS(x$m`R*GQ($T7WpB(Q6fTA2v7wdbr=GPt zFF^l-hHOm{k3a$pCE4RO>ARVz{Ib)aX(+<7B@5^IHqIMHxF$5k!7eMmXQV416#) za-gJH&M3QdGOI|1t+?8F+03i+SV=P&3Z;2C(IaCEy6R7c)ZxxG-U6ni`E20)RnD+b zdWfR){q9f%Ehe}L-eSsXujD8WViXU@-+8E4P<*#`h>IiBtDT^LkILEWuwItV%Y!*l zj?LWeaJWD{2&{{B&Hn02L%FG`R5iZuV(I+W*UlX5LZKd?6UmQPN3+kxHS`K;g{{En z$+*M^n>9RquBPT2Ss@`c+ryD1`j?9{5z-#s6P@cg(%_e`J~6#|1<@=7r-|^^x>;qm zH2H;rk+;BMBHBWgBBbY9SgZd(h?u^VcX^$HXU>nu`&)w*hK&oOTf0x=UtbtBk=a$E zxT?EUd#U8x$`|zmi{34_m7pG?!AKP;((D0a`Df2)Jt^yn-rb8t`a?^%HQ&hK|qSV#a}gO00%>J75?@&xbq5e?M{DaGy83Tb5R z0PH68{vspLB?R~8ydssV{(6~YQAoWRoV-km8`*pK_IZKT*?e&s34iQWXKJlB3F>*U_b`}%=(pw#6eBcmM&zk#2taPU2p?qW}!BT+F^R1DYRL)Rm0W8{SawghMrhesM$|`gD>1l_Yh${ zT%F2z4i#pp%Qa$d=c^}tiuuOxebD72%7@2w-5a&1!dn?-FFf(jFOOS{jP8lZ({ex@ z*13=QQ^Q$1onzx3(ekngd$pG63%A-$Z)C|bqN7nclsP?NMsOsSiGo@KBjw-Ltdku8 z}CvGmfQs%uA)dJyqv`eLnOTVY0XSqJT zfiam4-V~?N@l8L4%K>Y?9+&jLQvCCF(_+(B&93-+9|4^?c~9#G2K-%l4Kj4#7O(s zVQDJ_OXW0cD@<24I+EW5DJ<@s1M#fOa=`F>x=py_-gvb%iW3llEDWYAF|Ehye9Hzg zVZIl{s1QCYR0|sKTfBj?X~qQVXB5l~1h!p$2~OnnwL986mwAB4{uXcx&h3YhHv6mU zI=Z$wKNNWg{M(2~7^-wJgU&LH33gB3TCLbAKiNnmr*HPRwVp=gUZlk7cj_b&IIQ;h zB5p#2qlJG@r!L4LF6^n@S59J|d~|)~7bz9%?#I9P65^V2t^ap_!A8L`;zy#9t-F2K zj1fBhf>&gJs7=pN55hPC?U!EvojRZoq(ZFW+WomZV3WcMm&@3d*zWWG{zG={^mK`9 z1b=)a?r*u&KTH*DCFbp|F_?BcUt?^}hK6cF!IvNVJWLK?w0b1GH;jKI|CQC3#W{Cr z72xK;N&m)c5ey5ZrPYD8DyCrIZg&=ewH9-+pWSg{RT%uw$%9>^9nasWeXT4VG6?>M zLa)blq2m0Isho%@6GrNr`*%94zh8&(pXux%Er|V&lOEV?`A+Orzr85^2zw{LL9U)~ zV3^}@X5j<5purOEG${4mI7ah+POW3Y=kPrSb_1z{L_8U`c|IvTi6ARXw3K#AX-BLY zKZ#)KS_UszUeE|uB^JO;8|kI6{l3e9*3u=p4;QYfZF}gKq)0)+!d(juz|45HzJk8| zjCA8UXLJCCLnbB1L&Cisjf&I+1cOFoElkVvk51Vl)JN?Xty9ed|$ zes7c-dj#=x@`cG61wZeNd{BNL;b?XnYa}_};DMEbk>3g@`e_6R2dVxI{+gZ_;`i@^ zvpk#oP744H%6_O%*9`%y%+G&+zW)jXBgeSu!ZkxG5)ZfXW7M+WNuO{>$G>n2&e_Gb zAe-Z3V}xW6t6f}p4cE)na(p=%8J`Gi=ZyZkhspfvm7j>1-m1c1IhsIPy7_pw`kJE4 zuQS@wQPly}R+~!;>p=Ij!pZ|YaG0QPV_6Xpx@k_VYKm)-Rk%bIAEG~)722s9Jw>5y zj8A^5uauX_>R9J-nLOjQ5w_G>{3eXigx4Qe>8+)1e-bI;#KC*1BsRuK6> z2i|MAue-lFXi`+FaBlD#_hL2UQY-jk{zK* zjOk{|j8gVo=s@UO2Ear2*OV7(Uq}mzn9R+9yjDNo>%-!8a~E68BpnAgIkRRBW7`p` zprU4mQ^n1y+L`kI3=yxFeOw$ST3ZbQtw}$5O$9Qq8w#}7;@&#s7v8KhQocUR1JXRc zFQJgz(SA`|&eXbTQz{xvX>U|AU4Ad$Gf*6Vyj~2mAh#2=!R_|+G}7aso&h$rhvRg9gj8@oKC7-~ z#KD=($vL8vxRTSEIeq$cF~I+$)v#9nBtTqK62E+*p(Xg0lZ)x+mpGKns9hlEIB%&T zWz$30pci1Xr}3)b44}Z%{Co&O`y`KT3sno<8hJ|61t%ar!cFL?6o_zWktkYOYipB& zO86@;*H;7S0Sl~!CHmhanT6`pQw2bF=eNu6fnG^f{XEx7F9Sfkm?ff?g*Qd-l6oBX z7XV_4yO-++DDOy7md|?#1hVV2gHyJ=SQ_@&8*eLR!9}1PJ3UM<3H8B>cMI+1^ZKk= zVDT;_h7LpIz2AkY8M4>Jp>4rxi0d$Q@9rH;5G;jS^|(7>x|f^O`1Ylv94OAZ;!5~E zyM4F}F{-u+ySZS3)?EI7jn#%{^$EECNhF0l^rl&=8RK@lcssz+Ye{|UpvO(HWCetf zxSDu`3*B_SG#}(P4_s_J{EgAZUjX@lzeTJ<^T%yJ8A_9{%;q*3v)t)8!+X#&4$eYY zSD@S932ji|(>xDiJL}qY1`2r@LPkYTUY5Eq;8XR)rNYwGt6$i{EQtpl%_%2*0dnu| zBoOXSgBd(!*{2&x2JZ;^2d|m{S$I7h&xu|_WarB(X32{gei<312n+XtnrSaFjiIzA ztF#U>n;y;?CyQJ@v&%y#SGU_52k|Vw%kzqgn_qj@rjL%3%F6VLFnn)rrfh0nYHB93 zvwb2bb$A~WKRXXOfNozx#rY*AMa6Ec8eo7HTx9m{u(z`V5JZB16c&DKZXO7`=ah{9 z`e5-koL0PeNW*}};_W+QRl7aUEt-CAu+6u!^m3IPRUiQ-+Z0CM3+dND88$1HU|!LI=$w z!W-)!)YelOptfbY>Ag9B&q?vf|3MH0C+EBFfYEh*T{mA}gH|o(kbRT#OO_l-SB~HP z90P_mCy_ZcpFd>U)*aV$XtQfKAy1UNf5sVw%l0wtCn2ez>;AeHJ=~zh)0xhF1yerm z^IS)u{*)j8_)5Ume`dCuKDYcd!Ga9vlmqB?T6QnDRvymsnhz`Y08qDVsZlkjkdoXr zFK=V!++O{567zPjFXdqR#SDu2Gc4*Aew4t7&hojHY5(_CtaWK%u{3~s{C2wpA|`y< z$Ry*Nh(Q46b4TQSbpxoapzhj4>Hdi%P&yob2^<1{{Nz~PB6MPE zX$kkh)&Kby%I^o9qht-Lxm?B9`%{G2T|lx$<$CuT0Nz%Bc5wHITJB%wmifuI?Bb^Fm*PzS z$=k|Reyx}tzxwdkMlFKCAD>(XooXax&iq*bOEWeyyeDOod4GS;;(M;n@nzteW&fWT z7E!==v>6~*wGSc|@cN75UO8-{t{gBFm8iE!uRXCyv)!7e7ZIOvR~3h!@8LB>{Oa0` zZK8S=dYLSr)6p{tnQg~8{?-65bSmG^sJn6RT~=vZ_Fa^13_H5somnl)D_dwp#fOe9 zSHgu(_c6SwKQa)pJ(2@)*U!_g|2W?QFt^w0vF_VTrz`WL@3Esbr^ki@?>v_;BsuP0 zz%jOc@FowDSlc`A?jH*$9=j{VV~ywGm6iNYo>;w==ct>OhHMt?d*oN!iyJKm?(@e3 z6LG`lrrmIwpXaTo6;>q9Vq@|rrNwz-F>&<&8PTOU`&WM3zb3kMm{Sp|tl#T-6i}l> z1$hW*9?||#lvu#$mSqbQo>tV#h+9l+5;y>4z&FsJH6De2XVsqPY+4Jz#&=e*bHGG` zcQd%l%L1ZUmnMI{D&~&{vRU1#ic@ZD=#X%-A}UexYib<3`kLUdMuyENf_}p?RyA^p zdTl{{OaJ0#P0NU}Om%v1M3a?NsP-Qu_uP{ZcW<4cM%sUKU{fE%VKKnB7O&DCJP5-L z$}@Rj5cWGlV&KRT>_~wND8EC?y-JVJ#lp4NiY~U{S3^T!7N~xc&Dc9UK-MX;`nRaq zr5vzQ_HuGBe~YVn%91Bnl0K8&14KIl=I2cOXg4-7{Jqbt;e_!CwmpNhP64@Se|d-o z6qG*snI_QdQ`7ya0O8tIWk$O5WABb(r_nErK&Hbre$RC5Mj+~}b4%x;H<V1SuMx@ zDuXC$HTj9Y?@HRkUG1uGdUub3FlKy3hc#>rm>`G|C>=ubRo>ZAc2UIPmohFODnR@uFk7j(5x!Tj6}Lmr%K8$ zFLJ;G;GMJK4GECpXbLkYmc>A!^_g=wKEIx!5^?tvobp+C@xO(`oUZJIL>44Jsc0SX zLoC};!DMR}{~;ikH_ViK4kE-sineS+Wc33KTXN5+C#@x@C(L9J#9h+VB&IChp~4)I zA|f{4WCE=NhZa#r?M=LJp8k4CQ4Y`NN2b@C!sh$LFyqw;~lbvpS44 zvi{<>X8(@c2ESYw=p}tD0Pxad2I6e#zj!R2(O;zbE@b!5@wXMC4(MLLu^?XIKdf2- z`Ug`jf>#jTjzE9{^TltiS(|1tJ$<9AZB=@gm2jBlOU!x8N$$rg^0$(WSJyVg*jy`k zaaq6gBstqhKm&wtJ`%n8NRQBb=eAQJ2QFD#)}X8W@6cLLx_?1y;r~Qy15IeIrr4L& zrVZ6&Z&9E$z+Hi=5je!ba$A+(FS(z-_SW2OejNYi!R3LE%l6Q+ia6r5z+tDsXa>8v0v}2CeUs2#d3$zj(7l$Z48SSybwK%GU1WH3GTz^QmH{P$6nO) zptHSMpr6lhJUfSCr6V*?NAT`}(N8u{fJoBOix;qnx!=sgd1`vF(-skLi?;->Zp^{j4B4)Y9dyf{~bb`@Bu^` z)^3o5(^mAEpsBsIYme7uo&-Lz5@chBTnv{bVWR&vFuLm=s-=KD?8pj}Vk{Q@t1?8v zQl=z)@H6h=3gL%xlC7CB1pEW?8-oq(%c9ur`9N^?peFZ!VzW1*wq>0HBKU#FXdIQB z2G#%Hdb5FoGLV1sW>Zb|;6MU`bMn)2EL?F&!&dP7L~}EcV}cG3(@#~bha8I+u{2MD zk^JrLMlT>_?_wiYA9y) z$smWS!68NU`X{aUhV6MyfjVu@*tWWw(Qxn8bh+tNTH?!ipya?p!x@|=8rdpRFAA`O z^ONF`D0KAO>eFM%fc3FINk3;l(66^ag-SriNzaF)tEY?qPX$eX-;xVZ9AqJFkAHr| zm#aO|&YmYVS2ecS_oTMxSy{x^BQ9?4Ja85ZEdB6eJ4^gwD4JY{#Ou;Jq!G5TfYa95 z%(ox?m2e+j9OY=0Lc4RwRLUP0&iwACSVH%1?hSmT03z~W4Sy(k10`JX$L#ttLuolF zrp!Hq;F8aiD%V&#v4CO`UIRKXPM!yp?c5V~3ydYMLq5M(F-rT;HJ6;?w*GpbkPaT> zrZ4}(m`%o*wKoG}*lQSP92zGYCQ(m{7QZ&~R5!A0f&U(%l$SxR5UO>1mZy>&I{u}| zisD6@mfOKi1In<_B3uj=xCW%<1hTMEwMhP8OaMvQnqD6vMWEm0r2fBR%f^{f(*E6- zJ=D!B|3Bo)B6PW={nxwql9I$v%FF8~G&1uG*`9E7^FM0WXGSOSy9_k#AuQr2C4V&w zh-MSt8-d<(0&$|+EMno%u$cgAE=IUku}&&0qfQPN##0xAs5~5cv=A1Pq@?mMsq3`# zm7ukCaR@=*2%vf?sBHwtZh0sI>M$!}tigh)L#Yo79&8xSQN{_aym{(WGqN^O+Lf0~-^z zmvf{B@p8nc;wcA}^?l9X+OVXcrI8R5(aF+63JZGy(&)hvn4Xpfrs?h;3a$A<#LvH9 zratpuFlG%6V>&hJ;^kwMys8TOHRx76trAYq!qMI@HBNdbOxOyr#cUz8bp^U)x7cdp z_L^`7A`a?d^b@){*Z3-2Mjqh0lP-lDCPv;73Y*@y7kctrPa zv3de3p2nI7Mq$W~b)vICppxM4wAEAjsIIOmQc4l^fXOrAT$sBy2C3uy0FAmapjt(8 zs%KV43&=tJ_k2`vcnPklO_&K$YcK!*!&U!R zOj&@d2C1?RaG;D+1yK{*&m0TcFbj7=KI5(u-2@g6_ZONy&AhiyM+HHcJR;buNbDC)TZz_*BY(l+!UYtqI^Tbs&w%vNt< z;QoIgt10wE$@)Gq&2olCvf5c1IyRt`rr~+C`FT;+{MgV5#Bn@-q7!Mg$K~!US8pY} z_V?Qi2MLUnmB-OoaB=*=^HTM@?17Vc-e=Ub=fL!Pdm89(wY?m7QL-ptQ-RUo0Gs5; z><*$LYiFt-O!LbY^^x63NObD&oBbB2o~@;PFly#xklO0tP~JiaBz2`Ee5?O*>9+1% zI@FMsW->WBuIOk94VCf>*fo%LZKa++&LfQV^_E!OuG{JTvaw^`Ab(!>fTi2>5Wm{X zEB5#jgai&}$&%WhFDs>vBsy*HiSh9`1LOvRMRbwSSE`|5zSt~U`!-R0PU3HI*LR^I z#Zu}3N`F}ReXQ^VXlDdOHzom8sy!i1=mf-BC5r=M#Y(o+`p$s|P4Rd0f0!Qh@-x2c zRZ3soBjb+eGXz;gU9?koGZopvX>Zq8yQnc_T}z_zd(iesP-)vt4_28-wFMy8MDNh) z78Dn%PPdA?fB)Od(}7KQD2ZTnjnF?fF?l<+zPG-N25^&gAs$fo(t@!dTED)zWSLSjePC818BZtK$!oF3}2;;L06fBigTwR<|WgC3fk;P$f>zO^wm z0b$a?oPN~BU_*5OSc)kW4KbCp;ECvloyG$-r3kv#X-E{xtAbDq;0k`*gn9efxP-K~ z_EobjbMkJvj1L*&yD>2XZ_dVjuXAT+Y;0_RvJ-EJ`FfM*AP2_;WcpvkeC0F)xws&a z_{rZBa#e~t=WFK0m%j7PckzD6FfZ24s2P{t63bc6Kj<)kY+A`hSJcHhN~gFS+=wQ( zm~Btdie2kWUSA0gpcy*{>BOZB**n+!(PR}bZGR&ob_2o?^C_W7n33Me)cErLh~g14 zRVprN3MtA2+dfO@CUQ9UIR8H8q>=sGUL_X82k+NEb5xu_POaEndO6BEmdGxkoSOp- zv+Qp`7fa)6^>PQA9c-KV%8uf&{rGD?UlI=L3bwjwZ47kT-L)>TNnSI18E7e?Dtewk z^A(GzrMV`bfRSGv{bQkt%98V^pgG^Ghgu1G1=bG~(CLrer%dYpo&^ZK*K41E$^hTi zmTiQMQC`id<6LicVR2_r&DDSl?p`ntnWe10cV#-bb%kJE5hi#ivICXswDmBv4?h-0 zm$HT#7nh=aM=KXB5mW7t-$#n=5b9IKrDW~oBvR4p^VUwcVO=g}otVu1zO6teW}#Fh zR014yCIRpp^^ozEPj9%B0JaKeyvla@_iXif^L?PC^RBoxnUIc7(`_5!2_*-dR1}H` z{Jm`AETH}>B;iFg;*a^t;O%`^C-x`E{O>BVLZq?lir7msI5lRt|3+lL$K&iTQNcDj z{_F*vEx{D{pVn;W8EyDd^r zx#c>^7)jptV6F`<&Su91v=|N#@!9|@)i@>eVJpKg{l8u+?DFU%6RJEO- z+@i2aG!8$OnfV{kReG$y(N#rD5GX0>|9Y|i%U-Ny`y=Nd)#GqezSt)bXhuAEKc3mG zo2$|P_z(Y2!5I%R6*~|7lZFM!M~(LZo3}@;E_KeZxE{K_wAWQ`we~!FuxmV(4)2D( z^h#TXVjw&jr5Sg&d|oAxkj9}jO8UP{Utj(A>1%~_v) z&vepNUVkahd?6c4E9j(}J~6~tH6#p5-uj@Rh2Tqj8;h7xm=W04o%TseSwM<{9SJ#Qd^{RnL`q29<75rvz`UI9 z_WlSf%hIuY+G6{o>WL%@Vew}_6qCi+f(YA4lZbwz#RU;5o<$7>k}1jxSsqxOHB-=7 zd8Ui&7-*9TF_#-Hj4?QxA{q^`qfx)3;t*T>fb+{?9oLijc$Jwlf3wvz)%*~dR#gVE zMiC#TZB&}&wk;)>EYDC{5(YD)O0^N8O!n_G5a%e)R|E-<;J**{@ioqhk*iQJj>K5+RqvLSX*nnzfbh))Z*`=1w^Pr!SUugU2K09Xv8NUQN8Lc;R zo_Q;t&lF65B)Wo>&@n;)K1GI!>cc$ z@g+*nx68iNQ*PWACEJs+Ur!DWO?9H=3+@@6Uw(K*4w7cL{~mQNh#qAd^?Ne`^#kmc zUZ=b!iyOl5frK8=`pne#S~)zzx)ND?-v!_2&`AiUBMMa;)n^;o{?BlQ^vl5R6_Ge& zpEL;XJQ-zK@Yd{4Qrq~ieft-5pRo?6jq0dT)EjF;dTOv~H#5%tOsh1!>uR*vj=a0T zcDX;x3w4$Q!>0npd@|sA_%xUas8lOF#~3Ipbk6r@@-F?N1=*~IjAP_FEh`M{X=Gnr zm*Ia3y1S})pNcUX~ZsBsM71xWpr+-sAI4>tu>>}ClyY7B^&6}Z#3vB`G2P1SZ8;x`j;l|a z{B@7pbnmwl&1KNLK8xxC+H*fr6pOizt~F2{b!5AX98;Xg2^8ozC;0osGYKV=pU{E`txZf;g&rBvMC3Wi2^t?83>z$W)o>Gqg>2TAo zFSd#+>ar43oMTk<^q`#ncU_e7TA>kYxyQR^W)v(a&p1~~;47Jl%wY5-w6UN}1eJNg z_k-2Bu5z&4TDPg2Sp3Oh`fn)plaiRPTF}&w5rgk2N0sw{(!7W3U_xw^!l2PZykE!GeJ3Np|4;t$iPtmn*0 zBA{M@SB)jSi$lpq>h&~LQC_8*)l>CzB1+Due2&s)fj%h1Xs?3x+t3_nx5m~lv9n#b zU<9;KX*2hr*UXaIf!CpDpeGwNB8}!v_eJ>;YA?`7gV1JhIZzL??d*TXQU6e2mC)1k zt*)+?&C)s8_7W0G=r6%Mtx0T=405=>mSoYuWRD%6b@I(YYnxvRd~3avFfxKCD2U~_ zfGy#DyiL(rCMRKGCqCI_VP|CI`XWq+3ke&`N#Zp_i7v0eaq&WmaC3`F82nK258Ng3 zXr|7P9v*iyQ&Ji$)+Ll!O8al^od-}<@3!Sn)8s5jmY|44K?#zB2q;OAELo78bB0Dm zBr7@RoDq;rw~{3193|(RQ_n%~z3>0#&dhyps%BnI)mU9+(cLs~PM`1FYyZ~T{q0-& z$B(gPhIJL=<8~T_g&iGC92^lPDh^!55;Og5B+e{LD=dNT!q-ayZ;*|ymt(_Sh+Ez= zmFv#R!@>QKV7yQTh_Y{y7$+UN$f!r#BC9@*EjlK7->v8#J$kzX=R4j7dG;2|$dFQ( zJr`QyxnEE^xi1hw0m(C&-%~aoMO|TuO0Ta`)gkk0BZ=6)LWS7;=puZ zG;S*PLvy0Q{_zkm_%*5+%TAvcdMWoKmI2<1>S9X=clD?ICR2lQ51erH@0Q|WqHII! zeDQE6;ldkQTk`dh=k;bIoF9Y2uZ1`UpNEP%up+NgBDg6-l(Gz}b1AV<*L14F_RxuE zr#MgZ0#;Z9CzigBW_R@q)7(BB`Vc%&pL{&nF284i^%+wIlBd~@Nr!q${sR3zVx^%y z?tpiHqw3jnwCYLh{0~P!7r*wx%@t)!P>uh=EXISaVhJ-Taob(c)z&vm!QRz1*Z+CR zSuKyqb+Sf1vNa@`nB{#`TgVuAYSZb5n!wva%9}TmAt8=!o}xb2>s@kBm55@R0`?E5 z&ZZn9FHKd30)uhCZ%>1#4TU!4U9EtOx9LoM2tU8btoLNGV)g!6=Yy9+dG=*rW#WZB z+@wBAq+!}S2-YDYE62CK?4=m(h^j-aSCKyjh77* zr9zz#_3d9=&}iUc0_=oYysL$1)dVH<6^E|fUujbhMqfyE@W&DB>HF&?R2FBooVpt%Ce2z&j9 zO~k53NVUW+=|CFSy0&36P5UoV<(XfT=^pZdGs)`0M#u#4SM z+||IjH?*N%-X;<&1-6ltx6^%p&(t$?L(5i9mKe=;`7Y@cMiZ zCK`A}5RLMJ!w7`3`qBIz^YWguXSdR3EZ6m2H9ze>&yu;nFE3qF>$sMo&hiYK%O3kC z=Pq^%l_82rg_pBsGW5#i@y+CPN%8QFkr+;1R^a`T+ucfQCH zr@IWZh3gz@)TI(#fG>9QkT|kzb?&0PQB!^s)a02;YaII<>l#>CoLS-9FwKBwfye#k zqwEX*cv$-o($CORVBB!^HN+J~4F+iBZz(pVdOyHKo@gRJ_+4Y+tZWAC5C~_l?(Cc< zAXs6k{=!$DG{clfq2(UW;M%0;OJAu?PVzmxG-j%W;V2^$4cg4j2n!hX9IoZScBDvq zdzNAAZlqKd(h_4!Kzb^Oj! z)a%!0BazHx7UqGJRHE+ZYc5bIt7Q6cTpXFXd9~%Sr_BzBNq4${fLc%sD<`MDg?VC8 z;i1Q!z{P!+ujR^}9g8fgnK>rl0$o&7gVl4&$mUp1B1g-A?YJh%*w_@BTjeA_A<`|w zuXSt@Az|8H8T;hN&dx0x%+q7=fNedrV(Y5@(#Z94`e)MI`caE46=0ew&HO^xnWtRZ zes;LkZm+^E=z-|0iAAOuT`9f>8gR<0h@03?>OVvpAqphG%;|t?V6)GA6uh`UK+Hb| zNwY}Y68X+pY}Bc`?~)v%#cdRN%g3X2iv&6D>iW!)n$lDWdoWaoe~_tW$AD||2tj55 zy|+3qozwQ|I*r6<;d~Z#|6-$!*2e&&l7|ntdW$^h#$hWJ3Gh_T=f1A~R_5WxzQY#}>&%WbW_xAdS37yF_sk}+ z+{md&a3u+wV9`gjy=4p0g?{6#A=~1p!g-SEUB>+=u$K08BMfWYC?=GBe0zhl_T|u} z^+fTcd{lpg@tThxC_{=NgTCkpe884C7Iz4GEXGrc@)HeAFhwXZn*5w)<*5?suK*?zN*T7;K;8z z3SPO*tMz?&VsfQ}gE6`4+I5=}u+K_YW>#R9bE^2-$zC^<7pWB+mjlYn>ysC-i?P*! zH#IKBp7BuzhHprgPJ$cKygvDf-+fof_3M0a%X5zJ5iurY8))-Qr!m_BZ1HU$4-J6R zKQo1AQoWV)$SM>6u3a-HMh4F;?pvcvGt0>e`HT(r8#=uRE`8=%SGMn)DCLtvUU5pb z`0CK*ecA!J@MAXH=2IK&mw|7Uyv~xMDKS{7lH+P*GMr1lHVi5m%1i-c5F)F`IT@9K>ZVCQ_gll(>uXUCP0qR?oxeDl? zQ5O$8lW6_BXX4bo=4NrnJ)58NW{N8EgM^9LN3m&j_$69Ps5B( zsNDG0Q^8UVHUOMKC6=++C{q+TQ}@b7x2mPt_b$3C!ER>FCTF z+=yY8y7Y>yc1pN%F0IJwxD8m6PF7$0rotC&w2=sd_9Z8lCE8vcdgTsvFJu5iO#iae z(2gn)X@*0FGZ3eg8`_GhJ5Jf|n&kJeR0NMW*^X|*pe7ET zr)8<#Mcf_^!UAEOO2dR9A(na9N7!_J?t494Yq@a7X?xeiA?D_22jxFW zMhiu$f}sINxbHigu1CxXvLm=wY*tN?6d6$PPpaAPq|HRK-Ua6aGfam3jN6O3NBIf; zHbPAw%a&HhkUnXO&`A7O|G+>7I8Ow-#XuBZURI`J%@bSFu(<`X?Cjm)Pvg{ZOY8xU zJP9y!e5@t@tm?x@-P}BW+Xbn)@9#z1$h~>ynYAYK*x9uX_QUD#HQS%9#IUynQ$Y1U zgvfuYyJ&NBYyb6&$Z!5YHYRsr`t;H*IT;+~6>i*ZKexACQAxtX-5g9knbqAB+GJp) zswU;;7U!82pJ2zZA8MRes?02^{%UArk3#|X;-qDvt=JenbXPfFwJIUsI2iwtk*yGr z2~~$l(UD_9f=gUI(JUc700b)VW8h|Qnh9;P;Ze2jzJ%X8X20GxL=o}?n&sjvFMgDP zJs8eWUX}Y1&P)QLxO#6SM3ZO)&OQghZ(VW1SSoU*nWRj3kFU;&fxP->ClrVQMDB~( zzWLg(-D^5%ONn+0TyaAWVSb1wbePoyo9Is-St5@MZ7O;9l-3WjUw4wT%bXw7-;{h^ zMVBW&F9%GyWuiKo)6MS_qFSPbL+s%7dCk04xZdXTXMyR?HJg>p4vt|MXu>>qGq_7~ zt{m-^dpe2eZsnpVRfgXZ!`yxR8Qkf5J#NnL;;4;(D7I}Ci3-*RB-Ww2b*bwV2kg92 zV-B*PXqa~165yXca^9T-b>rght|CF0?tznq=Ox(LL55KM=`m21%^u1~J_ki=u78_o z(+{xBT?;+)zPX^0yBWUar(> zS#1{4S3nZj{yCm0gnLGQ@w{B;pfsJq^p4BFuZ9Z8CH1b3KN|L1Kxw@Cx_00ZlJitp zYVjGRIs4YY4ynuU0!yRE8e(1ikl^0~k1Ws0Gt&*30zM6DH@^I}zSlVlE~$En=$F2Al0Q!j9FaQGcf8_^Rv>;CQqh*38-TGCR^)-KFrHn+T7UCWup!!5iW zpk`tWuED>)jvq8Mz!Q0b)>kzil9v4Z`Lig`?%UUa9XqD*&e`^!mk(JZ3RJ!%C%50a z^=*0i0pCJOXsQg!+!x<9F4tP)(Cs$PhmzpDsvu(PWQJSL(^NW+ zK7{?7FpdA}^8bbD|7Bq+oHJ=8CcGWLz2kxyb(cC;V612}?3TEbJXwL#QNd+d0qK}|%zNjPg==t-B;Kg;-0 z`x0-T>AbGL?O!WYgQ-m*;EBx+EGmO~MFJN9>;%6{#*(ADFB5wy_(>YR}v zEz0JHxO!CpDT*P?SPVrX&J+pu&xML5XQnM;!Bs$2Lv{Ym%H{?qC8Ec{zgYP=D1Jkd zU^6G;q`O2KMz9MNtF#xulrS4~W}Cy~h8pN6ր%Et@D|L%H)4idZ5mL1lrzO03 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 + \item \verb-connectmap- : Connexions in order to make the netlist\\ +\end{itemize} +\indent \verb-param- and \verb-map- are dictionnaries as shown in the example below. + +\subsubsection{Example} + +\begin{verbatim} +Inst ( 'a2_x2' + , map = { 'i0' : in0 + , 'i1' : in1 + , 'q' : out + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} + +\begin{htmlonly} +You can see a concrete example at : \hyperref[ref]{\emph{Example}}{}{Example}{secexample} +\end{htmlonly} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-Error in Inst : the model Model does not exist.-\\\verb-Check CRL_CATA_LIB.-\\Either one has made a mistake in the name of the model, either the environment variable is not correct. + \item \verb-Error in Inst : port does not exist in model Model.-\\One port in map is not correct. + \item \verb-Error in Inst : one input net is not dimensionned.-\\The size of the output nets is automatically calculated bus the input nets must be dimensionned before being connected. +\end{itemize} + +\begin{htmlonly} +\input{see_also} +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_library.tex b/stratus1/doc/stratus/man_library.tex new file mode 100644 index 00000000..66e78355 --- /dev/null +++ b/stratus1/doc/stratus/man_library.tex @@ -0,0 +1,96 @@ +\subsubsection{Description} + +The virtual library permits to create a cell and map it to different libraries without having to change it. + +\subsubsection{List of the generators provided} + +\begin{itemize} + \item \verb-a2- : \verb-q <= i0 & i1- + \item \verb-a3- : \verb-q <= i0 & i1 & i2- + \item \verb-a4- : \verb-q <= i0 & i1 & i2 & i3- + \item \verb-na2- : \verb-nq <= ~ ( i0 & i1 )- + \item \verb-na3- : \verb-nq <= ~ ( i0 & i1 & i2 )- + \item \verb-na4- : \verb-nq <= ~ ( i0 & i1 & i2 & i3 )- + \item \verb-o2- : \verb-q <= i0 & i1- + \item \verb-o3- : \verb-q <= i0 & i1 & i2- + \item \verb-o4- : \verb-q <= i0 & i1 & i2 & i3- + \item \verb-no2- : \verb-nq <= ~ ( i0 & i1 )- + \item \verb-no3- : \verb-nq <= ~ ( i0 & i1 & i2 )- + \item \verb-no4- : \verb-nq <= ~ ( i0 & i1 & i2 & i3 )- + \item \verb-inv- : \verb-nq <= ~ i- + \item \verb-buf- : \verb-q <= i- + \item \verb-xr2- : \verb-q <= i0 ^ i1- + \item \verb-nxr2- : \verb-nq <= ~ ( i0 ^ i1 )- + \item \verb-zero- : \verb-nq <= '0'- + \item \verb-one- : \verb-q <= '1'- + \item \verb-halfadder- : \verb-sout <= a ^ b- and \verb-cout <= a & b- + \item \verb-fulladder- : \verb-sout <= a ^ b ^ cin-\\\indent and \verb-cout <= ( a & b ) | ( a & cin ) | ( b & cin )- + \item \verb-mx2- : \verb-q <= (i0 & ~cmd) | (i1 & cmd)- + \item \verb-nmx2- : \verb-nq <= ~( (i0 & ~cmd) | (i1 & cmd) )- + \item \verb-sff- : \verb-if RISE ( ck ) : q <= i- + \item \verb-sff2- : \verb-if RISE ( ck ) : q <= (i0 & ~cmd) | (i1 & cmd)- + \item \verb-sff3- : \verb-if RISE ( ck ) :-\\\verb- q <= (i0 & ~cmd0) | (((i1 & cmd1)|(i2&~cmd1)) & cmd0)- + \item \verb-ts- : \verb-if cmd : q <= i- + \item \verb-nts- : \verb-if cmd : nq <= ~i- +\end{itemize} + +\subsubsection{Mapping file} + +The virtual library is mapped to the sxlib library. A piece of the corresponding mapping file is shown below.\\ +\indent In order to map the virtual library to another library, on has to write a .xml file which makes correspond models and interfaces.\\ +\indent Note that the interfaces of the cells must be the same (except for the names of the ports). Otherwise, one has to create .vst file in order to make the interfaces match.\\ + +\indent The environment variable used to point the right file is \verb-STRATUS_MAPPING_NAME-. + +\begin{figure}[h!] +%\centering +\includegraphics[width=1\textwidth]{images/xml.png} +\end{figure} + +\subsubsection{Generators} + +Some generators are also provided in order to use the cells of the library with nets of more than 1 bit. One has to upper the first letter of the model name in order to user those generators. What is simply done is a for loop with the bits of the nets. The parameter \verb-'nbit'- gives the size of the generator. + +\subsubsection{Example} + +\begin{itemize} + \item Direct instanciation of a cell +\end{itemize} +\begin{verbatim} +for i in range ( 4 ) : + Inst ( 'a2' + , map = { 'i0' : neti0[i] + , 'i1' : neti1[i] + , 'q' : netq[i] + , 'vdd' : netvdd + , 'vss' : netvss + } + ) +\end{verbatim} + +\begin{itemize} + \item Instanciation of a generator +\end{itemize} +\begin{verbatim} +Generate ( 'A2', "my_and2_4bits", param = { 'nbit' : 4 } ) +Inst ( 'my_and2_4bits' + , map = { 'i0' : neti0 + , 'i1' : neti1 + , 'q' : netq + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Inst : the model ... does not exist.-\\\verb-Check CRL_CATA_LIB.-\\The model of the cell has not been found. One has to check the environment variable. + \item \verb-[Stratus ERROR] Virtual library : No file found in order to parse.-\\\verb-Check STRATUS_MAPPING_NAME.-\\The mapping file is not given in the environment variable. +\end{itemize} + +\begin{htmlonly} +\input{see_also} +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_mux.tex b/stratus1/doc/stratus/man_mux.tex new file mode 100644 index 00000000..a1e8320b --- /dev/null +++ b/stratus1/doc/stratus/man_mux.tex @@ -0,0 +1,135 @@ +\subsubsection{Name} + +Mux -- Easy way to instantiate a multiplexor + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCmd.Mux ( arg ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the command of the multiplexor. The nets given as parameters are all the input nets. This method returns a net : the output net.\\ +There are two ways to describe the multiplexor : the argument \verb-arg- can be a list or a dictionnary.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetMux- method. + +\subsubsection{Parameters} + +\begin{itemize} + \item List :\\ + \indent For each value of the command, the corresponding net is specified. All values must be specified.\\ + \indent For example : + \begin{verbatim} +out <= cmd.Mux ( [in0, in1, in2, in3] ) + \end{verbatim} + \indent The net out is then initialised like this : + \begin{verbatim} +if cmd == 0 : out <= in0 +if cmd == 1 : out <= in1 +if cmd == 2 : out <= in2 +if cmd == 3 : out <= in3 + \end{verbatim} + \item Dictionnary :\\ + \indent A dictionnary makes the correspondance between a value of the command and the corresponding net.\\ + \indent For example : + \begin{verbatim} +out <= cmd.Mux ( {"0" : in0, "1" : in1, "2" : in2, "3" : in3} ) + \end{verbatim} + \indent This initialisation corresponds to the one before. + \indent Thanks to the use of a dictionnary, the connections can be clearer : + \begin{itemize} + \item \verb-'default'-: This key of the dictionnary corresponds to all the nets that are not specified\\ + For example : + \begin{verbatim} +out <= cmd.Mux ( {"0" : in0, "default" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd == 0 : out <= in0 +else : out <= in1 + \end{verbatim} + Note that if there is no \verb-'default'- key specified and that not all the nets are specified, the non specified nets are set to 0. + \item \verb-#- and \verb-?- : When a key of the dictionnary begins with \verb-#-, the number after the \verb-#- has to be binary and each ? in the number means that this bit is not precised\\ + For example : + \begin{verbatim} +out <= cmd.Mux ( {"#01?" : in0, "default" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd in ( 2, 3 ) : out <= in0 +else : out <= in1 + \end{verbatim} + \item \verb-,- and \verb"-" : When keys contains thoses symbols, it permits to enumerate intervals\\ + For example : + \begin{verbatim} +out <= cmd.Mux ( {"0,4" : in0, "1-3,5" : in1} ) + \end{verbatim} + This notation corresponds to : + \begin{verbatim} +if cmd in ( 0, 4 ) : out <= in0 +elif cmd in ( 1, 2, 3, 5) : out <= in1 +else : out <= 0 + \end{verbatim} + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = SignalIn ( "a", 4 ) + self.B = SignalIn ( "b", 4 ) + self.C = SignalIn ( "c", 4 ) + self.D = SignalIn ( "d", 4 ) + + self.Cmd1 = SignalIn ( "cmd1", 2 ) + self.Cmd2 = SignalIn ( "cmd2", 4 ) + + self.S1 = SignalOut ( "s1", 4 ) + self.S2 = SignalOut ( "s2", 4 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S1 <= self.Cmd1.Mux ( [sefl.A, self.B, self.C, self.D] ) + + self.S2 <= self.Cmd2.Mux ( { "0" : self.A + , "1,5-7" : self.B + , "#1?1?" : self.C + , "default" : self.D + } ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Mux : all the nets must have the same lenght.-\\All the input nets pust have the same lenght. + \item \verb-[Stratus ERROR] Mux : there are no input nets.-\\The input nets seem to have been forgotten. + \item \verb-[Stratus ERROR] Mux : wrong argument type.-\\The connections of the buses are not described by a list nor a dictionnary. + \item \verb-[Stratus ERROR] Mux :-\\\verb-the number of nets does not match with the lenght of the command.-\\When using a list, the number of nets has to correspond to the number of possible values of the command. + \item \verb-[Stratus ERROR] Mux : wrong key.-\\One of the key of the dictionnary is not un number, neither a list or an interval. + \item \verb-[Stratus ERROR] Mux :-\\\verb-when an interval is specified, the second number of the interval-\\\verb-must be greater than the first one.-\\When creating an interval with "-", the second number has to be greater than the first one. + \item \verb-[Stratus ERROR] Mux :-\\\verb-the binary number does not match with the lenght of the command.-\\When using the \verb-#- notation, each digit of the binary number corresponds to a wire of the cmd. The leghts have to correspond. + \item \verb-[Stratus ERROR] Mux : after #, the number has to be binary.-\\When using the \verb-#- notation, the number has to be binary : one can use 0, 1 or ?. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a shifter}}{}{Shifter}{secshift} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_net.tex b/stratus1/doc/stratus/man_net.tex new file mode 100644 index 00000000..b85d9108 --- /dev/null +++ b/stratus1/doc/stratus/man_net.tex @@ -0,0 +1,118 @@ +\subsubsection{Name} + +SignalIn, SignalOut ... -- Creation of nets + +\subsubsection{Synopsys} + +\begin{verbatim} +netA = SignalIn ( "a", 4 ) +\end{verbatim} + +\subsubsection{Description} + +How to create and use nets. + +\subsubsection{Nets} + +Differents kind of nets are listed below : +\begin{itemize} + \item \verb-SignalIn- : Creation of an input port + \item \verb-SignalOut- : Creation of an output port + \item \verb-SignalInOut- : Creation of an inout port + \item \verb-SignalUnknown- : Creation of an input/output port which direction is not defined + \item \verb-TriState- : Creation of a tristate port + \item \verb-CkIn- : Creation of a clock port + \item \verb-VddIn- : Creation of the vdd alimentation + \item \verb-VssIn- : Creation of the vss alimentation + \item \verb-Signal- : Creation of an internal net +\end{itemize} + +\subsubsection{Parameters} + +All kind of constructors have the same parameters : +\begin{itemize} + \item \verb-name- : the name of the net (mandatory argument) + \item \verb-arity- : the arity of the net (mandatory argument) + \item \verb-indice- : for bit vectors only : the LSB bit (optional argument : set to 0 by default) +\end{itemize} + +\indent Only \verb-CkIn-, \verb-VddIn- and \verb-VssIn- do not have the same parameters : there is only the \verb-name- parameter (they are 1 bit nets). + +\subsubsection{Functions and methods} + +Some functions/methods are provided in order to handle nets : +\begin{itemize} + \item function \verb-Cat- : Concatenation of nets, beginning with the MSB +\begin{verbatim} +Inst ( 'DpgenInv' + , map = { 'i0' : Cat ( A, B ) + , 'nq' : S + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} +\indent Or : +\begin{verbatim} +tab = [] +tab.append ( A ) +tab.append ( B ) + +Inst ( 'DpgenInv' + , map = { 'i0' : Cat ( tab ) + , 'nq' : S + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} +\indent If A and B are 2 bits nets, the net \verb-myNet- will be such as : +\begin{verbatim} +myNet[3] = A[1] +myNet[2] = A[0] +myNet[1] = B[1] +myNet[0] = B[0] +\end{verbatim} + \item function \verb-Extend- : Creation of a net which is an extension of the net which it is applied to +\begin{verbatim} +temp = Signal ( "temp", 5 ) +tempExt = Signal ( "temp_ext", 8 ) + +tempExt <= temp.Extand ( 8, 'one' ) +\end{verbatim} + \item method \verb-Alias- : Creation of an alias name for a net +\begin{verbatim} +cin.Alias ( c_temp[0] ) +cout.Alias ( c_temp[4] ) +for i in range ( 4 ) : + Inst ( "Fulladder" + , map = { 'a' : a[i] + , 'b' : b[i] + , 'cin' : c_temp[i] + , 'sout' : sout[i] + , 'cout' : c_temp[i+1] + , 'vdd' : vdd + , 'vss' : vss + } + ) +\end{verbatim} +\end{itemize} + +\begin{htmlonly} + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{Example}}{}{Example}{secexample} + +\end{htmlonly} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-Error in SignalIn :-\\\verb-the lenght of the net must be a positive value.-\\One can not create a net with a negative lenght. +\end{itemize} + +\begin{htmlonly} +\input{see_also} +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_new.tex b/stratus1/doc/stratus/man_new.tex new file mode 100644 index 00000000..9581f186 --- /dev/null +++ b/stratus1/doc/stratus/man_new.tex @@ -0,0 +1,15 @@ + \subsection{march 2007} + +A modification has been done to the virtual library. The name of the cells have been changed in order to be synchronised with the sxlib cells.\\ +\indent Two utilizations can be done with the cells of the virtual library : wether direct instanciation of 1 bit cells, wether use of a generator (same model name with the first letter uppered) in order to have several bits cells. + + \subsection{mai 2006} + +First of all, the modifications made to stratus make all files created for version 2.0 deprecated, and unusable with this version 3.0.\\ +\indent All following releases will be improvements, and not major changements.\\ + +\begin{itemize} + \item The main modification is the new funtion \verb-Generate- : this function is used to generate generators before their instanciation.\\ + \item One other modification is the type of arguments of function \verb-Place- : it no longer takes x and y coordinates but a \verb-XY- object (which is a point (x, y) ).\\ + \item Some improvements are also added for layout : the creation of segments, contacts, and references. +\end{itemize} diff --git a/stratus1/doc/stratus/man_pads.tex b/stratus1/doc/stratus/man_pads.tex new file mode 100644 index 00000000..b4f8f5d3 --- /dev/null +++ b/stratus1/doc/stratus/man_pads.tex @@ -0,0 +1,56 @@ +\subsubsection{Name} + +PadNorth, PadSouth, PadEast, PasWest -- Placement of pads at the periphery of the cell + +\subsubsection{Synopsys} + +\begin{verbatim} +PadNorth ( args ) +\end{verbatim} + +\subsubsection{Description} + +These functions place the pads given as arguments at the given side of the cell (PadNorth : up north, PadSouth : down south ...). +Pads are placed from bottom to top for PadNorth and PadSouth and from left to right for PadWest and PasEast. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-args- : List of pads to be placed +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PadSouth ( self.p_cin, self.p_np, self.p_ng, self.p_vssick0 + , self.p_vddeck0, self.p_vsseck1, self.p_vddeck1, self.p_cout + , self.p_y[0], self.p_y[1], self.p_y[2] + ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PadNorth : not enough space for all pads.-\\The abutment box is not big enough in order to place all the pads. Maybe one could put pads on other faces of the cell. + \item \verb-[Stratus ERROR] PadNorth : one instance doesn't exist.-\\One of the pads given as arguments does not exist + \item \verb-[Stratus ERROR] PadNorth : one argument is not an instance.-\\One of the pads is not one of the pads of the cell. + \item \verb-[Stratus ERROR] PadNorth : the instance ins is already placed.-\\One is trying to place a pad twice. + \item \verb-[Stratus ERROR] PadNorth : pad ins must be closer to the center.-\\The pad name ins must be put closer to the center in order to route the cell +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place.tex b/stratus1/doc/stratus/man_place.tex new file mode 100644 index 00000000..27c4cfa7 --- /dev/null +++ b/stratus1/doc/stratus/man_place.tex @@ -0,0 +1,64 @@ +\subsubsection{Name} + +Place -- Places an instance + +\subsubsection{Synopsys} + +\begin{verbatim} +Place ( ins, sym, point ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist-, in order to use the \verb-Place- function. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-point- : coordinates of the lower left corner of the abutment box of the instance in the current figure. +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst, NOSYM, XY ( 0, 0 ) ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] Place : wrong argument for placement type.-\\The symetry given as argument is not correct. + \item \verb-[Stratus ERROR] Place : wrong argument for placement,-\\\verb- the coordinates must be put in a XY object.-\\The coordinates are not descrobed the bood way. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_bottom.tex b/stratus1/doc/stratus/man_place_bottom.tex new file mode 100644 index 00000000..8d767d3c --- /dev/null +++ b/stratus1/doc/stratus/man_place_bottom.tex @@ -0,0 +1,68 @@ +\subsubsection{Name} + +PlaceBottom -- Places an instance below the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceBottom ( ins, sym, offsetX, offsetY ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The top left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offsetX- (optionnal) : An offset is put horizontally. The value given as argument must be a multiple of PITCH + \item \verb-offsetY- (optionnal) : An offset is put vertically. The value given as argument must be a multiple of SLICE +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceBottom ( myInst2, SYM_Y ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceBottom : no previous instance.-\\One can use \verb-PlaceBottom- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceBottom : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_centric.tex b/stratus1/doc/stratus/man_place_centric.tex new file mode 100644 index 00000000..86bc02ea --- /dev/null +++ b/stratus1/doc/stratus/man_place_centric.tex @@ -0,0 +1,50 @@ +\subsubsection{Name} + +PlaceCentric -- Placement of an instance in the middle of an abutment box + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceCentric ( ins ) +\end{verbatim} + +\subsubsection{Description} + +This function places an instance in the middle of and abutment box.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use this function. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%PlaceCentric ( core ) +%\end{verbatim} +% +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlaceCentric: the instance does not exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] PlaceCentric :-\\\verb-the instance's size is greater than this model.-\\The instance must fit in the abutment box. The abutment box may not be big enough. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_contact.tex b/stratus1/doc/stratus/man_place_contact.tex new file mode 100644 index 00000000..155f1864 --- /dev/null +++ b/stratus1/doc/stratus/man_place_contact.tex @@ -0,0 +1,56 @@ +\subsubsection{Name} + +PlaceContact -- Places a contact + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceContact ( net, layer, point, width, height ) +\end{verbatim} + +\subsubsection{Description} + +Placement of a contact.\\ +\indent The contact is located at the coodinates of \verb-point-, on the layer \verb-layer- and has a size of 1 per 1. It belongs to the net \verb-net-.\\ +\indent Note that the segment must be horizontal or vertival. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : Net which the contact belongs to + \item \verb-layer- : Layer of the segment.\\The \verb-layer- argument is a string wich can take different values, thanks to the technology (file described in HUR\_TECHNO\_NAME) + \begin{itemize} + \item NWELL, PWELL, ptie, ntie, pdif, ndif, ntrans, ptrans, poly, ALU1, ALU2, ALU3, ALU4, ALU5, ALU6, VIA1, VIA2, VIA3, VIA4, VIA5, TEXT, UNDEF, SPL1, TALU1, TALU2, TALU3, TALU4, TALU5, TALU6, POLY, NTIE, PTIE, NDIF, PDIF, PTRANS, NTRANS, CALU1, CALU2, CALU3, CALU4, CALU5, CALU6, CONT\_POLY, CONT\_DIF\_N, CONT\_DIF\_P, CONT\_BODY\_N, CONT\_BODY\_P, via12, via23, via34, via45, via56, via24, via25, via26, via35, via36, via46, CONT\_TURN1, CONT\_TURN2, CONT\_TURN3, CONT\_TURN4, CONT\_TURN5, CONT\_TURN6 + \end{itemize} + \item \verb-point- : Coodinates of the contact + \item \verb-width- : Width of the contact + \item \verb-height- : Height of the contact +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PlaceContact ( myNet, "ALU2", XY (10, 0), 2, 2 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlaceContact : Argument layer must be a string.- + \item \verb-[Stratus ERROR] PlaceContact : Wrong argument,-\\\verb-the coordinates of the contact must be put in a XY object.- +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceSegment}}{}{PlaceSegment}{secsegment} +\hyperref[ref]{\emph{PlacePin}}{}{PlacePin}{secpin} +\hyperref[ref]{\emph{PlaceRef}}{}{PlaceRef}{secref} +\hyperref[ref]{\emph{GetRefXY}}{}{GetRefXY}{secgetref} +\hyperref[ref]{\emph{CopyUpSegment}}{}{CopyUpSegment}{seccopy} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_glu.tex b/stratus1/doc/stratus/man_place_glu.tex new file mode 100644 index 00000000..d4c3cfbd --- /dev/null +++ b/stratus1/doc/stratus/man_place_glu.tex @@ -0,0 +1,42 @@ +\subsubsection{Name} + +PlaceGlue -- Automatic placement of non placed instances + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceGlue ( cell ) +\end{verbatim} + +\subsubsection{Description} + +This function places, thanks to the automatic placer Mistral of Coriolis, all the non placed instances of the cell. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-cell- : the cell which the fonction is applied to +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%PlaceGlue ( core ) +%\end{verbatim} +% + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_left.tex b/stratus1/doc/stratus/man_place_left.tex new file mode 100644 index 00000000..0bef031b --- /dev/null +++ b/stratus1/doc/stratus/man_place_left.tex @@ -0,0 +1,68 @@ +\subsubsection{Name} + +PlaceLeft -- Places an instance at the left of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceLeft ( ins, sym, offsetX, offsetY ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom right corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offsetX- (optionnal) : An offset is put horizontally. The value given as argument must be a multiple of PITCH + \item \verb-offsetY- (optionnal) : An offset is put vertically. The value given as argument must be a multiple of SLICE +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceLeft ( myInst2, NOSYM ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceLeft : no previous instance.-\\One can use \verb-PlaceLeft- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceLeft : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_pin.tex b/stratus1/doc/stratus/man_place_pin.tex new file mode 100644 index 00000000..9455055a --- /dev/null +++ b/stratus1/doc/stratus/man_place_pin.tex @@ -0,0 +1,60 @@ +\subsubsection{Name} + +PlacePin -- Places a pin + +\subsubsection{Synopsys} + +\begin{verbatim} +PlacePin ( net, layer, direction, point, width, height ) +\end{verbatim} + +\subsubsection{Description} + +Placement of a pin.\\ +\indent The pin is located at the coodinates of \verb-point-, on the layer \verb-layer-, has a a direction of \verb-direction- and size of 1 per 1. It belongs to the net \verb-net-. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : Net which the pin belongs to + \item \verb-layer- : Layer of the segment.\\The \verb-layer- argument is a string wich can take different values, thanks to the technology (file described in HUR\_TECHNO\_NAME) + \begin{itemize} + \item NWELL, PWELL, ptie, ntie, pdif, ndif, ntrans, ptrans, poly, ALU1, ALU2, ALU3, ALU4, ALU5, ALU6, VIA1, VIA2, VIA3, VIA4, VIA5, TEXT, UNDEF, SPL1, TALU1, TALU2, TALU3, TALU4, TALU5, TALU6, POLY, NTIE, PTIE, NDIF, PDIF, PTRANS, NTRANS, CALU1, CALU2, CALU3, CALU4, CALU5, CALU6, CONT\_POLY, CONT\_DIF\_N, CONT\_DIF\_P, CONT\_BODY\_N, CONT\_BODY\_P, via12, via23, via34, via45, via56, via24, via25, via26, via35, via36, via46, CONT\_TURN1, CONT\_TURN2, CONT\_TURN3, CONT\_TURN4, CONT\_TURN5, CONT\_TURN6 + \end{itemize} + \item \verb-direction- : Direction of the pin + \begin{itemize} + \item UNDEFINED, NORTH, SOUTH, EAST, WEST + \end{itemize} + \item \verb-point- : Coodinates of the pin + \item \verb-width- : Width of the pin + \item \verb-height- : Height of the pin +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PlacePin ( myNet, "ALU2", NORTH, XY (10, 0), 2, 2 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlacePin : Argument layer must be a string.- + \item \verb-[Stratus ERROR] PlacePin : Illegal pin access direction.-\\\verb-The values are : UNDEFINED, NORTH, SOUTH, EAST, WEST.- + \item \verb-[Stratus ERROR] PlacePin : Wrong argument,-\\\verb-the coordinates of the pin must be put in a XY object.- +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceSegment}}{}{PlaceSegment}{secsegment} +\hyperref[ref]{\emph{PlaceContact}}{}{PlaceContact}{seccontact} +\hyperref[ref]{\emph{PlaceRef}}{}{PlaceRef}{secref} +\hyperref[ref]{\emph{GetRefXY}}{}{GetRefXY}{secgetref} +\hyperref[ref]{\emph{CopyUpSegment}}{}{CopyUpSegment}{seccopy} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_ref.tex b/stratus1/doc/stratus/man_place_ref.tex new file mode 100644 index 00000000..bb842d88 --- /dev/null +++ b/stratus1/doc/stratus/man_place_ref.tex @@ -0,0 +1,49 @@ +\subsubsection{Name} + +PlaceRef -- Places a reference + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceRef ( point, name ) +\end{verbatim} + +\subsubsection{Description} + +Placement of a reference.\\ +\indent The reference is located at the coordinates of \verb-point-, with name \verb-name-. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-point- : Coodinates of the reference + \item \verb-name- : Name of the reference +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PlaceRef ( XY (10, 0), "myref" ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlaceRef : Wrong argument,-\\\verb-the coordinates of the reference must be put in a XY object.- + \item \verb-[Stratus ERROR] PlaceRef : Argument layer must be a string.- +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceSegment}}{}{PlaceSegment}{secsegment} +\hyperref[ref]{\emph{PlaceContact}}{}{PlaceContact}{seccontact} +\hyperref[ref]{\emph{PlacePin}}{}{PlacePin}{secpin} +\hyperref[ref]{\emph{GetRefXY}}{}{GetRefXY}{secgetref} +\hyperref[ref]{\emph{CopyUpSegment}}{}{CopyUpSegment}{seccopy} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_right.tex b/stratus1/doc/stratus/man_place_right.tex new file mode 100644 index 00000000..24b31b7c --- /dev/null +++ b/stratus1/doc/stratus/man_place_right.tex @@ -0,0 +1,68 @@ +\subsubsection{Name} + +PlaceRight -- Places an instance at the right of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceRight ( ins, sym, offsetX, offsetY ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the bottom right corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offsetX- (optionnal) : An offset is put horizontally. The value given as argument must be a multiple of PITCH + \item \verb-offsetY- (optionnal) : An offset is put vertically. The value given as argument must be a multiple of SLICE +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceRight ( myInst2, NOSYM ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceRight : no previous instance.-\\One can use \verb-PlaceRight- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceRight : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_segment.tex b/stratus1/doc/stratus/man_place_segment.tex new file mode 100644 index 00000000..b697d3c1 --- /dev/null +++ b/stratus1/doc/stratus/man_place_segment.tex @@ -0,0 +1,55 @@ +\subsubsection{Name} + +PlaceSegment -- Places a segment + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceSegment ( net, layer, point1, point2, width ) +\end{verbatim} + +\subsubsection{Description} + +Placement of a segment.\\ +\indent The segment is created between \verb-point1- and \verb-point2- on the layer \verb-layer- and with width \verb-width-. It belongs to the net \verb-net-.\\ +\indent Note that the segment must be horizontal or vertival. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : Net which the segment belongs to + \item \verb-layer- : Layer of the segment.\\The \verb-layer- argument is a string wich can take different values, thanks to the technology (file described in HUR\_TECHNO\_NAME) + \begin{itemize} + \item NWELL, PWELL, ptie, ntie, pdif, ndif, ntrans, ptrans, poly, ALU1, ALU2, ALU3, ALU4, ALU5, ALU6, VIA1, VIA2, VIA3, VIA4, VIA5, TEXT, UNDEF, SPL1, TALU1, TALU2, TALU3, TALU4, TALU5, TALU6, POLY, NTIE, PTIE, NDIF, PDIF, PTRANS, NTRANS, CALU1, CALU2, CALU3, CALU4, CALU5, CALU6, CONT\_POLY, CONT\_DIF\_N, CONT\_DIF\_P, CONT\_BODY\_N, CONT\_BODY\_P, via12, via23, via34, via45, via56, via24, via25, via26, via35, via36, via46, CONT\_TURN1, CONT\_TURN2, CONT\_TURN3, CONT\_TURN4, CONT\_TURN5, CONT\_TURN6 + \end{itemize} + \item \verb-point1-, \verb-point2- : The segment is created between those two points +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PlaceSegment ( myNet, "ALU3", XY (10, 0), XY (10, 100), 2 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PlaceSegment : Argument layer must be a string.- + \item \verb-[Stratus ERROR] PlaceSegment : Wrong argument,-\\\verb-the coordinates of the segment must be put in XY objects.- + \item \verb-[Stratus ERROR] PlaceSegment : Segments are vertical or horizontal.-\\The two references given as argument do not describe a vertical or horizontal segment. Wether coordinate x or y of the references must be identical. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceContact}}{}{PlaceContact}{seccontact} +\hyperref[ref]{\emph{PlacePin}}{}{PlacePin}{secpin} +\hyperref[ref]{\emph{PlaceRef}}{}{PlaceRef}{secref} +\hyperref[ref]{\emph{GetRefXY}}{}{GetRefXY}{secgetref} +\hyperref[ref]]{\emph{CopyUpSegment}}{}{CopyUpSegment}{seccopy} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_place_top.tex b/stratus1/doc/stratus/man_place_top.tex new file mode 100644 index 00000000..95d83ccc --- /dev/null +++ b/stratus1/doc/stratus/man_place_top.tex @@ -0,0 +1,68 @@ +\subsubsection{Name} + +PlaceTop -- Places an instance at the top of the "reference instance" + +\subsubsection{Synopsys} + +\begin{verbatim} +PlaceTop ( ins, sym, offsetX, offsetY ) +\end{verbatim} + +\subsubsection{Description} + +Placement of an instance.\\ +\indent The instance has to be instantiated in the method \verb-Netlist- in order to use the \verb-PlaceTop- function.\\ + +\indent The bottom left corner of the abutment box of the instance is placed, after beeing symetrized and/or rotated, toward the top left corner of the abutment box of the "reference instance". The newly placed instance becomes the "reference instance". + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : Instance to place. + \item \verb-sym- : Geometrical operation to be performed on the instance before beeing placed.\\The \verb-sym- argument can take eight legal values : + \begin{itemize} + \item \verb-NOSYM- : no geometrical operation is performed + \item \verb-SYM_Y- : Y becomes -Y, that means toward X axe symetry + \item \verb-SYM_X- : X becomes -X, that means toward Y axe symetry + \item \verb-SYMXY- : X becomes -X, Y becomes -Y + \item \verb-ROT_P- : a positive 90 degrees rotation takes place + \item \verb-ROT_M- : a negative 90 degrees rotation takes place + \item \verb-SY_RP- : Y becomes -Y, and then a positive 90 degrees rotation takes place + \item \verb-SY_RM- : Y becomes -Y, and then a negative 90 degrees rotation takes place + \end{itemize} + \item \verb-offsetX- (optionnal) : An offset is put horizontally. The value given as argument must be a multiple of PITCH + \item \verb-offsetY- (optionnal) : An offset is put vertically. The value given as argument must be a multiple of SLICE +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceTop ( myInst2, SYM_Y ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Placement : the instance doesn't exist.-\\The instance must be instanciated in order to be placed. + \item \verb-[Stratus ERROR] Placement : the first argument is not an instance.- + \item \verb-[Stratus ERROR] Placement : the instance is already placed.-\\One can not place an instance twice + \item \verb-[Stratus ERROR] PlaceTop : no previous instance.-\\One can use \verb-PlaceTop- only if a reference instance exist. Use a \verb-Place- call before. + \item \verb-[Stratus ERROR] PlaceTop : wrong argument for placement type.-\\The symetry given as argument is not correct. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_power_ring.tex b/stratus1/doc/stratus/man_power_ring.tex new file mode 100644 index 00000000..bea4384d --- /dev/null +++ b/stratus1/doc/stratus/man_power_ring.tex @@ -0,0 +1,49 @@ +\subsubsection{Name} + +PowerRing -- Placement of power rings. + +\subsubsection{Synopsys} + +\begin{verbatim} +PowerRing ( nb ) +\end{verbatim} + +\subsubsection{Description} + +This function places power rings around the core and around the plots. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-nb- : Number of pair of rings vdd/vss +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +PowerRing ( 3 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] PowerRing : Pads in the north haven't been placed.-\\The pads of the 4 sides of the chip must be placed before calling function PowerRing. + \item \verb-[Stratus ERROR] PowerRing : too many rings, not enough space.-\\Wether The argument of PowerRing is to big, or the abutment box of the chip is to small. There's no space to put the rings. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{RouteCk}}{}{RouteCk}{secrouteck} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_reg.tex b/stratus1/doc/stratus/man_reg.tex new file mode 100644 index 00000000..4e43faba --- /dev/null +++ b/stratus1/doc/stratus/man_reg.tex @@ -0,0 +1,55 @@ +\subsubsection{Name} + +Reg -- Easy way to instantiate a register + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCk.Reg ( netIn ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the clock of the register. The net given as parameter is the input net. The method returns a net : the output net.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetReg- method. + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = SignalIn ( "a", 4 ) + self.S = SignalOut ( "s", 4 ) + + self.Ck = CkIn ( "ck" ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S <= self.Ck.Reg ( self.A ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Reg : The input net does not have a positive arity.-\\The input net must have a positive arity. + \item \verb-[Stratus ERROR] Reg : The clock does not have a positive arity.-\\The clock must have a positive arity. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_resize_ab.tex b/stratus1/doc/stratus/man_resize_ab.tex new file mode 100644 index 00000000..8eb71021 --- /dev/null +++ b/stratus1/doc/stratus/man_resize_ab.tex @@ -0,0 +1,59 @@ +\subsubsection{Name} + +ResizeAb -- Modifies the abutment box of the current cell + +\subsubsection{Synopsys} + +\begin{verbatim} +ResizeAb ( dx1, dy1, dx2, dy2 ) +\end{verbatim} + +\subsubsection{Description} + +This function modifies the abutment box of the current cell.\\ +\indent The coordinates of the abutment box are the coordinates of the envelop of the abutment boxes of each instance plus the delta values given as argument.\\ + +\indent Note that one can not call this function in order to create the abutment box. This fonction only modifies the already created abutment box. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-(dx1, dy1)- : Values to be substracted to the lower left corner of the previous abutment box. + \item \verb-(dx2, dy2)- : Values to be added to the upper right corner of the previous abutment box. +\end{itemize} + +\indent The Values are used as follow : +\begin{figure}[h!] +\centering +\includegraphics[width=.3\textwidth]{./images/resizeAb.png} +\end{figure} + +\subsubsection{Example} + +\begin{verbatim} +% Expansion of the abutment box at the top and the bottom +ResizeAb ( 0, 100, 0, 100 ) +\end{verbatim} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb- [Stratus ERROR] ResizeAb :-\\\verb-Coordinates of an abutment Box in y must be multiple of the slice.-\\\verb-Coordinates of an abutment Box in x must be multiple of the pitch.-\\One has called ResizeAb with non authorized values + \item \verb- [Stratus ERROR] ResizeAb :-\\\verb-one of the values of dx1 or dx2 (dy1 or dy2) is incompatible with-\\\verb-the size of the abutment box.-\\\verb-Coordinates of an abutment Box in x must be multiple of the pitch.-\\One has called ResizeAb with a value which deteriorates the abtument box +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{SetRefIns}}{}{SetRefIns}{secsetrefins} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_route_ck.tex b/stratus1/doc/stratus/man_route_ck.tex new file mode 100644 index 00000000..cdb4303c --- /dev/null +++ b/stratus1/doc/stratus/man_route_ck.tex @@ -0,0 +1,49 @@ +\subsubsection{Name} + +RouteCk -- Routing of signal Ck to standard cells + +\subsubsection{Synopsys} + +\begin{verbatim} +RouteCk ( net ) +\end{verbatim} + +\subsubsection{Description} + +This function routes signal Ck to standard cells. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-net- : the net which the fonction is applied to +\end{itemize} + +%\subsubsection{Example} +% +%\begin{verbatim} +%netCk = SignalIn ( "ck", 1 ) +%RouteCk ( netCk ) +%\end{verbatim} +% +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] RouteCk : Pads in the north haven't been placed-\\The pads must be placed before calling RoutageCk. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{PlaceCentric}}{}{PlaceCentric}{seccentric} +\hyperref[ref]{\emph{PlaceGlu}}{}{PlaceGlu}{secglu} +\hyperref[ref]{\emph{FillCell}}{}{FillCell}{secfillcell} +\hyperref[ref]{\emph{Pads}}{}{Pads}{secpads} +\hyperref[ref]{\emph{Alimentation rails}}{}{Alimentation rails}{secrails} +\hyperref[ref]{\emph{Alimentation connectors}}{}{Alimentation connectors}{secconnectors} +\hyperref[ref]{\emph{PowerRing}}{}{PowerRing}{secpowerring} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_set_ref_ins.tex b/stratus1/doc/stratus/man_set_ref_ins.tex new file mode 100644 index 00000000..17eda9a9 --- /dev/null +++ b/stratus1/doc/stratus/man_set_ref_ins.tex @@ -0,0 +1,57 @@ +\subsubsection{Name} + +SetRefIns -- Defines the new "reference instance" for placement + +\subsubsection{Synopsys} + +\begin{verbatim} +SetRefIns ( ins ) +\end{verbatim} + +\subsubsection{Description} + +This function defines the new "reference instance", used as starting point in the relative placement functions.\\ +\indent It's regarding the abutmentbox of the instance \verb-ins- that the next instance is going to be placed, if using the appropriate functions.\\ + +\indent Note that the more recently placed instance becomes automaticaly the "reference instance", if SetRefIns isn't called. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-ins- : defines the new "reference instance" +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +Place ( myInst1, NOSYM, 0, 0 ) +PlaceRight ( myInst2, NOSYM ) + +SetRefIns ( myInst1 ) +PlaceTop ( myInst3, SYM_Y ) +\end{verbatim} + +\indent \verb-myInst3- is on top of \verb-myInst1- instead of \verb-myInst2-. + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] SetRefIns : the instance doesn't exist.-\\If the instance has not been instanciated, it is impossible do to any placement from it. + \item \verb-[Stratus ERROR] SetRefIns : the instance ...is not placed.-\\If the instance has not been placed, it is impossible do to any placement from it. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Place}}{}{Place}{secplace} +\hyperref[ref]{\emph{PlaceTop}}{}{PlaceTop}{sectop} +\hyperref[ref]{\emph{PlaceBottom}}{}{PlaceBottom}{secbottom} +\hyperref[ref]{\emph{PlaceRight}}{}{PlaceRight}{secright} +\hyperref[ref]{\emph{PlaceLeft}}{}{PlaceLeft}{secleft} +\hyperref[ref]{\emph{DefAb}}{}{DefAb}{secdefab} +\hyperref[ref]{\emph{ResizeAb}}{}{ResizeAb}{secresizeab} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_shift.tex b/stratus1/doc/stratus/man_shift.tex new file mode 100644 index 00000000..1da6b7d4 --- /dev/null +++ b/stratus1/doc/stratus/man_shift.tex @@ -0,0 +1,86 @@ +\subsubsection{Name} + +Shift -- Easy way to instantiate a shifter + +\subsubsection{Synopsys} + +\begin{verbatim} +netOut <= netCmd.Shift ( netIn, direction, type ) +\end{verbatim} + +\subsubsection{Description} + +This method is a method of net. The net which this method is applied to is the command of the shifter, it's the one which defines the number of bits to shift. The net given as parameter is the input net. The other arguments set the different patameters. The method returns a net : the output net.\\ +\indent Note that it is possible to change the generator instanciated with the \verb-SetShift- method. + +\subsubsection{Parameters} + +\begin{itemize} + \item \verb-netIn- : the net which is going to be shifted + \item \verb-direction- : this string represents the direction of the shift : + \begin{itemize} + \item "left" + \item "right" + \end{itemize} + \item \verb-type- : this string represents the type of the shift : + \begin{itemize} + \item "logical" : only "zeros" are put in the net + \item "arith" : meaningful for "right" shift, the values put in the nets are an extension of the MSB + \item "circular" : the values put in the nets are the ones which have just been taken off + \end{itemize} +\end{itemize} + +\subsubsection{Example} + +\begin{verbatim} +class essai ( Model ) : + + def Interface ( self ) : + self.A = SignalIn ( "a", 4 ) + + self.Cmd = SignalIn ( "cmd", 2 ) + + self.S1 = SignalOut ( "s1", 4 ) + self.S2 = SignalOut ( "s2", 4 ) + self.S3 = SignalOut ( "s3", 4 ) + + self.Vdd = VddIn ( "vdd" ) + self.Vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + self.S1 <= self.Cmd.Shift ( self.A, "right", "logical" ) + self.S2 <= self.Cmd.Shift ( self.A, "right", "arith" ) + + self.S3 <= self.Cmd.Shift ( self.A, "left", "circular" ) +\end{verbatim} +\indent If the value of "a" is "0b1001" and the value of "cmd" is "0b10", we will have : +\begin{itemize} + \item "s1" : "0b0010" + \item "s2" : "0b1110" + \item "s3" : "0b0110" +\end{itemize} + +\subsubsection{Errors} + +Some errors may occur : +\begin{itemize} + \item \verb-[Stratus ERROR] Shift :-\\\verb-The input net does not have a positive arity.-\\The net which is going to be shifted must have a positive arity. + \item \verb-[Stratus ERROR] Shift :-\\\verb-The direction parameter must be "left" or "right".-\\The "direction" argument is not correct. + \item \verb-[Stratus ERROR] Shift :-\\\verb-The type parameter must be "logical" or "arith" or "circular".-\\The "type" argument is not correct. +\end{itemize} + +\begin{htmlonly} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Instanciation of a multiplexor}}{}{Multiplexor}{secmux} +\hyperref[ref]{\emph{Instanciation of a register}}{}{Reg}{secreg} +\hyperref[ref]{\emph{Instanciation of constants}}{}{Constant}{secconstant} +\hyperref[ref]{\emph{Boolean operations}}{}{Boolean}{secbool} +\hyperref[ref]{\emph{Arithmetical operations}}{}{Arithmetic}{secarithmetic} +\hyperref[ref]{\emph{Comparison operations}}{}{Comparison}{seccomp} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/man_stratus.tex b/stratus1/doc/stratus/man_stratus.tex new file mode 100644 index 00000000..0209920f --- /dev/null +++ b/stratus1/doc/stratus/man_stratus.tex @@ -0,0 +1,127 @@ +\subsubsection{Name} + +Stratus -- Procedural design language based upon \emph{Python} + +\subsubsection{Description} + +\emph{Stratus} is a set of \emph{Python} methods/functions dedicated to procedural generation purposes. From a user point of view, \emph{Stratus} is a circuit's description language that allows \emph{Python} programming flow control, variable use, and specialized functions in order to handle vlsi objects.\\ + +\indent Based upon the \emph{Hurricane} data structures, the \emph{Stratus} language gives the user the ability to describe netlist and layout views. + +\subsubsection{Creation of a cell} + +A cell is a hierachical structural description of a circuit in terms of ports (I/Os), signals (nets) and instances.\\ + +\indent The creation of a cell is done by creating a new class, derivating for class \verb-Model-, with different methods : + +\begin{itemize} +\item Method \verb-Interface- : Description of the external ports of the cell : + \begin{itemize} + \item SignalIn, SignalOut, ... + \end{itemize} +\item Method \verb-Netlist- : Description of the netlist of the cell : + \begin{itemize} + \item Inst, Signal + \end{itemize} +\item Method \verb-Layout- : Description of the layout of the cell : + \begin{itemize} + \item Place, PlaceTop, PlaceBottom, PlaceRight, PlaceLeft ... + \end{itemize} +\end{itemize} + +\indent Two methods are provided : +\begin{itemize} + \item Method \verb-View- : Opens/Refreshes the editor in order to see the created layout + \item Method \verb-Save- : Saves the created cell + \begin{itemize} + \item no argument : creation of a netlist file (format file thanks to CRL\_OUT\_LO) + \item PHYSICAL : creation of a netlist file AND a layout file (format files thanks to CRL\_OUT\_LO and CRL\_OUT\_PH) + \item STRATUS : creation of a python/stratus file + \begin{itemize} + \item FileName : optionnal argument when using Save(STRATUS) in order to choose the name of the file to be generated + \item Be careful : if one wants to create a stratus file AND a netlist, always use Save(STRATUS) before Save() ! + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Syntax} + +A \emph{Stratus} file must have a .py extension and must begin as follow : +\begin{verbatim} +#!/usr/bin/env python + +from stratus import * +\end{verbatim} + +\indent The creation of a class is done as follow : +\begin{verbatim} +class myClass ( Model ) : + ... + +exemple = myClass ( name, param ) +\end{verbatim} + +\indent In order to execute a \emph{Stratus} file (named \verb-file- for example), one has two choices : +\begin{verbatim} +python file.py +\end{verbatim} +\indent Or : +\begin{verbatim} +chmod u+x file.py +./file.py +\end{verbatim} + +\indent The names used in \emph{Stratus}, as arguments to \emph{Stratus} functions, should be alphanumerical, including the underscore. The arguments of \emph{Stratus} are case sensitive, so \textsc{VDD} is not equivalent to \textsc{vdd}.\\ + +\indent Vectorized connectors or signal can be used using the \textsc{[n:m]} construct.\\ + +\subsubsection{Syntax highlighting} + +When using vi, it's possible to have the right syntax highlighting when using vi : + +\begin{itemize} + \item Commands to do when you want to change once the coloration of your file : +\end{itemize} +\begin{small} +\begin{verbatim} +:syntax off +:source /asim/coriolis/share/etc/stratus.vim +\end{verbatim} +\end{small} +\begin{itemize} + \item Modification of your .vimrc in order to have the syntax highlighting each time you open a file : +\end{itemize} +\begin{small} +\begin{verbatim} +syntax off +autocmd BufRead,BufNewfile *.py so /asim/coriolis/share/etc/stratus.vim +syntax on +\end{verbatim} +\end{small} + +\subsubsection{Environment variables} + +\begin{itemize} + \item CRL\_IN\_LO, default value : \verb-def- + \item CRL\_OUT\_LO, default value : \verb-def- + \item CRL\_IN\_PH, default value : \verb-def- + \item CRL\_OUT\_PH, default value : \verb-def- + \item CRL\_CATA\_LIB, default value : \verb-.- + \item CRL\_CATAL\_NAME, default value : \verb-CATAL- +\end{itemize} + +\begin{htmlonly} + +\subsubsection{Example} + +You can see a concrete example at : \hyperref[ref]{\emph{Example}}{}{Example}{secexample} + +\subsubsection{See Also} + +\hyperref[ref]{\emph{Netlist}}{}{Netlist}{secnetlist} +\hyperref[ref]{\emph{Layout}}{}{Layout}{seclayout} +\hyperref[ref]{\emph{Place and Route}}{}{Place and Route}{secroute} +\hyperref[ref]{\emph{Virtual libraty}}{}{Virtual library}{seclibrary} +\hyperref[ref]{\emph{Instanciation facilities}}{}{Instanciation facilities}{secfacilities} + +\end{htmlonly} diff --git a/stratus1/doc/stratus/see_also.tex b/stratus1/doc/stratus/see_also.tex new file mode 100644 index 00000000..32299cf7 --- /dev/null +++ b/stratus1/doc/stratus/see_also.tex @@ -0,0 +1,3 @@ +\subsubsection{See Also} + +\hyperref[ref]{\emph{Introduction}}{}{Introduction}{secintroduction} diff --git a/stratus1/doc/stratus/stratus.tex b/stratus1/doc/stratus/stratus.tex new file mode 100644 index 00000000..44fef7ce --- /dev/null +++ b/stratus1/doc/stratus/stratus.tex @@ -0,0 +1,232 @@ +\documentclass[12pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{palatino} +\usepackage{fancyhdr} +\usepackage{float} +\usepackage{subfigure} +\usepackage{wrapfig} +\usepackage[dvips]{graphics} +\usepackage{graphicx} +\usepackage{epsfig} +\usepackage{multicol} +\usepackage{url} +\usepackage{html} +\usepackage{color} + + \definecolor{violet}{rgb}{0.5,0,0.5} + +\setlength{\topmargin}{0cm} +\setlength{\headheight}{1cm} +\setlength{\textheight}{21cm} +\setlength{\textwidth}{16cm} +\setlength{\oddsidemargin}{0cm} +\setlength{\evensidemargin}{0cm} +\setlength{\columnsep}{0.125in} +\setlength{\columnseprule}{0.5pt} +\setlength{\footskip}{1cm} +\sloppy + +%--------------------------------- page style -------------------------------- +\pagestyle{fancy} +\rhead{} +\lhead{} +\rfoot{\thepage} +\lfoot{} +\cfoot{} +%---------------------------------- document --------------------------------- +\date {} +\title {Stratus User's Manual} +\author {Sophie Belloeil} + +\begin{document} + +\setlength{\footrulewidth}{0.6pt} +\maketitle + +%%\begin{htmlonly} +%% \htmlrule +%% \noindent La version imprimable de ce document est disponible ici~: \\ +%% \begin{center} +%% \hyperref[hyper]{http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf}{}{} +%% {http://asim.lip6.fr/~jpc/M1-C++/TME/6/TME6.pdf} +%% \end{center} +%%\end{htmlonly} + +\tableofchildlinks +\htmlrule + +\section{What's new} +\input{man_new} + +\section{Introduction} +\label{secintroduction} + + \subsection{Stratus} + \label{secstratus} + \input{man_stratus} + \subsection{Example} + \label{secexample} + \input{man_example} + +\section{Description of a netlist} +\label{secnetlist} + + \subsection{Nets} + \label{secnet} + \input{man_net} + \subsection{Instances} + \label{secinst} + \input{man_inst} + \subsection{Generators} + \label{secgen} + \input{man_generate} + +\section{Description of a layout} +\label{seclayout} + + \subsection{Place} + \label{secplace} + \input{man_place} + \subsection{PlaceTop} + \label{sectop} + \input{man_place_top} + \subsection{PlaceBottom} + \label{secbottom} + \input{man_place_bottom} + \subsection{PlaceRight} + \label{secright} + \input{man_place_right} + \subsection{PlaceLeft} + \label{secleft} + \input{man_place_left} + \subsection{SetRefIns} + \label{secsetrefins} + \input{man_set_ref_ins} + \subsection{DefAb} + \label{secdefab} + \input{man_def_ab} + \subsection{ResizeAb} + \label{secresizeab} + \input{man_resize_ab} + +\section{Place and Route} +\label{secroute} + + \subsection{PlaceSegment} + \label{secsegment} + \input{man_place_segment} + \subsection{PlaceContact} + \label{seccontact} + \input{man_place_contact} + \subsection{PlacePin} + \label{secpin} + \input{man_place_pin} + \subsection{PlaceRef} + \label{secref} + \input{man_place_ref} + \subsection{GetRefXY} + \label{secgetref} + \input{man_get_ref} + \subsection{CopyUpSegment} + \label{seccopy} + \input{man_copy_up_segment} + \subsection{PlaceCentric} + \label{seccentric} + \input{man_place_centric} + \subsection{PlaceGlu} + \label{secglu} + \input{man_place_glu} + \subsection{FillCell} + \label{secfillcell} + \input{man_fill_cell} + \subsection{Pads} + \label{secpads} + \input{man_pads} + \subsection{Alimentation rails} + \label{secrails} + \input{man_alim_rail} + \subsection{Alimentation connectors} + \label{secconnectors} + \input{man_alim_connectors} + \subsection{PowerRing} + \label{secpowerring} + \input{man_power_ring} + \subsection{RouteCk} + \label{secrouteck} + \input{man_route_ck} + +\section{Instanciation facilities} +\label{secfacilities} + + \subsection{Buffer} + \label{secbuff} + \input{man_buff} + \subsection{Multiplexor} + \label{secmux} + \input{man_mux} + \subsection{Shifter} + \label{secshift} + \input{man_shift} + \subsection{Register} + \label{secreg} + \input{man_reg} + \subsection{Constants} + \label{secconstant} + \input{man_const} + \subsection{Boolean operations} + \label{secbool} + \input{man_boolean} + \subsection{Arithmetical operations} + \label{secarithmetic} + \input{man_arithmetic} + \subsection{Comparison operations} + \label{seccomp} + \input{man_comp} + +%\section{Developper's manual} +%\label{secdev} +% +% \subsection{Class Model} +% \label{secmodeldev} +% \input{man_model_dev} +% +% \subsection{Nets} +% \label{secnetdev} +% \input{man_net_dev} +% +% \subsection{Instances} +% \label{secinstdev} +% \input{man_inst_dev} + +\section{Virtual library} +\label{seclibrary} +\input{man_library} + +\begin{htmlonly} + +\section{Useful links} + + \subsection{Patterns module} + +You can find the documentation of the patterns module :\\ +\url{file:///asim/coriolis/share/doc/en/html/patterns/index.html} + + \subsection{DPGEN generators} + +You can find the documentation of the DPGEN library at :\\ +\url{file:///asim/coriolis/share/doc/en/html/dpgen/index.html} + + \subsection{Arithmetic package of stratus} + +You can find the documentation of the arithmetic stratus's package at :\\ +\url{file:////users/outil/arith/latest/modules_stratus/arithmetic/doc/arith/index.html} + + \subsection{Arithmetic generators and some stratus packages} + +You can find the documentation of the arithmetic library at :\\ +\url{file:////users/outil/arith/latest/doc/index.html} + +\end{htmlonly} + +\end{document} diff --git a/stratus1/etc/CMakeLists.txt b/stratus1/etc/CMakeLists.txt new file mode 100644 index 00000000..00281917 --- /dev/null +++ b/stratus1/etc/CMakeLists.txt @@ -0,0 +1,3 @@ + + install ( FILES stratus2sxlib.xml DESTINATION ${SYS_CONF_DIR}/coriolis2 ) + install ( FILES stratus.vim DESTINATION ${SYS_CONF_DIR}/coriolis2 ) diff --git a/stratus1/etc/stratus.vim b/stratus1/etc/stratus.vim new file mode 100644 index 00000000..7f9164c4 --- /dev/null +++ b/stratus1/etc/stratus.vim @@ -0,0 +1,174 @@ +" Vim syntax file +" Language: Stratus +" +" There are four options to control Stratus syntax highlighting : +" +" For highlighted numbers : + let s_highlight_numbers = 1 +" +" For highlighted builtin functions : + let s_highlight_builtins = 1 +" +" For highlighted standard exceptions : + let s_highlight_exceptions = 1 +" +" For highlighted stratus : + let s_highlight_stratus = 1 + + +" remove old syntax +syn clear + +syn keyword sStatement break continue del +syn keyword sStatement except exec finally +syn keyword sStatement pass print raise +syn keyword sStatement return try +syn keyword sStatement global assert +syn keyword sStatement lambda +syn keyword sStatement def class nextgroup=sFunction skipwhite +syn match sFunction "[a-zA-Z_][a-zA-Z0-9_]*" contained +syn keyword sRepeat for while +syn keyword sConditional if elif else +syn keyword sOperator and in is not or +syn keyword sPreCondit import from +syn match sComment "#.*$" contains=sTodo +syn keyword sTodo contained TODO FIXME XXX + +" strings +syn region sString matchgroup=Normal start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=sEscape +syn region sString matchgroup=Normal start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=sEscape +syn region sString matchgroup=Normal start=+"""+ end=+"""+ contains=sEscape +syn region sString matchgroup=Normal start=+'''+ end=+'''+ contains=sEscape +syn region sRawString matchgroup=Normal start=+[rR]'+ end=+'+ skip=+\\\\\|\\'+ +syn region sRawString matchgroup=Normal start=+[rR]"+ end=+"+ skip=+\\\\\|\\"+ +syn region sRawString matchgroup=Normal start=+[rR]"""+ end=+"""+ +syn region sRawString matchgroup=Normal start=+[rR]'''+ end=+'''+ +syn match sEscape +\\[abfnrtv'"\\]+ contained +syn match sEscape "\\\o\o\=\o\=" contained +syn match sEscape "\\x\x\+" contained +syn match sEscape "\\$" + +if exists("s_highlight_numbers") + " numbers (including longs and complex) + syn match sNumber "\<0x\x\+[Ll]\=\>" + syn match sNumber "\<\d\+[LljJ]\=\>" + syn match sNumber "\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" + syn match sNumber "\<\d\+\.\([eE][+-]\=\d\+\)\=[jJ]\=\>" + syn match sNumber "\<\d\+\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" +endif + +if exists("s_highlight_builtins") + " builtin functions, not really part of the syntax + syn keyword sBuiltin abs apply callable chr cmp coerce + syn keyword sBuiltin compile complex delattr dir divmod + syn keyword sBuiltin eval execfile filter float getattr + syn keyword sBuiltin globals hasattr hash hex id input + syn keyword sBuiltin int intern isinstance issubclass +" syn keyword sBuiltin len list locals long map max min + syn keyword sBuiltin len list locals long max min + syn keyword sBuiltin oct open ord pow range raw_input + syn keyword sBuiltin reduce reload repr round setattr + syn keyword sBuiltin slice str tuple type vars xrange +endif + +if exists("s_highlight_exceptions") + " builtin exceptions + syn keyword sException None + syn keyword sException ArithmeticError AssertionError + syn keyword sException AttributeError EOFError EnvironmentError + syn keyword sException Exception FloatingPointError IOError + syn keyword sException ImportError IndexError KeyError + syn keyword sException KeyboardInterrupt LookupError + syn keyword sException MemoryError NameError NotImplementedError + syn keyword sException OSError OverflowError RuntimeError + syn keyword sException StandardError SyntaxError SystemError + syn keyword sException SystemExit TypeError ValueError + syn keyword sException ZeroDivisionError +endif + +if exists("s_highlight_stratus") + " builtin exceptions + syn keyword stratusSpecial self + + syn keyword stratusClass Model + syn keyword stratusClass SignalIn SignalOut SignalInOut SignalUnknown TriState CkIn VddIn VssIn Signal + syn keyword stratusClass Inst + syn keyword stratusClass XY + + syn keyword stratusMethod Interface Netlist Layout Vbe Pattern View Save Simul HurricanePlug Quit GetModelName Clean + syn keyword stratusMethod Alias Extend + syn keyword stratusMethod Buffer Mux Shift Reg Eq Ne + syn keyword stratusMethod SetAnd SetOr SetNot SetXor SetNot SetMux SetAdd SetMult SetDiv + syn keyword stratusMethod Delete + + syn keyword stratusMap param map + + syn keyword stratusNumber NOSYM SYM_X SYM_Y SYMXY ROT_P ROT_M SY_RP SY_RM + syn keyword stratusNumber VIEWS LOGICAL PHYSICAL + syn keyword stratusNumber STRATUS + syn keyword stratusNumber UNPLACED PLACED FIXED + syn keyword stratusNumber F_LSB_FIRST F_MSB_FIRST + syn keyword stratusNumber TypePOWER TypeGROUND TypeCLOCK + syn keyword stratusNumber DirectionIN DirectionOUT DirectionINOUT DirectionTRISTATE DirectionUNDEFINED + + syn keyword stratusFunction Generate + syn keyword stratusFunction Place PlaceTop PlaceBottom PlaceRight PlaceLeft SetRefIns DefAb ResizeAb + syn keyword stratusFunction PlaceCentric AlimVerticalRail AlimHorizontalRail AlimConnectors PadNorth PadSouth PadEast PadWest AffichePad SearchVddVss IsConflit PowerRing GetNetInstances RoutageNet RouteCk FillCell PlaceGlue GlobalRoute DetailRoute + syn keyword stratusFunction GetRefXY PlaceRef PlaceContact PlaceSegment PlacePin CopyUpSegment + syn keyword stratusFunction Cat + syn keyword stratusFunction Param + syn keyword stratusFunction One Zero + +endif + + + +" This is fast but code inside triple quoted strings screws it up. It +" is impossible to fix because the only way to know if you are inside a +" triple quoted string is to start from the beginning of the file. If +" you have a fast machine you can try uncommenting the "sync minlines" +" and commenting out the rest. +syn sync match sSync grouphere NONE "):$" +syn sync maxlines=100 +"syn sync minlines=2000 + +if !exists("did_s_syntax_inits") + let did_s_syntax_inits = 1 + " The default methods for highlighting. Can be overridden later + hi link sStatement Statement + hi link sFunction Function + hi link sConditional Conditional + hi link sRepeat Repeat + hi link sString String + hi link sRawString String + hi link sEscape Special + hi link sOperator Operator + hi link sPreCondit PreCondit + hi link sComment Comment + hi link sTodo Todo + + if exists("s_highlight_numbers") + hi link sNumber Number + endif + + if exists("s_highlight_builtins") + hi link sBuiltin Function + endif + + if exists("s_highlight_exceptions") + hi link sException Exception + endif + + if exists("s_highlight_stratus") + hi link stratusSpecial Statement + hi link stratusClass Include + hi link stratusFunction Special + hi link stratusMethod Function + hi link stratusMap Identifier + hi link stratusNumber Number + endif +endif + + +let b:current_syntax = "stratus" + diff --git a/stratus1/etc/stratus2sxlib.xml b/stratus1/etc/stratus2sxlib.xml new file mode 100644 index 00000000..2ee7dd32 --- /dev/null +++ b/stratus1/etc/stratus2sxlib.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stratus1/src/CMakeLists.txt b/stratus1/src/CMakeLists.txt new file mode 100644 index 00000000..d4e973f3 --- /dev/null +++ b/stratus1/src/CMakeLists.txt @@ -0,0 +1,3 @@ + add_subdirectory ( stratus ) + add_subdirectory ( dpgen ) + add_subdirectory ( modules ) diff --git a/stratus1/src/dpgen/CMakeLists.txt b/stratus1/src/dpgen/CMakeLists.txt new file mode 100644 index 00000000..53f37ae8 --- /dev/null +++ b/stratus1/src/dpgen/CMakeLists.txt @@ -0,0 +1,16 @@ + + set ( pysources ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_ADSB2F.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_Nul.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_RAM.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_Regular.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_RF1.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_RF2.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_ROM2.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_ROM4.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_ROM.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_Shifter.py + ${CMAKE_CURRENT_SOURCE_DIR}/dpgen_Shrot.py + ${CMAKE_CURRENT_SOURCE_DIR}/ROM_encours.py + ) + + install ( FILES ${pysources} DESTINATION ${PYTHON_SITE_PACKAGES}/stratus ) diff --git a/stratus1/src/dpgen/ROM_encours.py b/stratus1/src/dpgen/ROM_encours.py new file mode 100644 index 00000000..4085f65f --- /dev/null +++ b/stratus1/src/dpgen/ROM_encours.py @@ -0,0 +1,865 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_ROM.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +# Le nombre de mots peut prendre cinq valeurs : 64, 128, 256, 512, 1024 +# Le nombre de bits est un multiple de 4 et doit etre inferieur ou egal a 64 +# On peut avoir une sortie tri-state en option (pour construire des ROMs +# de capacite superieure a 1024 mots. +# La largeur est egale a ( nmot / 64 * 50) + 150 (+ 20 si option tristate) +# La hauteur est egale a ( nbit + 8) * 50 pour 64 ou 128 mots +# ( nbit + 9) * 50 pour 256, 512 ou 1024 mots +# +# Les valeurs a encoder dans la ROM sont recuperees dans le tableau data[2048] +# qui contient des "mots" de 32 bits : une valeur est stockee dans deux cases +# consecutives de ce tableau, ce qui permet d'avoir des mots de 64 bits. +# Les poids faibles de la valeur i sont a l'adresse data[2*i] +# Les poids forts de la valeur i sont a l'adresse data[2*i+1] +# +# Les lignes de bit horizontales en ALU2 sont hors grilles et pre-routees +# la ROM respecte le gabarit SXLIB pour ce qui concerne les caissons et les +# alimentations en ALU1 sur les faces est et ouest, mais il n'y a pas +# de continuite des alimentations en ALU1 dans la zone data. +# Pour la partie "donnees", on utilise les cellules suivantes : +# - rom_data_invss +# - rom_data_insel +# - rom_data_midvss +# - rom_data_midsel +# - rom_data_outvss +# - rom_data_outsel +# - rom_data_outvss_ts +# - rom_data_outsel_ts +# +# Pour le decodeur, on utilise les cellules suivantes : +# - rom_dec_adbuf +# - rom_dec_nop +# - rom_dec_prech +# - rom_dec_col2 +# - rom_dec_col3 +# - rom_dec_col4 +# - rom_dec_colbuf +# - rom_dec_line01 +# - rom_dec_line23 +# - rom_dec_line45 +# - rom_dec_line67 +# - rom_dec_selmux01 +# - rom_dec_selmux23 +# - rom_dec_selmux45 +# - rom_dec_selmux67 +# - rom_dec_selmux67_128 +# - rom_dec_selmux01_ts +# - rom_dec_selmux23_ts +# - rom_dec_selmux45_ts +# - rom_dec_selmux67_ts +# - rom_dec_selmux67_128_ts + +class dpgen_ROM ( Model ) : + + ## Interface ## + ############### + def Interface ( self, nbit, nword ) : + + if nword == 64 : adrange = 6 + elif nword == 128 : adrange = 7 + elif nword == 256 : adrange = 8 + elif nword == 512 : adrange = 9 + elif nword == 1024 : adrange = 10 + else : + print "Error : DPGEN_ROM" + print "The word number (nword := %d) ", nword, "can only takes values : 64, 128, 256, 512 or 1024.\n" + sys.exit ( 3 ) + + if nbit % 4 != 0 or nbit > 64 or nbit < 4 : + print "Error : DPGEN_ROM\n" + print "The bus width (nbit := %d) ", nbit, "must be multiple of 4 and no larger than 64.\n" + sys.exit ( 3 ) + + ck = LogicIn ( "ck", 1 ) + selrom = LogicIn ( "selrom", 1 ) + + ad = LogicIn ( "ad", adrange ) + data = LogicOut ( "data", nbit ) + + vdd = VddIn ( "vdd" ) + vss = VssIn ( "vss" ) + + + ## Architecture ## + ################## + def architecture ( self, nbit, nword ) : + +# // Acquisition du tableau des valeurs a encoder +# +# /* ICI IL FAUT APPELER LE PARSER DE FICHIER .vbe */ +# /* +# for(i=0 ; i<1024 ; i++) { +# data[2*i] = i; +# data[2*i+1] = 1024 - i; +# } +# */ +# +# dpgen_ROM_code ( LV_name, nbit, nword, 0, 0, data ) # !!! + + for i in range ( nbit ) : + if i % 4 == 0 : + cellin = "rom_data_invss" + cellmid = "rom_data_midvss" + + cellout = "rom_data_outvss" + + elif i % 4 == 1 : + cellin = "rom_data_insel" + cellmid = "rom_data_midsel" + + cellout = "rom_data_outsel" + + elif i % 4 == 2: + cellin = "rom_data_insel" + cellmid = "rom_data_midsel" + + cellout = "rom_data_outsel" + + elif i % 4 == 3 : + cellin = "rom_data_invss" + cellmid = "rom_data_midvss" + + cellout = "rom_data_outvss" + + instanciate ( cellin + , "in%d" % i + , map = { 'prech' : prech + , 'bit0' : bit0[i] + , 'bit1' : bit1[i] + , 'bit2' : bit2[i] + , 'bit3' : bit3[i] + , 'bit4' : bit4[i] + , 'bit5' : bit5[i] + , 'bit6' : bit6[i] + , 'bit7' : bit7[i] + } + ) + + for j in range ( 0, nword, 64 ) : + instanciate ( cellmid + , "bit%d_%d" % ( i, j ) + , map = { 'sela' : line0[j] + , 'selb' : line2[j] + , 'selc' : line4[j] + , 'seld' : line6[j] + , 'bit0' : bit0 [i] + , 'bit1' : bit1 [i] + , 'bit2' : bit2 [i] + , 'bit3' : bit3 [i] + , 'bit4' : bit4 [i] + , 'bit5' : bit5 [i] + , 'bit6' : bit6 [i] + , 'bit7' : bit7 [i] + } + ) + + instanciate ( cellmid + , "bit%d_%d" % ( i, j + 32 ) + , map = { 'sela' : line1[j] + , 'selb' : line3[j] + , 'selc' : line5[j] + , 'seld' : line7[j] + , 'bit0' : bit0 [i] + , 'bit1' : bit1 [i] + , 'bit2' : bit2 [i] + , 'bit3' : bit3 [i] + , 'bit4' : bit4 [i] + , 'bit5' : bit5 [i] + , 'bit6' : bit6 [i] + , 'bit7' : bit7 [i] + } + ) + + instanciate ( cellout + , "out%d" % i + , map = { 'nprech' : nprech + , 'mux0' : mux0 + , 'mux1' : mux1 + , 'mux2' : mux2 + , 'mux3' : mux3 + , 'mux4' : mux4 + , 'mux5' : mux5 + , 'mux6' : mux6 + , 'mux7' : mux7 + , 'bit0' : bit0[i] + , 'bit1' : bit1[i] + , 'bit2' : bit2[i] + , 'bit3' : bit3[i] + , 'bit4' : bit4[i] + , 'bit5' : bit5[i] + , 'bit6' : bit6[i] + , 'bit7' : bit7[i] + , 'q' : data[i] + } + ) + + ## Placement des cellules decodeur ## + + # Lignes 0 et 1 + instanciate ( "rom_dec_prech" + , "prech" + , map = { 'nck' : nck + , 'prech' : prech + , 'nprech' : nprech + } + ) + + for j in range ( 0, nword, 64 ) : + thisMap = { 'nck0' : nck + , 'nck1' : nck + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'line0' : line0[j] + , 'line1' : line1[j] + } + + if nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = vdd + + instanciate ( "rom_dec_line01" + , "and01_%d" % j + , map = thisMap + ) + + instanciate ( "rom_dec_selmux01" + , "selmux01" + , map = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : ck + , 'selrom' : selrom + , 'nck' : nck + , 'mux0' : mux0 + , 'sel0' : sel0 + , 'mux1' : mux1 + , 'sel1' : sel1 + } + ) + + # Lignes 2 et 3 + instanciate ( "rom_dec_adbuf" + , "ad4" + , map = { 'ad' : ad[4] + , 'adx' : a4 + , 'nadx' : na4 + } + ) + + instanciate ( "rom_dec_adbuf" + , "ad5" + , map = { 'ad' : ad[5] + , 'adx' : a5 + , 'nadx' : na5 + } + ) + + for j in range ( 0, nword, 64 ) : + thisMap = { 'nck2' : nck + , 'nck3' : nck + , 'sel2' : sel2 + , 'sel3' : sel3 + , 'line2' : line2[j] + , 'line3' : line3[j] + } + + if nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = vdd + + instanciate ( "rom_dec_line23" + , "and23_%d" % j + , map = thisMap + ) + + LV_name.PLACE_RIGHT ( "rom_dec_selmux23" + , "selmux23" + , map = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : ck + , 'selrom' : selrom + , 'nck' : nck + , 'mux2' : mux2 + , 'sel2' : sel2 + , 'mux3' : mux3 + , 'sel3' : sel3 + } + ) + + # Lignes 4 et 5 + instanciate ( "rom_dec_adbuf" + , "ad2" + , map = { 'ad' : ad[2] + , 'adx' : a2 + , 'nadx' : na2 + } + ) + + nstanciate ( "rom_dec_adbuf" + , "ad3" + , map = { 'ad' : ad[3] + , 'adx' : a3 + , 'nadx' : na3 + } + ) + + for j in range ( 0, nword, 64 ) : + thisMap = { 'nck4' : nck + , 'nck5' : nck + , 'sel4' : sel4 + , 'sel5' : sel5 + , 'line4' : line4[j] + , 'line5' : line5[j] + } + + if nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = vdd + + instanciate ( "rom_dec_line45" + , "and45_%d" % j + , map = thisMap + ) + + instanciate ( "rom_dec_selmux45" + , "selmux45" + , map = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : ck + , 'selrom' : selrom + , 'nck' : nck + , 'mux4' : mux4 + , 'sel5' : sel4 + , 'mux5' : mux5 + , 'sek5' : sel5 + } + ) + + # Lignes 6 et 7 + instanciate ( "rom_dec_adbuf" + , "ad0" + , map = { 'ad' : ad[0] + , 'adx' : a0 + , 'nadx' : na0 + } + ) + + instanciate ( "rom_dec_adbuf" + , "ad1" + , map = { "ad => ad[1]" + , "adx => a1" + , "nadx => na1" + } + ) + + for j in range ( 0, nword, 64 ) : + thisMap = { 'nck6' : nck + , 'nck7' : nck + , 'sel6' : sel6 + , 'sel7' : sel7 + , 'line6' : line6[j] + , 'line7' : line7[j] + } + + if nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = vdd + + instanciate ( "rom_dec_line67" + , "and67_%d" % j + , map = thisMap + ) + + if nword != 128 : # pas de sortie tristate + instanciate ( "rom_dec_selmux67" + , "selmux67" + , map = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : ck + , 'selrom' : selrom + , 'nck' : nck + , 'mux6' : mux6 + , 'sel6' : sel6 + , 'mux7' : mux7 + , 'sel7' : sel7 + } + ) + + else : # pas de sortie tristate - 128 mots + instanciate ( "rom_dec_selmux67_128" + , "selmux67" + , map = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'a6' : ad[6] + , 'selrom' : selrom + , 'a6x' : col_64 + , 'na6x' : col_0 + , 'mux6' : mux6 + , 'sel6' : sel6 + , 'mux7' : mux7 + , 'sel7' : sel7 + } + ) + + # Ligne 9 dans le cas 1024 mots + if nword == 1024 : + instanciate ( "rom_dec_nop" + , "nop" + ) + + for j in range ( 0, nword, 64 ) : + thisMap = { 'q' : col[j] } + + if ( j >> 6 ) % 2 == 0 : thisMap['i0'] = na6x + else : thisMap['i0'] = a6x + + if ( j >> 7 ) % 2 == 0 : thisMap['i1'] = na7x + else : thisMap['i1'] = a7x + + if ( j >> 8 ) % 2 == 0 : thisMap['i2'] = na8x + else : thisMap['i2'] = a8x + + if ( j >> 9 ) % 2 == 0 : thisMap['i3'] = na9x + else : thisMap['i3'] = a9x + + instanciate ( "rom_dec_col4" + , "col_%d" % j + , map = thisMap + ) + + instanciate ( "rom_dec_colbuf" + , "colbuf6" + , map = { " => ad[6]" + , " => a6x" + , " => na6x" + ) + + instanciate ( "rom_dec_colbuf" + , "colbuf7" + , NOSYM + , FIXED + , "a => ad[7]" + , "ax => a7x" + , "nax => na7x" + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf8" + , NOSYM + , FIXED + , "a => ad[8]" + , "ax => a8x" + , "nax => na8x" + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf9" + , NOSYM + , FIXED + , "a => ad[9]" + , "ax => a9x" + , "nax => na9x" + , vdd + , vss + ) + + # Ligne 9 dans le cas 512 mots + if nword == 512 : + LV_name.PLACE ( "rom_dec_nop" + , "nop" + , NOSYM + , 0 + , ( nbit + 8 ) * HCELL + , FIXED + , vdd + , vss + ) + + for j in range ( 0, nword, 64 ) : + if ( j >> 6 ) % 2 == 0 : x6 = "i0 => na6x" + else : x6 = "i0 => a6x" + + if ( j >> 7 ) % 2 == 0 : x7 = "i1 => na7x" + else : x7 = "i1 => a7x" + + if ( j >> 8 ) % 2 == 0 : x8 = "i2 => na8x" + else : x8 = "i2 => a8x" + + LV_name.PLACE_RIGHT ( "rom_dec_col3" + , "col_%d" % j + , NOSYM + , FIXED + , x6 + , x7 + , x8 + , "q => col_%d" % j + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf6" + , NOSYM + , FIXED + , "a => ad[6]" + , "ax => a6x" + , "nax => na6x" + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf7" + , NOSYM + , FIXED + , "a => ad[7]" + , "ax => a7x" + , "nax => na7x" + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf8" + , NOSYM + , FIXED + , "a => ad[8]" + , "ax => a8x" + , "nax => na8x" + , vdd + , vss + ) + + # Ligne 9 dans le cas 256 mots + if nword == 256 : + LV_name.PLACE ( "rom_dec_nop" + , "nop" + , NOSYM + , 0 + , ( nbit + 8 ) * HCELL + , FIXED + , vdd + , vss + ) + + for j in range ( 0, nword, 64 ) : + if ( j >> 6 ) % 2 == 0 : x6 = "i0 => na6x" + else : x6 = "i0 => a6x" + + if ( j >> 7 ) % 2 == 0 : x7 = "i1 => na7x" + else : x7 = "i1 => a7x" + + LV_name.PLACE_RIGHT ( "rom_dec_col2" + , "col_%d" % j + , NOSYM + , FIXED + , x6 + , x7 + , "q => col_%d" % j + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf6" + , NOSYM + , FIXED + , "a => ad[6]" + , "ax => a6x" + , "nax => na6x" + , vdd + , vss + ) + + LV_name.PLACE_RIGHT ( "rom_dec_colbuf" + , "colbuf7" + , NOSYM + , FIXED + , "a => ad[7]" + , "ax => a7x" + , "nax => na7x" + , vdd + , vss + ) + +# ## Routage des rappels d'alimentation et des signaux hors grille ## +# y1 = nbit * HCELL +# +# if nword > 128 : y2 = ( nbit + 9 ) * HCELL +# else : y2 = ( nbit + 8 ) * HCELL +# +# if type == 0 : x2 = ( nword / 64 * 50 ) + 150 +# else : x2 = ( nword / 64 * 50 ) + 170 +# +# # alimentations verticales ALU3 +# LV_name.PHSEG ( CALU3,12, "vdd", 10, 0, 10, y2) +# LV_name.PHSEG ( CALU3, 2, "vss", 20, 0, 20, y2) +# LV_name.PHSEG ( CALU3, 2, "vss", 30, 0, 30, y2) +# +# for j in range ( 0, nword, 64 ) : +# LV_name.PHSEG ( CALU3, 2, "vss", 55 + ( 50 * j / 64 ), 0, 55 + ( 50 * j / 64 ), y2 ) +# LV_name.PHSEG ( CALU3, 2, "vss", 80 + ( 50 * j / 64 ), 0, 80 + ( 50 * j / 64 ), y2 ) +# +# if type == 0 : +# LV_name.PHSEG ( CALU3, 2, "vss", 125 + ( nword / 64 * 50 ), 0, 125 + ( nword / 64 * 50 ), y1 ) +# LV_name.PHSEG ( CALU3, 2, "vdd", 135 + ( nword / 64 * 50 ), 0, 135 + ( nword / 64 * 50 ), y1 ) +# LV_name.PHSEG ( CALU3, 2, "vdd", 145 + ( nword / 64 * 50 ), 0, 145 + ( nword / 64 * 50 ), y1 ) +# +# else : +# LV_name.PHSEG ( CALU3, 2, "vss", 135 + ( nword / 64 * 50 ), 0, 135 + ( nword / 64 * 50 ), y1 ) +# LV_name.PHSEG ( CALU3, 2, "vdd", 145 + ( nword / 64 * 50 ), 0, 145 + ( nword / 64 * 50 ), y1 ) +# LV_name.PHSEG ( CALU3, 2, "vss", 155 + ( nword / 64 * 50 ), 0, 155 + ( nword / 64 * 50 ), y2 ) +# LV_name.PHSEG ( CALU3, 2, "vdd", 165 + ( nword / 64 * 50 ), 0, 165 + ( nword / 64 * 50 ), y2 ) +# +# # alimemtations horizontales ALU2 +# for i in range ( 0, nbit, 4 ) : +# LV_name.PHSEG ( CALU2, 2, "vss", 0, i * HCELL, x2, i * HCELL ) +# +# for l in range ( 0, 8, 2 ) : +# LV_name.PHSEG ( CALU2, 2, "vss", 0, ( nbit + l ) * HCELL, x2, ( nbit + l ) * HCELL ) +# LV_name.PHSEG ( CALU2, 2, "vdd", 0, ( nbit + l + 1 ) * HCELL, x2, ( nbit + l + 1 ) * HCELL ) +# +# LV_name.PHSEG ( CALU2, 2, "vss", 0, ( nbit + 8 ) * HCELL, x2, ( nbit + 8 ) * HCELL ) +# +# if nword > 128 : LV_name.PHSEG ( CALU2, 2, "vdd", 0, ( nbit + 9 ) * HCELL, x2, ( nbit + 9 ) * HCELL ) +# +# # alimentations horizontales ALU1 +# for i in range ( 0, nbit, 2 ) : +# LV_name.PHSEG ( CALU1, 6, "vss", 0 , HCELL * i + 3, 5, HCELL * i + 3 ) +# LV_name.PHSEG ( CALU1, 6, "vss", x2 - 5, HCELL * i + 3, x2, HCELL * i + 3 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", 0 , HCELL * i + 47, 5, HCELL * i + 47 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", x2 - 5, HCELL * i + 47, x2, HCELL * i + 47 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", 0 , HCELL * i + 53, 5, HCELL * i + 53 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", x2 - 5, HCELL * i + 53, x2, HCELL * i + 53 ) +# LV_name.PHSEG ( CALU1, 6, "vss", 0 , HCELL * i + 97, 5, HCELL * i + 97 ) +# LV_name.PHSEG ( CALU1, 6, "vss", x2 - 5, HCELL * i + 97, x2, HCELL * i + 97 ) +# +# for l in range ( 0, 8, 2 ) : +# LV_name.PHSEG ( CALU1, 6, "vss", 0, y1 + HCELL * l + 3, x2, y1 + HCELL * l + 3 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", 0, y1 + HCELL * l + 47, x2, y1 + HCELL * l + 47 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", 0, y1 + HCELL * l + 53, x2, y1 + HCELL * l + 53 ) +# LV_name.PHSEG ( CALU1, 6, "vss", 0, y1 + HCELL * l + 97, x2, y1 + HCELL * l + 97 ) +# +# if nword > 128 : +# LV_name.PHSEG ( CALU1, 6, "vss", 0, y1 + 403, x2, y1 + 403 ) +# LV_name.PHSEG ( CALU1, 6, "vdd", 0, y1 + 447, x2, y1 + 447 ) +# +# # routage des lignes de bit horizontales hors grille +# for i in range ( nbit ) : +# for l inr ange ( 8 ) : +# x1 = GET_REF_X ( "in%d" % i), "bit%d" % ,l ) ) +# y1 = GET_REF_Y ( "in%d" % i), "bit%d" % ,l ) ) +# x2 = GET_REF_X ( "out%d" % i), "bit%d" % ,l ) ) +# y2 = GET_REF_Y ( "out%d" % i), "bit%d" % ,l ) ) +# +# LV_name.PHSEG ( ALU2, 2, "bit%d_%d" % ( l, i ), x1, y1, x2, y2 ) +# +# # cablage a 1 de l'entree col dans le cas 64 mots +# if nword == 64 : +# x1 = GET_REF_X ( "and01_0", "refcol" ) +# y1 = GET_REF_Y ( "and01_0", "refcol" ) +# PHBIGVIA ( CONT_VIA2, x1, y1, 0, 0, "vdd" ) +# +# x1 = GET_REF_X ( "and23_0", "refcol" ) +# y1 = GET_REF_Y ( "and23_0", "refcol" ) +# PHBIGVIA ( CONT_VIA2, x1, y1, 0, 0, "vdd" ) +# +# x1 = GET_REF_X ( "and45_0", "refcol" ) +# y1 = GET_REF_Y ( "and45_0", "refcol" ) +# PHBIGVIA ( CONT_VIA2, x1, y1, 0, 0, "vdd" ) +# +# x1 = GET_REF_X ( "and67_0", "refcol" ) +# y1 = GET_REF_Y ( "and67_0", "refcol" ) +# PHBIGVIA ( CONT_VIA2, x1, y1, 0, 0, "vdd" ) +# +# # Codage Plan Memoire (codage diffusion) +# a modifier pour creer ces segments dans une figure separee +# for j in range ( 0, nword ; j+=32) : # boucle sur les cellules +# for k in range ( 4 ) : # boucle sur les colonnes +# for l in range ( 8 ) : # boucle sur le multiplexeur de sortie +# for i in range ( nbit ) : # boucle sur les bits du mot +# x1 = GET_REF_X ( "bit%d_%d" % ( i, j ), "ref%d%d" % ( k, l ) ) +# y1 = GET_REF_Y ( "bit%d_%d" % ( i, j ), "ref%d%d" % ( k, l ) ) +# +# if i < 32 : +# value = data[2*(j + 8*k + l)] +# +# if (value>>i ) % 2 == 0 : LV_name.PHSEG ( NTRANS, 1, "", x1, y1 - 3, x1, y1 + 3 ) +# else : LV_name.PHSEG ( POLY , 1, "", x1, y1 - 3, x1, y1 + 3 ) +# +# else : +# value = data[2*(j + 8*k + l)+1] +# +# if ( value>>(i-32) ) % 2 == 0 : LV_name.PHSEG ( NTRANS, 1, "", x1, y1 - 3, x1, y1 + 3 ) +# else : LV_name.PHSEG ( POLY , 1, "", x1, y1 - 3, x1, y1 + 3 ) + + + + +########## ROM_VHDL ########## +############################## +def ROM_VHDL () : + global nbit + global LV_flags + global LV_ModelName + global nword + + print "ROM behavior not yet implemented" + +# fileName = LV_ModelName + ".vbe" +# +# file = open ( fileName, "w+" ) +# +# if nword == 64 : adrange = 6 +# elif nword == 128 : adrange = 7 +# elif nword == 256 : adrange = 8 +# elif nword == 512 : adrange = 9 +# elif nword == 1024 : adrange = 10 +# +# sBusWide0 = VHDL_BUS_WIDE ( nbit - 1, 0, nbit, LV_flags ) +# sBusWide1 = VHDL_BUS_WIDE ( adrange - 1, 0, nbit, LV_flags ) +# +# ## Entity description ## +# file.write ( "\nENTITY %s IS\n PORT (\n" % LV_ModelName ) +# +# file.write ( "%14s : in BIT;\n" % "ck" ) +# file.write ( "%14s : in BIT;\n" % "selrom" ) +# file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "ad", sBusWide1 ) ) +# file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "data", sBusWide0 ) ) +# +# ## Power supplies terminals ## +# file.write ( "%14s : in BIT;\n" % "vdd" ) +# file.write ( "%14s : in BIT\n" % "vss" ) +# +# ## End of entity description ## +# file.write ( " );\nEND %s;\n\n\n" % LV_ModelName ) +# +# ## Architecture description ## +# file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % LV_ModelName ) +# +# ## Signals ## +# +# +# +# ## Behavior ## +# file.write ( "\nBEGIN\n\n" ) +# +# +# +# +# +# ## Assert ## +# file.write ( " ASSERT (vdd = '1')\n" ) +# file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % LV_modelName ) +# file.write ( " SEVERITY WARNING;\n\n" ) +# +# +# file.write ( " ASSERT (vss = '0')\n" ) +# file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % LV_modelName ) +# file.write ( " SEVERITY WARNING;\n\n" ) +# +# ## End of Architectural description ## +# file.write ( "END VBE;\n" ) +# +# file.close () diff --git a/stratus1/src/dpgen/dpgen_ADSB2F.py b/stratus1/src/dpgen/dpgen_ADSB2F.py new file mode 100644 index 00000000..2a061fb2 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_ADSB2F.py @@ -0,0 +1,362 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_ADSB2F.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenAdsb2f ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + global add_sub, c30, c31, i0, i1, q, vdd, vss + + self._nbit = self._param['nbit'] + + add_sub = SignalIn ( "add_sub", 1 ) + c30 = SignalOut ( "c30", 1 ) + c31 = SignalOut ( "c31", 1 ) + + i0 = SignalIn ( "i0", self._nbit ) + i1 = SignalIn ( "i1", self._nbit ) + q = SignalOut ( "q", self._nbit ) + + vdd = VddIn ( "vdd" ) + vss = VssIn ( "vss" ) + + ## Netlist ## + ############# + def Netlist ( self ) : + + # Liste des signaux internes + xorb = Signal ( "xorb", self._nbit ) + c = Signal ( "c", self._nbit ) + + pi = [] + gi = [] + for i in range ( self._nbit ) : + pi_bis = [] + gi_bis = [] + for j in range ( self._nbit ) : + pi_bis += [Signal("pi_%d_%d" % (i, j), 1 )] + gi_bis += [Signal("gi_%d_%d" % (i, j), 1 )] + pi += [pi_bis] + gi += [gi_bis] + + c30.Alias ( c[self._nbit-2] ) + c31.Alias ( c[self._nbit-1] ) + + # Ligne des XOR + self.Xorb = {} + for i in range ( self._nbit ) : + self.Xorb[i] = Inst ( "xr2_x1" + , "xorb%d" % i + , map = { 'i0' : add_sub + , 'i1' : i1[i] + , 'q' : xorb[i] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + # Ligne des PIGI + self.Pigi = {} + for i in range ( 1, self._nbit ) : + self.Pigi[i] = Inst ( "halfadder_x2" + , "pigi%d" % i + , map = { 'a' : i0[i] + , 'b' : xorb[i] + , 'cout' : gi[0][i] + , 'sout' : pi[0][i] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + # Ligne des PG + self.PgI1 = {} + self.PgI2 = {} + + for n in range ( 1, ilog2(self._nbit) + 1 ) : + + self.I1Bis = {} + self.I2Bis = {} + + for ipg in range ( iexp2(n) + iexp2(n-1), self._nbit, iexp2(n) ) : + inpg = ipg + + for npg in range ( iexp2(n-1) ) : + if inpg >= self._nbit : break + + self.I1Bis[inpg] = Inst ( "a2_x2" + , "pg_i1_%d_%d" % ( n, inpg ) + , map = { 'i0' : pi[n-1][ipg-1] + , 'i1' : pi[ilog2(npg)][inpg ] + , 'q' : pi[n][inpg ] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + self.I2Bis[inpg] = Inst ( "oa22_x2" + , "pg_i2_%d_%d" % ( n, inpg ) + , map = { 'i0' : pi[ilog2(npg)][inpg ] + , 'i1' : gi[n-1 ][ipg-1] + , 'i2' : gi[ilog2(npg)][inpg ] + , 'q' : gi[n ][inpg ] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + inpg += 1 + + self.PgI1[n] = self.I1Bis + self.PgI2[n] = self.I2Bis + + # Calcul des retenues + p = 2 + self.R = {} + for n in range ( 1, ilog2 ( self._nbit ) + 1 ) : + for isr in range ( iexp2 ( n - 1 ) ) : + if iexp2 ( n - 1 ) + isr >= self._nbit : break + + self.R[p] = Inst ( "oa22_x2" + , "r%d" % p + , map = { 'i0' : pi[ilog2(isr)][iexp2(n-1) + isr] + , 'i1' : c[iexp2(n-1) - 1] + , 'i2' : gi[ilog2(isr)][iexp2(n-1) + isr] + , 'q' : c[iexp2(n-1) + isr] + , 'vdd' : vdd + , 'vss' : vss + } + ) + p += 1 + + + # Calcul des sommes + self.S = {} + + for i in range ( 1, self._nbit ) : + self.S[i] = Inst ( "xr2_x1" + , "s%d" % i + , map = { 'i0' : pi[0][i] + , 'i1' : c[i-1] + , 'q' : q[i] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + # Calcul somme et retenue du LSB + self.S[0] = Inst ( "fulladder_x2" + , "s0" + , map = { 'a1' : i0[0] + , 'a2' : i0[0] + , 'a3' : i0[0] + , 'a4' : i0[0] + , 'b1' : xorb[0] + , 'b2' : xorb[0] + , 'b3' : xorb[0] + , 'b4' : xorb[0] + , 'cin1' : add_sub + , 'cin2' : add_sub + , 'cin3' : add_sub + , 'cout' : c[0] + , 'sout' : q[0] + , 'vdd' : vdd + , 'vss' : vss + } + ) + + + ## Layout ## + ############ + def Layout ( self ) : + + twostage = -1 + + # Ligne des XOR + Place ( self.Xorb[0], NOSYM, XY ( 0, 0 ) ) + + for i in range ( 1, self._nbit ) : + if i % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + PlaceTop ( self.Xorb[i], sym ) + + # Ligne des PIGI + if self._nbit > 1 : Place ( self.Pigi[1], SYM_Y, XY ( 45, 50 ) ) + + for i in range ( 2, self._nbit ) : + if i % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + PlaceTop ( self.Pigi[i], sym ) + + # Ligne des PG + for n in range ( 1, ilog2(self._nbit) + 1, 2 ) : + twostage += 1 + pi = self._nbit - 1 + + for i in range ( self._nbit - 1, 0, -1 ) : + if i >= iexp2(n) + iexp2(n-1) and i & ( 1 << (n-1) ) : + + if pi % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + + Place ( self.PgI1[n][i], sym, XY ( 125 + 55 * twostage, pi * 50 ) ) + Place ( self.PgI2[n][i], sym, XY ( 150 + 55 * twostage, pi * 50 ) ) + + pi -= 1 + + if i >= iexp2(n+1) + iexp2(n) and i & ( 1 << n ) : + + if pi % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + Place ( self.PgI1[n+1][i], sym, XY ( 125 + 55 * twostage, pi * 50 ) ) + Place ( self.PgI2[n+1][i], sym, XY ( 150 + 55 * twostage, pi * 50 ) ) + + pi -= 1 + + # nbit n'est pas une puissance entiere de 2 + if self._nbit % ( iexp2 ( ilog2 ( self._nbit ) - 1 ) ) : twostage += 1 + + # Ligne retenue + for n in range ( 2, self._nbit + 1 ) : + if ( n - 1 ) % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + Place ( self.R[n], sym, XY ( 125 + 55 * twostage, ( n - 1 ) * 50 ) ) + + + # Calcul des sommes + if self._nbit > 1 : Place ( self.S[1], NOSYM, XY ( 155 + 55 * twostage, 0 ) ) + + for i in range ( 2, self._nbit ) : + if ( i - 1 ) % 2 == 0 : sym = NOSYM + else : sym = SYM_Y + PlaceTop ( self.S[i], sym ) + + + # Calcul somme et retenue du LSB + Place ( self.S[0], NOSYM, XY ( 45, 0 ) ) + + + ########## VHDL ########## + ########################## + def Vbe ( self ) : + + name = self._name + + LV_flags = self._param['flags'] + + fileName = name + ".vbe" + + file = open ( fileName, "w+" ) + + sBusWide0 = VHDL_BUS_WIDE ( self._nbit - 1, 0, self._nbit, LV_flags ) + sBusWide1 = VHDL_BUS_WIDE ( self._nbit , 1, self._nbit, LV_flags ) + sBusWide2 = VHDL_BUS_WIDE ( self._nbit , 0, self._nbit, LV_flags ) + + ## Entity description ## + file.write ( "\nENTITY %s IS\n PORT (\n" % name ) + + file.write ( "%14s : in BIT;\n" % "add_sub" ) + file.write ( "%14s : out BIT;\n" % "c31" ) + file.write ( "%14s : out BIT;\n" % "c30" ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide0 ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i1", sBusWide0 ) ) + file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "q", sBusWide0 ) ) + + ## Power supplies terminals ## + file.write ( "%14s : in BIT;\n" % "vdd" ) + file.write ( "%14s : in BIT\n" % "vss" ) + + ## End of entity description ## + file.write ( " );\nEND %s;\n\n\n" % name ) + + ## Architecture description ## + file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % name ) + + ## Signals ## + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "carry", sBusWide2 ) ) + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "xor_b", sBusWide0 ) ) + + ## Behavior ## + file.write ( "\nBEGIN\n\n" ) + + for i in range ( self._nbit - 1, -1, -1 ) : + file.write ( " xor_b(%ld) <= i1(%ld) xor add_sub;\n" % ( i, i ) ) + + file.write ( "\n" ) + + file.write ( " carry(0) <= add_sub;\n\n" ) + + file.write ( " q <= i0\n" ) + file.write ( " xor xor_b\n" ) + file.write ( " xor carry%s;\n\n" % sBusWide0 ) + + file.write ( " c31 <= carry(%ld);\n" % self._nbit ) + file.write ( " c30 <= carry(%ld);\n\n" % ( self._nbit - 1 ) ) + + file.write ( " carry%s <= ( i0 and xor_b)\n" % sBusWide1 ) + file.write ( " or ( i0 and carry%s)\n" % sBusWide0 ) + file.write ( " or (xor_b and carry%s);\n\n\n" % sBusWide0 ) + + ## Assert ## + file.write ( " ASSERT (vdd = '1')\n" ) + file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + file.write ( " ASSERT (vss = '0')\n" ) + file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + ## End of Architectural description ## + file.write ( "END VBE;\n" ) + + file.close () diff --git a/stratus1/src/dpgen/dpgen_Nul.py b/stratus1/src/dpgen/dpgen_Nul.py new file mode 100644 index 00000000..98928c86 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_Nul.py @@ -0,0 +1,406 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_Nul.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenNul ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + + self._nbit = self._param['nbit'] + + self._i0 = SignalIn ( "i0", self._nbit ) + self._nul = SignalOut ( "nul", 1 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self ) : + global LV_prevTreeOut + global LV_oneShift + + global nul + + LV_prevTreeOut = -1 + LV_oneShift = 0 + + offset = 0 + depthNext = get_depth ( self._nbit, 0 ) + + nul = [] + for i in range ( self._nbit ) : + nul += [Signal ( "nul_%d" % i, 1 )] + + self.Nul = {} + + while ( 1 ) : + depth = depthNext + depthNext = get_depth ( self._nbit, depth + 1 ) + + offset = self.create_Netlist_Tree ( offset, depth, depthNext ) + + if depthNext == 0 : break # Simulation d'une boucle do ... while + + + + ########## Layout ########## + ############################ + def Layout ( self ) : + global LV_prevTreeOut + global LV_oneShift + + mDepth = ilog2 ( self._nbit ) + + LV_prevTreeOut = -1 + LV_oneShift = 0 + + offset = 0 + depthNext = get_depth ( self._nbit, 0 ) + + while ( 1 ) : + depth = depthNext + depthNext = get_depth ( self._nbit, depth + 1 ) + + offset = self.create_Layout_Tree ( offset, depth, depthNext ) + + if depthNext == 0 : break + + + + ########## VBE ########## + ######################### + def Vbe ( self ) : + + flags = self._param['flags'] + + fileName = self._name + ".vbe" + + file = open ( fileName, "w+" ) + + sBusWide = VHDL_BUS_WIDE ( self._nbit - 1, 0, self._nbit, flags ) + + ## Entity description ## + file.write ( "\nENTITY %s IS\n PORT (\n" % self._name ) + + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide ) ) + file.write ( "%14s : out BIT;\n" % "nul" ) + + file.write ( "%14s : in BIT;\n" % "vdd" ) + file.write ( "%14s : in BIT\n" % "vss" ) + + ## End of entity description ## + file.write ( " );\nEND %s;\n\n\n" % self._name ) + + ## Architecture description ## + file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % self._name ) + + file.write ( "BEGIN\n\n" ) + + xl_zero = newxl () + xl_zero._size = self._nbit + + file.write ( " nul <= \'1\' WHEN (i0 = %s)\n" % xl_zero.xltovhdl () ) + file.write ( " ELSE \'0\';\n\n\n" ) + + ## Assert ## + file.write ( " ASSERT (vdd = '1')\n" ) + file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + file.write ( " ASSERT (vss = '0')\n" ) + file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + ## End of architecture description ## + file.write ( "END VBE;\n" ) + + file.close () + + + + + ########## create_Netlist_Tree ########## + ######################################### + def create_Netlist_Tree ( self, aOffset, amDepth, amDepthNext ) : + global LV_prevTreeOut + global LV_oneShift + + global nul + + if amDepthNext > 0 : polarity = amDepthNext % 2 + else : polarity = amDepth % 2 + + if not ( amDepth ) : + if not ( amDepthNext ) : + # Pathological case : the zero detect is reduced to only one bit! This is only a inversor. + self.Nul[aOffset] = Inst ( "inv_x4" + , "nul_%ld" % aOffset + , map = { 'i' : self._i0[aOffset] + , 'nq' : self._nul + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + LV_prevTreeOut = aOffset + + if ( amDepth % 2 ) == polarity : + # This branch will skip an even number of layer, we keep the same polarity. + self._i0[aOffset].Alias ( nul[aOffset] ) + else : + # There is a polarity inversion. + self.Nul[aOffset] = Inst ( "inv_x4" + , "nul_%ld" % aOffset + , map = { 'i' : self._i0[aOffset] + , 'nq' : nul[aOffset] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + LV_oneShift = 1 + aOffset += 1 + + aOffset += 1 + return aOffset + + + # Build the tree. + for depth in range ( amDepth ) : + mk = iexp2 ( amDepth - depth - 1 ) + + for k in range ( mk ) : + if depth : i_offset = iexp2 ( depth - 1 ) - 1 + else : i_offset = 0 + + cell_index = iexp2 ( depth + 1 ) * k + iexp2 ( depth ) - 1 + aOffset + + i1_index = iexp2 ( depth + 1 ) * k + iexp2 ( depth ) + i_offset + aOffset + i0_index = iexp2 ( depth + 1 ) * k + i_offset + aOffset + + if depth % 2 : sModel = "na2_x1" + else : sModel = "no2_x1" + + thisMap = {} + + thisMap['nq'] = nul[cell_index] + + if depth : + thisMap['i0'] = nul[i0_index] + thisMap['i1'] = nul[i1_index] + else : + thisMap['i0'] = self._i0[i0_index - LV_oneShift] + thisMap['i1'] = self._i0[i1_index - LV_oneShift] + + # Special case of the last layer. + if mk == 1 and LV_prevTreeOut < 0 : + if not ( amDepthNext ) : + # This is the only tree in the operator. + if depth % 2 : + sModel = "a2_x4" + + thisMap['q'] = self._nul + if thisMap.has_key('nq') : del thisMap['nq'] + else : + sModel = "no2_x4" + thisMap['nq'] = self._nul + + else : + if depth % 2 == polarity : + # Only for the first tree : adjust the polarity. + if depth % 2 : sModel = "a2_x2" + else : sModel = "o2_x2" + + if thisMap.has_key('nq') : del thisMap['nq'] + thisMap['q'] = nul[cell_index] + + thisMap['vdd'] = self._vdd + thisMap['vss'] = self._vss + + self.Nul[cell_index] = Inst ( sModel + , "nul_%ld" % cell_index + , map = thisMap + ) + + depth += 1 # Attention : difference entre les boucles en c et les boucles en python + + # Check if there is a ripple part. + if LV_prevTreeOut < 0 : + LV_prevTreeOut = cell_index + + return ( aOffset + iexp2 ( amDepth ) ) + + # Add the ripple part. + cell_index = aOffset - 1 + + thisMap = {} + + if not ( amDepthNext ) : + if depth % 2 : + sModel = "a2_x4" + thisMap['q'] = self._nul + else : + sModel = "no2_x4" + thisMap['nq'] = self._nul + + else : + if depth % 2 : sModel = "na2_x1" + else : sModel = "no2_x1" + + if depth % 2 != polarity : + thisMap['nq'] = nul[cell_index] + else : + thisMap['q'] = nul[cell_index] + + if depth % 2 == polarity : + if depth % 2 : sModel = "a2_x2" + else : sModel = "o2_x2" + + i1_index = iexp2 ( amDepth - 1 ) - 1 + aOffset + i0_index = LV_prevTreeOut + + thisMap['i0'] = nul[i0_index] + thisMap['i1'] = nul[i1_index] + + thisMap['vdd'] = self._vdd + thisMap['vss'] = self._vss + + self.Nul[aOffset-1] = Inst ( sModel + , "nul_%ld" % ( aOffset - 1 ) + , map = thisMap + ) + + LV_prevTreeOut = cell_index + + return ( aOffset + iexp2 ( amDepth ) ) + + + + ########## create_Layout_Tree ########## + ######################################## + def create_Layout_Tree ( self, aOffset, amDepth, amDepthNext ) : + global LV_oneShift + global LV_prevTreeOut + + if amDepthNext > 0 : polarity = amDepthNext % 2 + else : polarity = amDepth % 2 + + if not ( amDepth ) : + if not ( amDepthNext ) : + # Cas pathologique : detection a un seul bit : c'est un inverseur + dpgen_place ( self.Nul[aOffset], 0, aOffset * 50 ) + else : + LV_prevTreeOut = aOffset + + if ( amDepth % 2 ) != polarity : dpgen_place ( self.Nul[aOffset], 0, aOffset * 50 ) + + LV_oneShift = 1 + aOffset += 1 + + aOffset += 1 + + return aOffset + + + # Build the tree. + for depth in range ( amDepth ) : + mk = iexp2 ( amDepth - depth - 1 ) + + for k in range ( mk ) : + cell_index = iexp2 ( depth + 1 ) * k + iexp2 ( depth ) - 1 + aOffset + + if depth % 2 : sModel = "na2_x1" + else : sModel = "no2_x1" + + # Special case of the last layer. + if mk == 1 and LV_prevTreeOut < 0 : + if not ( amDepthNext ) : + # This is the only tree in the operator. + if depth % 2 : sModel = "a2_x4" + else : sModel = "no2_x4" + + else : + if depth % 2 == polarity : + # Only for the first tree : adjust the polarity. + if depth % 2 : sModel = "a2_x2" + else : sModel = "o2_x2" + + dpgen_place ( self.Nul[cell_index], 0, cell_index * 50 ) + + if LV_prevTreeOut < 0 : + LV_prevTreeOut = cell_index + + return ( aOffset + iexp2 ( amDepth ) ) + + + if not ( amDepthNext ) : + if depth % 2 : sModel = "a2_x4" + else : sModel = "no2_x4" + + else : + if depth % 2 : sModel = "na2_x1" + else : sModel = "no2_x1" + + if depth % 2 == polarity : + if depth % 2 : sModel = "a2_x2" + else : sModel = "o2_x2" + + cell_index = aOffset - 1 + + dpgen_place ( self.Nul[aOffset-1], 0, ( aOffset - 1 ) * 50 ) + + LV_prevTreeOut = cell_index + + return ( aOffset + iexp2 ( amDepth ) ) diff --git a/stratus1/src/dpgen/dpgen_RAM.py b/stratus1/src/dpgen/dpgen_RAM.py new file mode 100644 index 00000000..939e4847 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_RAM.py @@ -0,0 +1,675 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_RAM.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenRam ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + global adrange + + self._nbit = self._param['nbit'] + self._nmot = self._param['nword'] + + if self._nbit % 2 == 1 or self._nbit > 64 or self._nbit < 2 : + print "Error in DpgenRam : the bit number must be even and no larger than 64\n" + sys.exit ( 3 ) + + if self._nmot % 8 != 0 or self._nmot > 256 or self._nmot < 32 : + print "Error in instanciaton of DpgenRam" + print "The word number (nword = %d) " % self._nmot, "must be multiple of 8, at least 32 and no larger than 256.\n" + sys.exit ( 3 ) + + if self._nmot > 128 : adrange = 8 + elif self._nmot > 64 : adrange = 7 + elif self._nmot > 32 : adrange = 6 + else : adrange = 5 + + # Connecteurs externes + self._ck = SignalIn ( "ck", 1 ) + self._w = SignalIn ( "w", 1 ) + self._selram = SignalIn ( "selram", 1 ) + + self._ad = SignalIn ( "ad", adrange ) + self._datain = SignalIn ( "datain", self._nbit ) + + self._dataout = TriState ( "dataout", self._nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self ) : + + # Signaux + prech = Signal ( "prech", 1 ) + prechbis = Signal ( "prechbis", 1 ) + + ad0x = Signal ( "ad0x", 1 ) + nad0x = Signal ( "nad0x", 1 ) + + nsense = Signal ( "nsense", 1 ) + sensex = Signal ( "sensex", 1 ) + nsensex = Signal ( "nsensex", 1 ) + + selramx = Signal ( "selramx", 1 ) + + nwrite = Signal ( "nwrite", 1 ) + writex = Signal ( "writex", 1 ) + + ndec00 = Signal ( "ndec00", 1 ) + ndec01 = Signal ( "ndec01", 1 ) + ndec10 = Signal ( "ndec10", 1 ) + ndec11 = Signal ( "ndec11", 1 ) + + nck = Signal ( "nck", 1 ) + nckx = Signal ( "nckx", 1 ) + nckxbis = Signal ( "nckxbis", 1 ) + + ad3x = Signal ( "ad3x", 1 ) + nad3x = Signal ( "nad3x", 1 ) + ad4x = Signal ( "ad4x", 1 ) + nad4x = Signal ( "nad4x", 1 ) + if adrange > 5 : + ad5x = Signal ( "ad5x", 1 ) + nad5x = Signal ( "nad5x", 1 ) + if adrange > 6 : + ad6x = Signal ( "ad6x", 1 ) + nad6x = Signal ( "nad6x", 1 ) + if adrange > 7 : + ad7x = Signal ( "ad7x", 1 ) + nad7x = Signal ( "nad7x", 1 ) + + bus0 = [] + nbus0 = [] + bus1 = [] + nbus1 = [] + + sel = [] + nsel = [] + selx = [] + + ndeca = [] + ndecb = [] + for i in range ( self._nbit ) : + bus0 += [Signal ( "bus0_%d" % i, 1 )] + nbus0 += [Signal ( "nbus0_%d" % i, 1 )] + bus1 += [Signal ( "bus1_%d" % i, 1 )] + nbus1 += [Signal ( "nbus1_%d" % i, 1 )] + + for i in range ( self._nmot ) : + sel += [Signal ( "sel%d" % i, 1 )] + nsel += [Signal ( "nsel%d" % i, 1 )] + selx += [Signal ( "selx%d" % i, 1 )] + + ndeca += [Signal ( "ndeca%d" % i, 1 )] + ndecb += [Signal ( "ndecb%d" % i, 1 )] + + + # Lignes de bit + self.Prech = {} + self.Bit = {} + self.Sense = {} + + bottom = 0 + for i in range ( self._nbit ) : + self.Prech[i] = Inst ( "ram_prech_data" + , "prech%d" % i + , map = { 'prech' : prech + , 'bit0' : bus0[i] + , 'nbit0' : nbus0[i] + , 'bit1' : bus1[i] + , 'nbit1' : nbus1[i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis = {} + for j in range ( 0, self._nmot, 4 ) : + + self.BitBis[j] = Inst ( "ram_mem_data" + , "bit_%d_%d" % ( i, j ) + , map = { 'selxi' : selx[j] + , 'bit0' : bus0[i] + , 'nbit0' : nbus0[i] + , 'bit1' : bus1[i] + , 'nbit1' : nbus1[i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis[j+2] = Inst ( "ram_mem_data" + , "bit_%d_%d" % ( i, j + 2 ) + , map = { 'selxi' : selx[j+2] + , 'bit0' : bus0[i] + , 'nbit0' : nbus0[i] + , 'bit1' : bus1[i] + , 'nbit1' : nbus1[i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Bit[i] = self.BitBis + + self.Sense[i] = Inst ( "ram_sense_data" + , "sense%d" % i + , map = { 'bit0' : bus0[i] + , 'nbit0' : nbus0[i] + , 'bit1' : bus1[i] + , 'nbit1' : nbus1[i] + , 'ad0x' : ad0x + , 'nad0x' : nad0x + , 'sensex' : sensex + , 'nsensex' : nsensex + , 'prechx' : prechbis + , 'writex' : writex + , 'din' : self._datain[i] + , 'dout' : self._dataout[i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Premiere ligne de la zone des buffers + self.PrechBuf0 = Inst ( "ram_prech_buf0" + , "prechbuf0" + , map = { 'i' : nckx + , 'nq' : prech + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf0 = {} + for j in range ( 0, self._nmot, 4 ) : + self.Buf0[j] = Inst ( "ram_mem_buf0" + , "buf0_%d" % j + , map = { 'i' : nsel[j] + , 'nq' : selx[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf0[j+2] = Inst ( "ram_mem_buf0" + , "buf0_%d" % ( j + 2 ) + , map = { 'i' : nsel[j+2] + , 'nq' : selx[j+2] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SenseBuf0 = Inst ( "ram_sense_buf0" + , "sensebuf0" + , map = { 'ad0' : self._ad[0] + , 'nsense' : nsense + , 'nckx' : nckxbis + , 'nwrite' : nwrite + , 'ad0x' : ad0x + , 'nad0x' : nad0x + , 'sensex' : sensex + , 'nsensex' : nsensex + , 'prech' : prechbis + , 'writex' : writex + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne de la zone des buffers + self.PrechBuf1 = Inst ( "ram_prech_buf1" + , "prechbuf1" + , map = { 'nck' : nck + , 'nckx' : nckx + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf1 = {} + for j in range ( 0, self._nmot, 4 ) : + self.Buf1[j] = Inst ( "ram_mem_buf1" + , "buf1_%d" % j + , map = { 'seli' : sel[j] + , 'nck' : nck + , 'selramx' : selramx + , 'nseli' : nsel[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf1[j+2] = Inst ( "ram_mem_buf1" + , "buf1_%d" % ( j + 2 ) + , map = { 'seli' : sel[j+2] + , 'nck' : nck + , 'selramx' : selramx + , 'nseli' : nsel[j+2] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SenseBuf1 = Inst ( "ram_sense_buf1" + , "sensebuf1" + , map = { 'ck' : self._ck + , 'selram' : self._selram + , 'w' : self._w + , 'nck' : nck + , 'selramx' : selramx + , 'nsense' : nsense + , 'nwrite' : nwrite + , 'nckx' : nckxbis + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Premiere ligne de la zone du decodeur + self.PrechDecB = Inst ( "ram_prech_dec0" + ,"prechdecb" + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Dec = {} + for j in range ( 0, self._nmot, 8 ) : + self.Dec[j] = Inst ( "ram_mem_deci" + , "dec_%d" % j + , map = { 'i0' : ndeca[j] + , 'i1' : ndecb[j] + , 'i2' : ndec00 + , 'seli' : sel[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Dec[j+2] = Inst ( "ram_mem_deci" + , "dec_%d" % ( j + 2 ) + , map = { 'i0' : ndeca[j] + , 'i1' : ndecb[j] + , 'i2' : ndec01 + , 'seli' : sel[j+2] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Dec[j+4] = Inst ( "ram_mem_deci" + , "dec_%d" % ( j + 4 ) + , map = { 'i0' : ndeca[j] + , 'i1' : ndecb[j] + , 'i2' : ndec10 + , 'seli' : sel[j+4] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Dec[j+6] = Inst ( "ram_mem_deci" + , "dec_%d" % ( j + 6 ) + , map = { 'i0' : ndeca[j] + , 'i1' : ndecb[j] + , 'i2' : ndec11 + , 'seli' : sel[j+6] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SenseDecAd12 = Inst ( "ram_sense_decad12" + , "sensedecad12" + , map = { 'ad1' : self._ad[1] + , 'ad2' : self._ad[2] + , 'ndec00' : ndec00 + , 'ndec01' : ndec01 + , 'ndec10' : ndec10 + , 'ndec11' : ndec11 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne de la zone du decodeur + if adrange == 8 : # adresse sur 8 bits : on decode 5 bits + self.PrechDecU = Inst ( "ram_prech_dec0" + , "prechdecu" + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.MemDec = {} + for j in range ( 0, self._nmot, 8 ) : + thisMap = { 'ndeca' : ndeca[j] + , 'ndecb' : ndecb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if ( j >> 3 ) % 2 == 0 : thisMap['i0'] = nad3x + else : thisMap['i0'] = ad3x + + if ( j >> 4 ) % 2 == 0 : thisMap['i1'] = nad4x + else : thisMap['i1'] = ad4x + + if ( j >> 5 ) % 2 == 0 : thisMap['i2'] = nad5x + else : thisMap['i2'] = ad5x + + if ( j >> 6 ) % 2 == 0 : thisMap['i3'] = nad6x + else : thisMap['i3'] = ad6x + + if ( j >> 7 ) % 2 == 0 : thisMap['i4'] = nad7x + else : thisMap['i4'] = ad7x + + self.MemDec[j] = Inst ( "ram_mem_dec5" + , "memdec%d" % j + , map = thisMap + ) + + self.SenseDecAd = Inst ( "ram_sense_decad5" + , "sensedecad" + , map = { 'ad3' : self._ad[3] + , 'ad4' : self._ad[4] + , 'ad5' : self._ad[5] + , 'ad6' : self._ad[6] + , 'ad7' : self._ad[7] + , 'ad3x' : ad3x + , 'nad3x' : nad3x + , 'ad4x' : ad4x + , 'nad4x' : nad4x + , 'ad5x' : ad5x + , 'nad5x' : nad5x + , 'ad6x' : ad6x + , 'nad6x' : nad6x + , 'ad7x' : ad7x + , 'nad7x' : nad7x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 7 : # adresse sur 7 bits : on decode 4 bits + self.PrechDecU = Inst ( "ram_prech_dec0" + , "prechdecu" + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.MemDec = {} + for j in range ( 0, self._nmot, 8 ) : + thisMap = { 'ndeca' : ndeca[j] + , 'ndecb' : ndecb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if ( j >> 3 ) % 2 == 0 : thisMap['i0'] = nad3x + else : thisMap['i0'] = ad3x + + if ( j >> 4 ) % 2 == 0 : thisMap['i1'] = nad4x + else : thisMap['i1'] = ad4x + + if ( j >> 5 ) % 2 == 0 : thisMap['i2'] = nad5x + else : thisMap['i2'] = ad5x + + if ( j >> 6 ) % 2 == 0 : thisMap['i3'] = nad6x + else : thisMap['i3'] = ad6x + + self.MemDec[j] = Inst ( "ram_mem_dec4" + , "memdec%d" % j + , map = thisMap + ) + + self.SenseDecAd = Inst ( "ram_sense_decad4" + , "sensedecad" + , map = { 'ad3' : self._ad[3] + , 'ad4' : self._ad[4] + , 'ad5' : self._ad[5] + , 'ad6' : self._ad[6] + , 'ad3x' : ad3x + , 'nad3x' : nad3x + , 'ad4x' : ad4x + , 'nad4x' : nad4x + , 'ad5x' : ad5x + , 'nad5x' : nad5x + , 'ad6x' : ad6x + , 'nad6x' : nad6x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 6 : # adresse sur 6 bits : on decode 3 bits + self.PrechDecU = Inst ( "ram_prech_dec0" + , "prechdecu" + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.MemDec = {} + for j in range ( 0, self._nmot, 8 ) : + thisMap = { 'ndeca' : ndeca[j] + , 'ndecb' : ndecb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if ( j >> 3 ) % 2 == 0 : thisMap['i0'] = nad3x + else : thisMap['i0'] = ad3x + + if ( j >> 4 ) % 2 == 0 : thisMap['i1'] = nad4x + else : thisMap['i1'] = ad4x + + if ( j >> 5 ) % 2 == 0 : thisMap['i2'] = nad5x + else : thisMap['i2'] = ad5x + + self.MemDec[j] = Inst ( "ram_mem_dec3" + , "memdec%d" % j + , map = thisMap + ) + + self.SenseDecAd = Inst ( "ram_sense_decad3" + , "sensedecad" + , map = { 'ad3' : self._ad[3] + , 'ad4' : self._ad[4] + , 'ad5' : self._ad[5] + , 'ad3x' : ad3x + , 'nad3x' : nad3x + , 'ad4x' : ad4x + , 'nad4x' : nad4x + , 'ad5x' : ad5x + , 'nad5x' : nad5x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 5 : # adresse sur 5 bits : on decode 2 bits + self.PrechDecU = Inst ( "ram_prech_dec0" + , "prechdecu" + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.MemDec = {} + for j in range ( 0, self._nmot, 8 ) : + thisMap = { 'ndeca' : ndeca[j] + , 'ndecb' : ndecb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if ( j >> 3 ) % 2 == 0 : thisMap['i0'] = nad3x + else : thisMap['i0'] = ad3x + + if ( j >> 4 ) % 2 == 0 : thisMap['i1'] = nad4x + else : thisMap['i1'] = ad4x + + self.MemDec[j] = Inst ( "ram_mem_dec2" + , "memdec%d" % j + , map = thisMap + ) + + self.SenseDecAd = Inst ( "ram_sense_decad2" + , "sensedecad" + , map = { 'ad3' : self._ad[3] + , 'ad4' : self._ad[4] + , 'ad3x' : ad3x + , 'nad3x' : nad3x + , 'ad4x' : ad4x + , 'nad4x' : nad4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ########## Layout ########## + ############################ + def Layout ( self ) : + + HCELL = 50 + + # Lignes de bit + bottom = 0 + + for i in range ( self._nbit ) : + if i % 2 : # lignes impaires + sym1 = SYM_Y + sym2 = SYMXY + else : # lignes paires + sym1 = NOSYM + sym2 = SYM_X + + Place ( self.Prech[i], sym1, XY ( 0, bottom + i * HCELL ) ) + + for j in range ( 0, self._nmot, 4 ) : + PlaceRight ( self.Bit[i][j], sym2 ) + PlaceRight ( self.Bit[i][j+2], sym1 ) + + PlaceRight ( self.Sense[i], sym1 ) + + # Premiere ligne de la zone des buffers + bottom = self._nbit * HCELL + + Place ( self.PrechBuf0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( 0, self._nmot, 4 ) : + PlaceRight ( self.Buf0[j], SYM_X ) + PlaceRight ( self.Buf0[j+2], NOSYM ) + + PlaceRight ( self.SenseBuf0, NOSYM ) + + # Deuxieme ligne de la zone des buffers + bottom = ( self._nbit + 1 ) * HCELL + + Place ( self.PrechBuf1, SYM_Y, XY ( 0, bottom ) ) + + for j in range ( 0, self._nmot, 4 ) : + PlaceRight ( self.Buf1[j], SYMXY ) + PlaceRight ( self.Buf1[j+2], SYM_Y ) + + PlaceRight ( self.SenseBuf1, SYM_Y ) + + # Premiere ligne de la zone du decodeur + bottom = ( self._nbit + 2 ) * HCELL + + Place ( self.PrechDecB, NOSYM, XY ( 0, bottom ) ) + + for j in range ( 0, self._nmot, 8 ) : + PlaceRight ( self.Dec[j], SYM_X ) + PlaceRight ( self.Dec[j+2], NOSYM ) + PlaceRight ( self.Dec[j+4], SYM_X ) + PlaceRight ( self.Dec[j+6], NOSYM ) + + PlaceRight ( self.SenseDecAd12, NOSYM ) + + # Deuxieme ligne de la zone du decodeur + bottom = ( self._nbit + 3 ) * HCELL + + if adrange == 8 : # adresse sur 8 bits : on decode 5 bits + Place ( self.PrechDecU, SYM_Y, XY ( 0, bottom ) ) + for j in range ( 0, self._nmot, 8 ) : PlaceRight ( self.MemDec[j], SYM_Y ) + PlaceRight ( self.SenseDecAd, SYM_Y ) + + if adrange == 7 : # adresse sur 7 bits : on decode 4 bits + Place ( self.PrechDecU, SYM_Y, XY ( 0, bottom ) ) + for j in range ( 0, self._nmot, 8 ) : PlaceRight ( self.MemDec[j], SYM_Y ) + PlaceRight ( self.SenseDecAd, SYM_Y ) + + if adrange == 6 : # adresse sur 6 bits : on decode 3 bits + Place ( self.PrechDecU, SYM_Y, XY ( 0, bottom ) ) + for j in range ( 0, self._nmot, 8 ) : PlaceRight ( self.MemDec[j], SYM_Y ) + PlaceRight ( self.SenseDecAd, SYM_Y ) + + if adrange == 5 : # adresse sur 5 bits : on decode 2 bits + Place ( self.PrechDecU, SYM_Y, XY ( 0, bottom ) ) + for j in range ( 0, self._nmot, 8 ) : PlaceRight ( self.MemDec[j], SYM_Y ) + PlaceRight ( self.SenseDecAd, SYM_Y ) + + + ## VBE ## + ######### + def Vbe () : + print "RAM behavior not yet implemented" diff --git a/stratus1/src/dpgen/dpgen_RF1.py b/stratus1/src/dpgen/dpgen_RF1.py new file mode 100644 index 00000000..d42bf426 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_RF1.py @@ -0,0 +1,1441 @@ +#!/usr/bin/pythn + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_RF1.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +# Banc de registre double acces : une lecture, une ecriture +# Le programme genere une net-list et un placement optimise. +# On peut generer trois types d'operateurs: +# - banc de registres sans decodeur +# - banc de registres avec decodeur +# - banc de registre de LV_type fifo +# +# La largeur est egale a ( nmot * 25 ) + 100 +# La hauteur est egale a ( nbit + 2 ) * 50 sans decodeur +# ( nbit + 6 ) * 50 avec decodeur +# ( nbit + 8 ) * 50 pour la fifo +# +# Pour la partie "donnees", on utilise les LV_names suivantes : +# colonne d'entree +# - rf_inmux_mem +# - rf_inmux_buf_2 +# - rf_inmux_buf_4 +# colonne centrale +# - rf_mid_mem +# - rf_mid_mem_r0 +# - rf_mid_buf_2 +# - rf_mid_buf_4 +# colonne de sortie +# - rf_out_mem +# - rf_out_buf_2 +# - rf_out_buf_4 +# +# Pour le controleur fifo, on utilise les LV_names suivantes : +# - rf_fifo_buf +# - rf_fifo_clock +# - rf_fifo_empty +# - rf_fifo_full +# - rf_fifo_inc +# - rf_fifo_nop +# - rf_fifo_ok +# - rf_fifo_orand4 +# - rf_fifo_orand5 +# - rf_fifo_ptreset +# - rf_fifo_ptset +# +# Pour le decodeur, on utilise les LV_names suivantes : +# - rf_dec_bufad0 +# - rf_dec_bufad1 +# - rf_dec_bufad2 +# - rf_dec_nbuf +# - rf_dec_nor3 +# - rf_dec_nao3 +# - rf_dec_nand2 +# - rf_dec_nand3 +# - rf_dec_nand4 + + +#---------------------------------------------------------------- +# DEBUT PROGRAMME PRINCIPAL +#---------------------------------------------------------------- +# aFunction : le type : +# DPGEN_RF1 : sans decodeur +# DPGEN_RF1R0 : sans decodeur, avec R0 colle a 0 +# DPGEN_RF1D : avec decodeur +# DPGEN_RF1DR0 : avec decodeur, avec R0 colle a 0 +# DPGEN_FIFO : une fifo +# +# Liste des parametres : +# ModelName : nom de modele. +# flags : indexation des connecteurs. +# n : nombre de bits (largeur du bus). +# nmot : nombre de mots. +# - le nombre de mots doit etre pair et =< 32 +# - le nombre de bits doit etre pair, non nul et =< 64 +#---------------------------------------------------------------- + + + +################### +##### top_RF1 ##### +################### +class top_rf1 ( Model ) : + + ## Interface ## + ############### + def Interface ( self, nbit, nword, type ) : + global nbitu, hbuf, adrange + + nbitu = 0 + + if nword % 2 == 1 or nword > 32 or nword < 4 : + print "Error in DpgenRf1 : the word number must be even larger than 4 and no larger than 32\n" + sys.exit ( 3 ) + + if nword == 4 and ( type == 2 or type == 3 ) : + print "Error in DpgenRf1 : the word number must be larger than 4\n" + sys.exit ( 3 ) + + if nbit % 2 == 1 or nbit > 64 or nbit < 2 : + print "Error in DpgenRf1 : the bit number must be even and no larger than 64\n" + sys.exit ( 3 ) + + adrange = 2 + if nword > 4 : adrange = 3 + if nword > 8 : adrange = 4 + if nword > 16 : adrange = 5 + + if type < 2 : # c'est un banc de registres sans decodeur + self._ck = SignalIn ( "ck", 1 ) + self._sel = SignalIn ( "sel", 1 ) + + self._selr = SignalIn ( "selr", nword ) + self._selw = SignalIn ( "selw", nword ) + self._datain0 = SignalIn ( "datain0", nbit ) + self._datain1 = SignalIn ( "datain1", nbit ) + self._dataout = SignalOut ( "dataout", nbit ) + + elif type < 4 : # c'est un banc de registres avec decodeur + self._ck = SignalIn ( "ck", 1 ) + self._sel = SignalIn ( "sel", 1 ) + self._wen = SignalIn ( "wen", 1 ) + self._ren = SignalIn ( "ren", 1 ) + + self._adr = SignalIn ( "adr", adrange ) + self._adw = SignalIn ( "adw", adrange ) + self._datain0 = SignalIn ( "datain0", nbit ) + self._datain1 = SignalIn ( "datain1", nbit ) + self._dataout = SignalOut ( "dataout", nbit ) + + self._selr = Signal ( "selr", nword ) + self._selw = Signal ( "selw", nword ) + + else : # c'est une fifo + self._ck = SignalIn ( "ck", 1 ) + self._reset = SignalIn ( "reset", 1 ) + self._r = SignalIn ( "r", 1 ) + self._w = SignalIn ( "w", 1 ) + self._rok = SignalInOut ( "rok", 1 ) + self._wok = SignalInOut ( "wok", 1 ) + self._sel = SignalIn ( "sel", 1 ) + + self._datain0 = SignalIn ( "datain0", nbit ) + self._datain1 = SignalIn ( "datain1", nbit ) + self._dataout = SignalOut ( "dataout", nbit ) + + self._selr = Signal ( "selr", nword ) + self._selw = Signal ( "selw", nword ) + self._ckok = Signal ( "ckok", 1 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############## + def Netlist ( self, nbit, nword, type ) : + + hbuf = 2 # hauteur des buffers (2 ou 4 slices) : non utilise + + # choix des LV_names buffer + if hbuf == 2 : # buffers sur 2 slices + cell_in_buf = "rf_inmux_buf_2" + cell_mid_buf = "rf_mid_buf_2" + cell_out_buf = "rf_out_buf_2" + + elif hbuf == 4 : # buffers sur 4 slices + cell_in_buf = "rf_inmux_buf_4" + cell_mid_buf = "rf_mid_buf_4" + cell_out_buf = "rf_out_buf_4" + + + sel0 = Signal ( "sel0", 1 ) + sel1 = Signal ( "sel1", 1 ) + xck = Signal ( "xck", 1 ) + nck = Signal ( "nck", 1 ) + + rbus = Signal ( "rbus", nbit ) + dinx = Signal ( "dinx", nbit ) + + write = [] + read = [] + for i in range ( nword ) : + write += [Signal ( "write%d" % i, 1 )] + read += [Signal ( "read%d" % i, 1 )] + + if type != 4 : + nandr = [] + for i in range ( nword >> 1 ) : + nandr += [Signal ( "nandr%d" % i, 1 )] + + cell_in_mem = "rf_inmux_mem" + cell_out_mem = "rf_out_mem" + + self.In = {} + self.Bit = {} + self.Out = {} + + for i in range ( nbit ) : + self.In[nbit-1-i] = Inst ( cell_in_mem + , "in%d" % ( nbit - 1 - i ) + , map = { 'datain0' : self._datain0[nbit - 1 - i] + , 'datain1' : self._datain1[nbit - 1 - i] + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'dinx' : dinx[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis = {} + + for j in range ( 0, nword, 2 ) : + + if j == 0 and type % 2 == 1 : cell_mid_mem = "rf_mid_mem_r0" + else : cell_mid_mem = "rf_mid_mem" + + self.BitBis[j] = Inst ( cell_mid_mem + , "bit%d_%d" % ( nbit - 1 - i, j ) + , map = { 'dinx' : dinx[nbit - 1 - i] + , 'write' : write[j] + , 'read' : read[j] + , 'rbus' : rbus[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + cell_mid_mem = "rf_mid_mem" + + self.BitBis[j+1] = Inst ( cell_mid_mem + , "bit%d_%d" % ( nbit - 1 - i, j + 1 ) + , map = { 'dinx' : dinx[nbit - 1 - i] + , 'write' : write[j + 1] + , 'read' : read[j + 1] + , 'rbus' : rbus[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Bit[nbit-1-i] = self.BitBis + + self.Out[nbit-1-i] = Inst ( cell_out_mem + , "out%d" % ( nbit - 1 - i ) + , map = { 'rbus' : rbus[nbit - 1 - i] + , 'xcks' : xck + , 'dataout' : self._dataout[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Placement de la ligne contenant les buffers ## + if type < 4 : + self.InBuf = Inst ( cell_in_buf + , "inbuf" + , map = { 'ck' : self._ck + , 'sel' : self._sel + , 'nck' : nck + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.InBuf = Inst ( cell_in_buf + , "inbuf" + , map = { 'ck' : self._ckok + , 'sel' : self._sel + , 'nck' : nck + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf = {} + + for j in range ( 0, nword, 2 ) : + self.Buf[j] = Inst ( cell_mid_buf + , "buf%d" % j + , map = { 'selr' : self._selr[j] + , 'selw' : self._selw[j] + , 'nck' : nck + , 'read' : read[j] + , 'write' : write[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + self.Buf[j+1] = Inst ( cell_mid_buf + , "buf%d" % ( j + 1 ) + , map = { 'selr' : self._selr[j + 1] + , 'selw' : self._selw[j + 1] + , 'nck' : nck + , 'read' : read[j + 1] + , 'write' : write[j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.OutBuf = Inst ( cell_out_buf + , "outbuf" + , map = { 'nck' : nck + , 'xcks' : xck + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Placement des lignes de bit au dessus des buffers ## + cell_in_mem = "rf_inmux_mem" + cell_out_mem = "rf_out_mem" + + for i in range ( nbitu ) : + self.In[nbitu-1-i] = Inst ( cell_in_mem + , "in%d" % ( nbitu - 1 - i ) + , map = { 'datain0' : datain0[nbitu - 1 - i] + , 'datain1' : datain1[nbitu - 1 - i] + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'dinx' : dinx[nbitu - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis = {} + + for j in range ( 0, nword, 2 ) : + if j == 0 and type % 2 == 1 : cell_mid_mem = "rf_mid_mem_r0" + else : cell_mid_mem = "rf_mid_mem" + + self.BitBis[j] = Inst ( cell_mid_mem + , "bit%d_%d" % ( nbitu - 1 - i, j ) + , map = { 'dinx' : dinx[nbitu - 1 - i] + , 'write' : write[j] + , 'read' : read[j] + , 'rbus' : rbus[nbitu - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + cell_mid_mem = "rf_mid_mem" + + self.BitBis[j+1] = Inst ( cell_mid_mem + , "bit%d_%d" % ( nbitu - 1 - i, j + 1 ) + , map = { 'dinx' : dinx[nbitu - 1 - i] + , 'write' : write[j + 1] + , 'read' : read[j + 1] + , 'rbus' : rbus[nbitu - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Bit[nbitu-1-i] = self.BitBis + + self.Out[nbitu-1-i] = Inst ( cell_out_mem + , "out%d" % ( nbitu - 1 - i ) + , sym1 + , map = { 'rbus' : rbus[nbitu - 1 - i] + , 'xcks' : xck + , 'dataout' : dataout[nbitu - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Placement des cellules du decodeur ## + if type == 2 or type == 3 : + nwen = Signal ( "nwen", 1 ) + nren = Signal ( "nren", 1 ) + + nadw0x = Signal ( "nadw0x", 1 ) + adw0x = Signal ( "adw0x", 1 ) + + adr0x = Signal ( "adr0x", 1 ) + nadr0x = Signal ( "nadr0x", 1 ) + + nandw = [] + for i in range ( nword >> 1 ) : + nandw += [Signal ( "nandw%d" % i, 1 )] + + + half = nword >> 1 + + # Premiere ligne decodeur ecriture + self.Adw0 = Inst ( "rf_dec_bufad0" + , "adw0" + , map = { 'i' : self._adw[0] + , 'nq' : nadw0x + , 'q' : adw0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelW = {} + + for j in range ( half ) : + self.SelW[2*j] = Inst ( "rf_dec_nor3" + , "selw%d" % ( 2 * j ) + , map = { 'i0' : nandw[j] + , 'i1' : adw0x + , 'i2' : nwen + , 'nq' : self._selw[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + self.SelW[2*j+1] = Inst ( "rf_dec_nor3" + , "selw%d" % ( 2 * j + 1 ) + , map = { 'i0' : nandw[j] + , 'i1' : nadw0x + , 'i2' : nwen + , 'nq' : self._selw[2 * j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + self.Wen = Inst ( "rf_dec_nbuf" + , "wen" + , map = { 'i' : self._wen + , 'nq' : nwen + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne decodeur ecriture + if adrange == 5 : # adresse sur 5 bits + + nadw1x = Signal ( "nadw1x", 1 ) + adw1x = Signal ( "adw1x", 1 ) + nadw2x = Signal ( "nadw2x", 1 ) + adw2x = Signal ( "adw2x", 1 ) + adw3x = Signal ( "adw3x", 1 ) + nadw3x = Signal ( "nadw3x", 1 ) + adw4x = Signal ( "adw4x", 1 ) + nadw4x = Signal ( "nadw4x", 1 ) + + adr1x = Signal ( "adr1x", 1 ) + nadr1x = Signal ( "nadr1x", 1 ) + adr2x = Signal ( "adr2x", 1 ) + nadr2x = Signal ( "nadr2x", 1 ) + adr3x = Signal ( "adr3x", 1 ) + nadr3x = Signal ( "nadr3x", 1 ) + adr4x = Signal ( "adr4x", 1 ) + nadr4x = Signal ( "nadr4x", 1 ) + + self.Adw12 = Inst ( "rf_dec_bufad2" + , "adw12" + , map = { 'i0' : self._adw[1] + , 'i1' : self._adw[2] + , 'nq0' : nadw1x + , 'q0' : adw1x + , 'nq1' : nadw2x + , 'q1' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand4W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadw3x + else : thisMap['i2'] = adw3x + if ( j >> 3 ) % 2 == 0 : thisMap['i3'] = nadw4x + else : thisMap['i3'] = adw4x + + self.Nand4W[j] = Inst ( "rf_dec_nand4" + , "nand4w%d" % j + , map = thisMap + ) + + self.Adw34 = Inst ( "rf_dec_bufad2" + , "adw34" + , map = { 'i0' : self._adw[3] + , 'i1' : self._adw[4] + , 'nq0' : nadw3x + , 'q0' : adw3x + , 'nq1' : nadw4x + , 'q1' : adw4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif adrange == 4 : # adresse sur 4 bits + + nadw1x = Signal ( "nadw1x", 1 ) + adw1x = Signal ( "adw1x", 1 ) + nadw2x = Signal ( "nadw2x", 1 ) + adw2x = Signal ( "adw2x", 1 ) + adw3x = Signal ( "adw3x", 1 ) + nadw3x = Signal ( "nadw3x", 1 ) + + adr1x = Signal ( "adr1x", 1 ) + nadr1x = Signal ( "nadr1x", 1 ) + adr2x = Signal ( "adr2x", 1 ) + nadr2x = Signal ( "nadr2x", 1 ) + adr3x = Signal ( "adr3x", 1 ) + nadr3x = Signal ( "nadr3x", 1 ) + + self.Adw12 = Inst ( "rf_dec_bufad2" + , "adw12" + , map = { 'i0' : self._adw[1] + , 'i1' : self._adw[2] + , 'nq0' : nadw1x + , 'q0' : adw1x + , 'nq1' : nadw2x + , 'q1' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand3W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadw3x + else : thisMap['i2'] = adw3x + + self.Nand3W[j] = Inst ( "rf_dec_nand3" + , "nand3w%d" % j + , map = thisMap + ) + + self.Adw3 = Inst ( "rf_dec_bufad1" + , "adw3" + , map = { 'i' : self._adw[3] + , 'nq' : nadw3x + , 'q' : adw3x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif adrange == 3 : # adresse sur 3 bits + + nadw1x = Signal ( "nadw1x", 1 ) + adw1x = Signal ( "adw1x", 1 ) + nadw2x = Signal ( "nadw2x", 1 ) + adw2x = Signal ( "adw2x", 1 ) + + adr1x = Signal ( "adr1x", 1 ) + nadr1x = Signal ( "nadr1x", 1 ) + adr2x = Signal ( "adr2x", 1 ) + nadr2x = Signal ( "nadr2x", 1 ) + + self. Adw1 = Inst ( "rf_dec_bufad1" + , "adw1" + , map = { 'i' : self._adw[1] + , 'nq' : nadw1x + , 'q' : adw1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand2W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + + self.Nand2W[j] = Inst ( "rf_dec_nand2" + , "nand2w%d" % j + , map = thisMap + ) + + self.Adw2 = Inst ( "rf_dec_bufad1" + , "adw2" + , map = { 'i' : self._adw[2] + , 'nq' : nadw2x + , 'q' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Premiere ligne decodeur lecture + self.Adr0 = Inst ( "rf_dec_bufad0" + , "adr0" + , map = { 'i' : self._adr[0] + , 'nq' : nadr0x + , 'q' : adr0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelR = {} + + for j in range ( half ) : + if j == 0 : + self.SelR[2*j] = Inst ( "rf_dec_nao3" + , "selr%d" % ( 2 * j ) + , map = { 'i0' : nandr[j] + , 'i1' : adr0x + , 'i2' : self._ren + , 'nq' : self._selr[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.SelR[2*j] = Inst ( 'rf_dec_nor3' + , 'selr%d' % ( 2 * j ) + , map = { 'i0' : nandr[j] + , 'i1' : adr0x + , 'i2' : nren + , 'nq' : self._selr[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelR[2*j+1] = Inst ( "rf_dec_nor3" + , 'selr%d' % ( 2 * j + 1 ) + , map = { 'i0' : nandr[j] + , 'i1' : nadr0x + , 'i2' : nren + , 'nq' : self._selr[2 * j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Ren = Inst ( 'rf_dec_nbuf' + , 'ren' + , map = { 'i' : self._ren + , 'nq' : nren + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne decodeur lecture + if adrange == 5 : # adresse sur 5 bits + self.Adr12 = Inst ( 'rf_dec_bufad2' + , 'adr12' + , map = { 'i0' : self._adr[1] + , 'i1' : self._adr[2] + , 'nq0' : nadr1x + , 'q0' : adr1x + , 'nq1' : nadr2x + , 'q1' : adr2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand4R = {} + + for j in range ( half ) : + thisMap = { 'nq': nandr[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadr1x + else : thisMap['i0'] = adr1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadr2x + else : thisMap['i1'] = adr2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadr3x + else : thisMap['i2'] = adr3x + if ( j >> 3 ) % 2 == 0 : thisMap['i3'] = nadr4x + else : thisMap['i3'] = adr4x + + self.Nand4R[j] = Inst ( 'rf_dec_nand4' + , 'nand4r%d' % j + , map = thisMap + ) + + self.Adr34 = Inst ( 'rf_dec_bufad2' + , 'adr34' + , map = { 'i0' : self._adr[3] + , 'i1' : self._adr[4] + , 'nq0' : nadr3x + , 'q0' : adr3x + , 'nq1' : nadr4x + , 'q1' : adr4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 4 : # adresse sur 4 bits + self.Adr12 = Inst ( 'rf_dec_bufad2' + , 'adr12' + , map = { 'i0' : self._adr[1] + , 'i1' : self._adr[2] + , 'nq0' : nadr1x + , 'q0' : adr1x + , 'nq1' : nadr2x + , 'q1' : adr2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand3R = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandr[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadr1x + else : thisMap['i0'] = adr1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadr2x + else : thisMap['i1'] = adr2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadr3x + else : thisMap['i2'] = adr3x + + self.Nand3R[j] = Inst ( 'rf_dec_nand3' + , 'nand3r%d' % j + , map = thisMap + ) + + self.Adr3 = Inst ( 'rf_dec_bufad1' + , 'adr3' + , map = { 'i' : self._adr[3] + , 'nq' : nadr3x + , 'q' : adr3x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 3 : # adresse sur 3 bits + self.Adr1 = Inst ( 'rf_dec_bufad1' + , 'adr1' + , map = { 'i' : self._adr[1] + , 'nq' : nadr1x + , 'q' : adr1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand2R = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandr[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadr1x + else : thisMap['i0'] = adr1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadr2x + else : thisMap['i1'] = adr2x + + self.Nand2R[j] = Inst ( 'rf_dec_nand2' + , 'nand2r%d' % j + , map = thisMap + ) + + self.Adr2 = Inst ( 'rf_dec_bufad1' + , 'adr2' + , map = { 'i' : self._adr[2] + , 'nq' : nadr2x + , 'q' : adr2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + +# end if type == 2 or type == 3 + + ## Placement des cellules du controleur FIFO ## + if type == 4 : + ckm = Signal ( "ckm", 1 ) + cks = Signal ( "cks", 1 ) + nreset = Signal ( "nreset", 1 ) + nwval = Signal ( "nwval", 1 ) + pwnop = Signal ( "pwnop", 1 ) + pwinc = Signal ( "pwinc", 1 ) + prnop = Signal ( "prnop", 1 ) + princ = Signal ( "princ", 1 ) + xreset = Signal ( "xreset", 1 ) + xckm = Signal ( "xckm", 1 ) + xcks = Signal ( "xcks", 1 ) + nr = Signal ( "nr", 1 ) + nw = Signal ( "nw", 1 ) + full = Signal ( "full", 1 ) + fullnext = Signal ( "fullnext", 1 ) + empty = Signal ( "empty", 1 ) + emptynext = Signal ( "emptynext", 1 ) + nrval = Signal ( "nrval", 1 ) + + orfull = [] + orempty = [] + for i in range ( nword >> 1 ) : + orfull += [Signal ( "orfull%d" % i, 1 )] + orempty += [Signal ( "orempty%d" % i, 1 )] + + + half = nword >> 1 + + # Premiere ligne + self.Inspwnop = Inst ( 'rf_fifo_nop' + , 'inspwnop' + , map = { 'ckm' : ckm + , 'nreset' : nreset + , 'rw' : self._w + , 'rwok' : self._wok + , 'nval' : nwval + , 'nop' : pwnop + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Pw = {} + + self.Pw[0] = Inst ( 'rf_fifo_ptset' + , 'pw0' + , map = { 'nop' : pwnop + , 'inc' : pwinc + , 'cks' : xcks + , 'nreset' : nreset + , 'ptm1' : self._selw[nword - 1] + , 'pt' : self._selw[0] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for j in range ( 1, half, 1 ) : + self.Pw[j] = Inst ( 'rf_fifo_ptreset' + , 'pw%d' % j + , map = { 'nop' : pwnop + , 'inc' : pwinc + , 'cks' : xcks + , 'reset' : xreset + , 'ptm1' : self._selw[j - 1] + , 'pt' : self._selw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.FifoBuf = Inst ( 'rf_fifo_buf' + , 'fifo_buf' + , map = { 'cks' : cks + , 'ckm' : ckm + , 'r' : self._r + , 'w' : self._w + , 'reset' : self._reset + , 'xcks' : xcks + , 'xckm' : xckm + , 'nr' : nr + , 'nw' : nw + , 'xreset' : xreset + , 'nreset' : nreset + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne + self.Inspwinc = Inst ( 'rf_fifo_inc' + , 'inspwinc' + , map = { 'ckm' : ckm + , 'nreset' : nreset + , 'nval' : nwval + , 'inc' : pwinc + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for j in range ( half ) : + self.Pw[nword-1-j] = Inst ( 'rf_fifo_ptreset' + , 'pw%d' % ( nword - 1 - j ) + , map = { 'nop' : pwnop + , 'inc' : pwinc + , 'cks' : xcks + , 'reset' : xreset + , 'ptm1' : self._selw[nword - 2 - j] + , 'pt' : self._selw[nword - 1 - j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Troisieme ligne + self.InsWok = Inst ( 'rf_fifo_ok' + , 'inswok' + , map = { 'rw' : self._w + , 'ripple' : orfull[0] + , 'nrw' : nr + , 'prev' : full + , 'nextval' : fullnext + , 'ok' : self._wok + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsOrFull = {} + + for j in range ( half - 1 ) : + self.InsOrFull[j] = Inst ( 'rf_fifo_orand5' + , 'insorfull%d' % j + , map = { 'a0' : self._selw[j] + , 'b0' : self._selr[j + 1] + , 'a1' : self._selw[nword - 1 - j] + , 'b1' : self._selr[( nword - j ) % nword] + , 'ripplein' : orfull[j + 1] + , 'rippleout' : orfull[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsOrFull[half-1] = Inst ( 'rf_fifo_orand4' + , 'insorfull%d' % ( half - 1 ) + , map = { 'a0' : self._selw[half - 1] + , 'b0' : self._selr[half] + , 'a1' : self._selw[half] + , 'b1' : self._selr[half + 1] + , 'rippleout' : orfull[half - 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsEmpty = Inst ( 'rf_fifo_empty' + , 'insempty' + , map = { 'ckm' : xckm + , 'nreset' : nreset + , 'emptynext' : emptynext + , 'cks' : xcks + , 'empty' : empty + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Quatrieme ligne + self.InsFull = Inst ( 'rf_fifo_full' + , 'insfull' + , map = { 'ckm' : xckm + , 'reset' : xreset + , 'fullnext' : fullnext + , 'cks' : xcks + , 'full' : full + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsOrEmpty = {} + + self.InsOrEmpty[0] = Inst ( 'rf_fifo_orand4' + , 'insorempty0' + , map = { 'a0' : self._selr[0] + , 'b0' : self._selw[1] + , 'a1' : self._selr[nword - 1] + , 'b1' : self._selw[0] + , 'rippleout' : orempty[0] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for j in range ( 1, half ) : + self.InsOrEmpty[j] = Inst ( 'rf_fifo_orand5' + , 'insorempty%d' % j + , map = { 'a0' : self._selr[j] + , 'b0' : self._selw[j + 1] + , 'a1' : self._selr[nword - 1 - j] + , 'b1' : self._selw[nword - j] + , 'ripplein' : orempty[j - 1] + , 'rippleout' : orempty[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsRok = Inst ( 'rf_fifo_ok' + , 'insrok' + , map = { 'rw' : self._r + , 'ripple' : orempty[half - 1] + , 'nrw' : nw + , 'prev' : empty + , 'nextval' : emptynext + , 'ok' : self._rok + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Cinquieme ligne + self.InsClock = Inst ( 'rf_fifo_clock' + , 'insclock' + , map = { 'ck' : self._ck + , 'wok' : self._wok + , 'cks' : cks + , 'ckm' : ckm + , 'ckok' : self._ckok + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Pr = {} + + self.Pr[0] = Inst ( 'rf_fifo_ptset' + , 'pr0' + , map = { 'nop' : prnop + , 'inc' : princ + , 'cks' : xcks + , 'nreset' : nreset + , 'ptm1' : self._selr[nword - 1] + , 'pt' : self._selr[0] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for j in range ( 1, half ) : + self.Pr[j] = Inst ( 'rf_fifo_ptreset' + , 'pr%d' % j + , map = { 'nop' : prnop + , 'inc' : princ + , 'cks' : xcks + , 'reset' : xreset + , 'ptm1' : self._selr[j - 1] + , 'pt' : self._selr[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsPrNop = Inst ( 'rf_fifo_nop' + , 'insprnop' + , map = { 'ckm' : ckm + , 'nreset' : nreset + , 'rw' : self._r + , 'rwok' : self._rok + , 'nval' : nrval + , 'nop' : prnop + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Sixieme ligne + self.Pr[nword-1] = Inst ( 'rf_fifo_ptreset' + , 'pr%d' % ( nword - 1 ) + , map = { 'nop' : prnop + , 'inc' : princ + , 'cks' : xcks + , 'reset' : xreset + , 'ptm1' : self._selr[nword - 2] + , 'pt' : self._selr[nword - 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for j in range ( 1, half ) : + self.Pr[nword-1-j] = Inst ( 'rf_fifo_ptreset' + , 'pr%d' % ( nword - 1 - j ) + , map = { 'nop' : prnop + , 'inc' : princ + , 'cks' : xcks + , 'reset' : xreset + , 'ptm1' : self._selr[nword - 2 - j] + , 'pt' : self._selr[nword - 1 - j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.InsPrinc= Inst ( 'rf_fifo_inc' + , 'insprinc' + , map = { 'ckm' : ckm + , 'nreset' : nreset + , 'nval' : nrval + , 'inc' : princ + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) +# end if type == 4 + + + ## Layout ## + ############ + def Layout ( self, nbit, nword, type ) : + + hbuf = 2 # hauteur des buffers (2 ou 4 slices) : non utilise + + HCELL = 50 + + ## Placement des lignes de bit en dessous des buffers ## + bottom = 0 + + sym1 = NOSYM + sym2 = SYM_X + + for i in range ( nbit ) : + if i % 2 : # lignes paires + sym1 = NOSYM + sym2 = SYM_X + else : # lignes impaires + sym1 = SYM_Y + sym2 = SYMXY + + Place ( self.In[nbit - 1 - i], sym1, XY ( 0, bottom + ( nbit - 1 - i ) * HCELL ) ) + + for j in range ( 0, nword, 2 ) : + PlaceRight ( self.Bit[nbit - 1 - i][j], sym1 ) + PlaceRight ( self.Bit[nbit - 1 - i][j + 1], sym2 ) + + PlaceRight ( self.Out[nbit - 1 - i] , sym1 ) + + ## Placement de la ligne contenant les buffers ## + bottom = nbit * HCELL + + Place ( self.InBuf, NOSYM, XY ( 0, bottom ) ) + + for j in range ( 0, nword, 2 ) : + PlaceRight ( self.Buf[j], NOSYM ) + PlaceRight ( self.Buf[j + 1], SYM_X ) + + PlaceRight ( self.OutBuf, NOSYM ) + + ## Placement des lignes de bit au dessus des buffers ## + bottom = ( nbit + hbuf ) * HCELL + + for i in range ( nbitu ) : + if i % 2 : # lignes impaires + sym1 = SYM_Y + sym2 = SYMXY + else : # lignes paires + sym1 = NOSYM + sym2 = SYM_X + + Place ( self.In[nbitu - 1 - i], sym1, XY ( 0, bottom + i * HCELL ) ) + + for j in range ( 0, nword, 2 ) : + PlaceRight ( self.Bit[nbitu - 1 - i][j], sym1 ) + PlaceRight ( self.Bit[nbitu - 1 - i][j + 1], sym2 ) + + PlaceRight ( self.Out[nbitu - 1 - i], sym1 ) + + ## Placement des cellules du decodeur ## + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur ecriture + bottom = ( nbit + nbitu + hbuf + 2 ) * HCELL + + Place ( self.Adw0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half ) : + PlaceRight ( self.SelW[2 * j], SYM_X ) + PlaceRight ( self.SelW[2 * j + 1], NOSYM ) + + PlaceRight ( self.Wen, NOSYM ) + + # Deuxieme ligne decodeur ecriture + bottom = ( nbit + nbitu + hbuf + 3 ) * HCELL + + if adrange == 5 : # adresse sur 5 bits + Place ( self.Adw12, SYM_Y, XY ( 0, bottom ) ) + + for j in range ( half ) : PlaceRight ( self.Nand4W[j], SYM_Y ) + + PlaceRight ( self.Adw34, SYMXY ) + + if adrange == 4 : # adresse sur 4 bits + Place ( self.Adw12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand3W[j], SYM_Y ) + PlaceRight ( self.Adw3, SYMXY ) + + if adrange == 3 : # adresse sur 3 bits + Place ( self.Adw1, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand2W[j], SYM_Y ) + PlaceRight ( self.Adw2, SYMXY ) + + # Premiere ligne decodeur lecture + bottom = ( nbit + nbitu + hbuf ) * HCELL + + Place ( self.Adr0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half ) : + if j == 0 : PlaceRight ( self.SelR[2 * j], NOSYM ) + else : PlaceRight ( self.SelR[2 * j], NOSYM ) + PlaceRight ( self.SelR[2 * j + 1], SYM_X ) + + PlaceRight ( self.Ren, NOSYM ) + + # Deuxieme ligne decodeur lecture + bottom = ( nbit + nbitu + hbuf + 1 ) * HCELL + + if adrange == 5 : # adresse sur 5 bits + Place ( self.Adr12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand4R[j], SYM_Y ) + PlaceRight ( self.Adr34, SYMXY ) + + if adrange == 4 : # adresse sur 4 bits + Place ( self.Adr12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand3R[j], SYM_Y ) + PlaceRight ( self.Adr3, SYMXY ) + + if adrange == 3 : # adresse sur 3 bits + Place ( self.Adr1, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand2R[j], SYM_Y ) + PlaceRight ( self.Adr2, SYMXY ) + + ## Placement des cellules du controleur FIFO ## + if type == 4 : + half = nword >> 1 + + # Premiere ligne + bottom = ( nbit + nbitu + hbuf ) * HCELL + Place ( self.Inspwnop, SYM_X, XY ( 0, bottom ) ) + PlaceRight ( self.Pw[0], NOSYM ) + + for j in range ( 1, half, 1 ) : PlaceRight ( self.Pw[j], NOSYM ) + + PlaceRight ( self.FifoBuf, SYM_X ) + + # Deuxieme ligne + bottom = ( nbit + nbitu + hbuf + 1 ) * HCELL + + Place ( self.Inspwinc, SYMXY, XY ( 0, bottom ) ) + + for j in range ( half ) : PlaceRight ( self.Pw[nword - 1 - j], SYMXY ) + + # Troisieme ligne + bottom = ( nbit + nbitu + hbuf + 2 ) * HCELL + + Place ( self.InsWok, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half - 1 ) : PlaceRight ( self.InsOrFull[j], NOSYM ) + + PlaceRight ( self.InsOrFull[half - 1], NOSYM ) + PlaceRight ( self.InsEmpty, SYM_X ) + + # Quatrieme ligne + bottom = ( nbit + nbitu + hbuf + 3 ) * HCELL + + Place ( self.InsFull, SYM_Y, XY ( 0, bottom ) ) + PlaceRight ( self.InsOrEmpty[0], SYMXY ) + + for j in range ( 1, half ) : PlaceRight ( self.InsOrEmpty[j], SYMXY ) + + PlaceRight ( self.InsRok, SYMXY ) + + # Cinquieme ligne + bottom = ( nbit + nbitu + hbuf + 4 ) * HCELL + + Place ( self.InsClock, NOSYM, XY ( 0, bottom ) ) + PlaceRight ( self.Pr[0], NOSYM ) + + for j in range ( 1, half ) : PlaceRight ( self.Pr[j], NOSYM ) + + PlaceRight ( self.InsPrNop, NOSYM ) + + # Sixieme ligne + bottom = ( nbit + nbitu + hbuf + 5 ) * HCELL + + Place ( self.Pr[nword - 1] , SYMXY, XY ( 50, bottom ) ) + + for j in range ( 1, half ) : PlaceRight ( self.Pr[nword - 1 - j], SYM_Y ) + + PlaceRight ( self.InsPrinc, SYM_Y ) + + + ## VBE ## + ######### + def Vbe ( self ) : + print "rf1 behavior not implemented" + + + +#################### +##### DpgenRf1 ##### +#################### +class DpgenRf1 ( top_rf1 ) : + + def Interface ( self ) : + top_rf1.Interface ( self, self._param['nbit'], self._param['nword'], 0 ) + + def Netlist ( self ) : + top_rf1.Netlist ( self, self._param['nbit'], self._param['nword'], 0 ) + + def Layout ( self ) : + top_rf1.Layout ( self, self._param['nbit'], self._param['nword'], 0 ) + + +###################### +##### DpgenRf1r0 ##### +###################### +class DpgenRf1r0 ( top_rf1 ) : + + def Interface ( self ) : + top_rf1.Interface ( self, self._param['nbit'], self._param['nword'], 1 ) + + def Netlist ( self ) : + top_rf1.Netlist ( self, self._param['nbit'], self._param['nword'], 1 ) + + def Layout ( self ) : + top_rf1.Layout ( self, self._param['nbit'], self._param['nword'], 1 ) + + +##################### +##### DpgenRf1d ##### +##################### +class DpgenRf1d ( top_rf1 ) : + + def Interface ( self ) : + top_rf1.Interface ( self, self._param['nbit'], self._param['nword'], 2 ) + + def Netlist ( self ) : + top_rf1.Netlist ( self, self._param['nbit'], self._param['nword'], 2 ) + + def Layout ( self ) : + top_rf1.Layout ( self, self._param['nbit'], self._param['nword'], 2 ) + + +####################### +##### DpgenRf1dr0 ##### +####################### +class DpgenRf1dr0 ( top_rf1 ) : + + def Interface ( self ) : + top_rf1.Interface ( self, self._param['nbit'], self._param['nword'], 3 ) + + def Netlist ( self ) : + top_rf1.Netlist ( self, self._param['nbit'], self._param['nword'], 3 ) + + def Layout ( self ) : + top_rf1.Layout ( self, self._param['nbit'], self._param['nword'], 3 ) + + +##################### +##### DpgenFifo ##### +##################### +class DpgenFifo ( top_rf1 ) : + + def Interface ( self ) : + top_rf1.Interface ( self, self._param['nbit'], self._param['nword'], 4 ) + + def Netlist ( self ) : + top_rf1.Netlist ( self, self._param['nbit'], self._param['nword'], 4 ) + + def Layout ( self ) : + top_rf1.Layout ( self, self._param['nbit'], self._param['nword'], 4 ) diff --git a/stratus1/src/dpgen/dpgen_RF2.py b/stratus1/src/dpgen/dpgen_RF2.py new file mode 100644 index 00000000..10d77216 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_RF2.py @@ -0,0 +1,1145 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_RF2.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +# Banc de registre triple acces : deux lectures, une ecriture +# Le programme genere une net-list et un placement optimise. +# +# La largeur est egale a (nmot * 35) + 150 +# La hauteur est egale a (nbit + 8) * 50 +# +# Pour la partie "donnees", on utilise les cellules suivantes : +# colonne d'entree +# - rf2_inmux_mem +# - rf2_inmux_buf +# colonne centrale +# - rf2_mid_mem +# - rf2_mid_mem_r0 +# - rf2_mid_buf +# colonne de sortie +# - rf2_out_mem +# - rf2_out_buf +# +# Pour le decodeur, on utilise les cellules suivantes : +# - rf2_dec_bufad0 +# - rf2_dec_bufad1_l +# - rf2_dec_bufad2_l +# - rf2_dec_bufad1_r +# - rf2_dec_bufad2_r +# - rf2_dec_nbuf +# - rf2_dec_nor3 +# - rf2_dec_nao3 +# - rf2_dec_nand2 +# - rf2_dec_nand3 +# - rf2_dec_nand4 + + +#---------------------------------------------------------------- +# DEBUT PROGRAMME PRINCIPAL +#---------------------------------------------------------------- +# aFunction : le type : +# DPGEN_RF2 (sans decodeur) +# DPGEN_RF2R0 (sans decodeur, avec R0 colle a 0) +# DPGEN_RF2D (avec decodeur) +# DPGEN_RF2DR0 (avec decodeur, avec R0 colle a 0) +# +# aAL : liste des parametres : +# Model_name : nom de modele. +# flags : indexation des connecteurs. +# nbit : nombre de bits (largeur du bus). +# nmot : nombre de mots. +# - le nombre de mots doit etre pair, 6 =< nmot =< 32 +# - le nombre de bits doit etre pair, 2 =< nbit =< 64 +#---------------------------------------------------------------- + + + +################################# +##### Classe mere : top_rf2 ##### +################################# +class top_rf2 ( Model ) : + + ## Interface ## + ############### + def Interface ( self, nbit, nword, type ) : + global adrange + + if nword % 2 == 1 or nword > 32 or nword < 4 : + print "Error in DpgenRf2 : the word number must be even, larger than 4 and no larger than 32\n" + sys.exit ( 1 ) + + if nword == 4 and ( type == 2 or type == 3 ) : + print "Error in DpgenRf2 : the word number must be larger than 4\n" + sys.exit ( 1 ) + + if nbit % 2 == 1 or nbit > 64 or nbit < 2 : + print "Error in DpgenRf2 : the bit number must be even and no larger than 64\n" + sys.exit ( 1 ) + + adrange = 2 + if nword > 4 : adrange = 3 + if nword > 8 : adrange = 4 + if nword > 16 : adrange = 5 + + if type < 2 : # c'est un banc de registres sans decodeur + self._ck = SignalIn ( "ck", 1 ) + self._sel = SignalIn ( "sel", 1 ) + + self._sela = SignalIn ( "sela", nword ) + self._selb = SignalIn ( "selb", nword ) + self._selw = SignalIn ( "selw", nword ) + self._datain0 = SignalIn ( "datain0", nbit ) + self._datain1 = SignalIn ( "datain1", nbit ) + + self._dataouta = SignalOut ( "dataouta", nbit ) + self._dataoutb = SignalOut ( "dataoutb", nbit ) + + else : # c'est un banc de registres avec decodeur + self._ck = SignalIn ( "ck", 1 ) + self._sel = SignalIn ( "sel", 1 ) + self._wen = SignalIn ( "wen", 1 ) + self._rena = SignalIn ( "rena", 1 ) + self._renb = SignalIn ( "renb", 1 ) + + self._adra = SignalIn ( "adra", adrange ) + self._adrb = SignalIn ( "adrb", adrange ) + self._adw = SignalIn ( "adw" , adrange ) + + self._datain0 = SignalIn ( "datain0", nbit ) + self._datain1 = SignalIn ( "datain1", nbit ) + + self._dataouta = SignalOut ( "dataouta", nbit ) + self._dataoutb = SignalOut ( "dataoutb", nbit ) + + self._selw = Signal ( "selw", nword ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self, nbit, nword, type ) : + global adrange + + # Signaux + sel0 = Signal ( "sel0", 1 ) + sel1 = Signal ( "sel1", 1 ) + xcks = Signal ( "xcks", 1 ) + nck = Signal ( "nck", 1 ) + nwen = Signal ( "nwen", 1 ) + nrena = Signal ( "nrena", 1 ) + nrenb = Signal ( "nrenb", 1 ) + + adw0x = Signal ( "adw0x", 1 ) + nadw0x = Signal ( "nadw0x", 1 ) + adw1x = Signal ( "adw1x", 1 ) + nadw1x = Signal ( "nadw1x", 1 ) + adw2x = Signal ( "adw2x", 1 ) + nadw2x = Signal ( "nadw2x", 1 ) + adw3x = Signal ( "adw3x", 1 ) + nadw3x = Signal ( "nadw3x", 1 ) + adw4x = Signal ( "adw4x", 1 ) + nadw4x = Signal ( "nadw4x", 1 ) + + adra0x = Signal ( "adra0x", 1 ) + nadra0x = Signal ( "nadra0x", 1 ) + adra1x = Signal ( "adra1x", 1 ) + nadra1x = Signal ( "nadra1x", 1 ) + adra2x = Signal ( "adra2x", 1 ) + nadra2x = Signal ( "nadra2x", 1 ) + adra3x = Signal ( "adra3x", 1 ) + nadra3x = Signal ( "nadra3x", 1 ) + adra4x = Signal ( "adra4x", 1 ) + nadra4x = Signal ( "nadra4x", 1 ) + + adrb0x = Signal ( "adrb0x", 1 ) + nadrb0x = Signal ( "nadrb0x", 1 ) + adrb1x = Signal ( "adrb1x", 1 ) + nadrb1x = Signal ( "nadrb1x", 1 ) + adrb2x = Signal ( "adrb2x", 1 ) + nadrb2x = Signal ( "nadrb2x", 1 ) + adrb3x = Signal ( "adrb3x", 1 ) + nadrb3x = Signal ( "nadrb3x", 1 ) + adrb4x = Signal ( "adrb4x", 1 ) + nadrb4x = Signal ( "nadrb4x", 1 ) + + dinx = Signal ( "dinx", nbit ) + busa = Signal ( "busa", nbit ) + busb = Signal ( "busb", nbit ) + + if type >= 2 : + self._sela = Signal ( "sela", nword ) + self._selb = Signal ( "selb", nword ) + + write = [] + reada = [] + readb = [] + for i in range ( nword ) : + write += [Signal ( "write%d" % i, 1 )] + reada += [Signal ( "reada%d" % i, 1 )] + readb += [Signal ( "readb%d" % i, 1 )] + + nandw = [] + nandra = [] + nandrb = [] + for i in range ( nword >> 1 ) : + nandw += [Signal ( "nandw%d" % i, 1 )] + nandra += [Signal ( "nandra%d" % i, 1 )] + nandrb += [Signal ( "nandrb%d" % i, 1 )] + + + # placement des lignes de bit en dessous des buffers + self.In = {} + self.Bit = {} + self.Out = {} + + for i in range ( nbit ) : + self.In[nbit-1-i] = Inst ( 'rf2_inmux_mem' + , 'in%d' % ( nbit - 1 - i ) + , map = { 'datain0' : self._datain0[nbit - 1 - i] + , 'datain1' : self._datain1[nbit - 1 - i] + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'dinx' : dinx[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis = {} + + for j in range ( 0, nword, 2 ) : + if j == 0 and ( type == 1 or type == 3 ) : + self.BitBis[j] = Inst ( 'rf2_mid_mem_r0' + , 'bit%d_%d' % ( nbit - 1 - i , j ) + , map = { 'dinx' : dinx[nbit - 1 - i] + , 'write' : write[j] + , 'reada' : reada[j] + , 'readb' : readb[j] + , 'busa' : busa[nbit - 1 - i] + , 'busb' : busb[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.BitBis[j] = Inst ( 'rf2_mid_mem' + , 'bit%d_%d' % ( nbit - 1 - i, j ) + , map = { 'dinx' : dinx[nbit - 1 - i] + , 'write' : write[j] + , 'reada' : reada[j] + , 'readb' : readb[j] + , 'busa' : busa[nbit - 1 - i] + , 'busb' : busb[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.BitBis[j+1] = Inst ( 'rf2_mid_mem' + , 'bit%d_%d' % ( nbit - 1 - i, j + 1 ) + , map = { 'dinx' : dinx[nbit - 1 - i] + , 'write' : write[j + 1] + , 'reada' : reada[j + 1] + , 'readb' : readb[j + 1] + , 'busa' : busa[nbit - 1 - i] + , 'busb' : busb[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Bit[nbit-1-i] = self.BitBis + + self.Out[nbit-1-i] = Inst ( 'rf2_out_mem' + , 'out%d' % ( nbit - 1 - i ) + , map = { 'busa' : busa[nbit - 1 - i] + , 'busb' : busb[nbit - 1 - i] + , 'xcks' : xcks + , 'dataouta' : self._dataouta[nbit - 1 - i] + , 'dataoutb' : self._dataoutb[nbit - 1 - i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # placement de la ligne contenant les buffers + self.InBuf = Inst ( 'rf2_inmux_buf' + , 'inbuf' + , map = { 'sel' : self._sel + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf = {} + + for j in range ( 0, nword, 2 ) : + self.Buf[j] = Inst ( 'rf2_mid_buf' + , 'buf%d' % j + , map = { 'selra' : self._sela[j] + , 'selrb' : self._selb[j] + , 'selw' : self._selw[j] + , 'nck' : nck + , 'reada' : reada[j] + , 'readb' : readb[j] + , 'write' : write[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Buf[j+1] = Inst ( 'rf2_mid_buf' + , 'buf%d' % ( j + 1 ) + , map = { 'selra' : self._sela[j + 1] + , 'selrb' : self._selb[j + 1] + , 'selw' : self._selw[j + 1] + , 'nck' : nck + , 'reada' : reada[j + 1] + , 'readb' : readb[j + 1] + , 'write' : write[j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.OutBuf = Inst ( 'rf2_out_buf' + , 'outbuf' + , map = { 'ck' : self._ck + , 'nck' : nck + , 'xcks' : xcks + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # placement des cellules du decodeur ecriture + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur ecriture + self.Adw0 = Inst ( 'rf2_dec_bufad0' + , 'adw0' + , map = { 'i' : self._adw[0] + , 'nq' : nadw0x + , 'q' : adw0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelW = {} + + for j in range ( half ) : + self.SelW[2*j] = Inst ( 'rf2_dec_nor3' + , 'selw%d' % ( 2 * j ) + , map = { 'i0' : nandw[j] + , 'i1' : adw0x + , 'i2' : nwen + , 'nq' : self._selw[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelW[2*j+1] = Inst ( 'rf2_dec_nor3' + , 'selw%d' % ( 2 * j + 1 ) + , map = { 'i0' : nandw[j] + , 'i1' : nadw0x + , 'i2' : nwen + , 'nq' : self._selw[2 * j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Wen = Inst ( 'rf2_dec_nbuf' + , 'wen' + , map = { 'i' : self._wen + , 'nq' : nwen + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne decodeur ecriture + if adrange == 5 : # adresse sur 5 bits + self.Adw12 = Inst ( 'rf2_dec_bufad2_l' + , 'adw12' + , map = { 'i0' : self._adw[1] + , 'i1' : self._adw[2] + , 'nq0' : nadw1x + , 'q0' : adw1x + , 'nq1' : nadw2x + , 'q1' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand4W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadw3x + else : thisMap['i2'] = adw3x + if ( j >> 3 ) % 2 == 0 : thisMap['i3'] = nadw4x + else : thisMap['i3'] = adw4x + + self.Nand4W[j] = Inst ( 'rf2_dec_nand4' + , 'nand4w%d' % j + , map = thisMap + ) + + self.Adw34 = Inst ( 'rf2_dec_bufad2_l' + , 'adw34' + , map = { 'i0' : self._adw[3] + , 'i1' : self._adw[4] + , 'nq0' : nadw3x + , 'q0' : adw3x + , 'nq1' : nadw4x + , 'q1' : adw4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 4 : # adresse sur 4 bits + self.Adw12 = Inst ( 'rf2_dec_bufad2_l' + , 'adw12' + , map = { 'i0' : self._adw[1] + , 'i1' : self._adw[2] + , 'nq0' : nadw1x + , 'q0' : adw1x + , 'nq1' : nadw2x + , 'q1' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand3W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadw3x + else : thisMap['i2'] = adw3x + + self.Nand3W[j] = Inst ( 'rf2_dec_nand3' + , 'nand3w%d' % j + , map = thisMap + ) + + self.Adw3 = Inst ( 'rf2_dec_bufad1_r' + , 'adw3' + , map = { 'i' : self._adw[3] + , 'nq' : nadw3x + , 'q' : adw3x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 3 : # adresse sur 3 bits + self.Adw1 = Inst ( 'rf2_dec_bufad1_l' + , 'adw1' + , map = { 'i' : self._adw[1] + , 'nq' : nadw1x + , 'q' : adw1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand2W = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandw[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadw1x + else : thisMap['i0'] = adw1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadw2x + else : thisMap['i1'] = adw2x + + self.Nand2W[j] = Inst ( 'rf2_dec_nand2' + , 'nand2w%d' % j + , map = thisMap + ) + + self.Adw2 = Inst ( 'rf2_dec_bufad1_r' + , 'adw2' + , map = { 'i' : self._adw[2] + , 'nq' : nadw2x + , 'q' : adw2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # placement des cellules du decodeur lecture A + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur lecture A + self.Adra0 = Inst ( 'rf2_dec_bufad0' + , 'adra0' + , map = { 'i' : self._adra[0] + , 'nq' : nadra0x + , 'q' : adra0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelRa = {} + + for j in range ( half ) : + if j == 0 : + self.SelRa[2*j] = Inst ( 'rf2_dec_nao3' + , 'sela%d' % ( 2 * j ) + , map = { 'i0' : nandra[j] + , 'i1' : adra0x + , 'i2' : self._rena + , 'nq' : self._sela[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.SelRa[2*j] = Inst ( 'rf2_dec_nor3' + , 'sela%d' % ( 2 * j ) + , map = { 'i0' : nandra[j] + , 'i1' : adra0x + , 'i2' : nrena + , 'nq' : self._sela[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelRa[2*j+1] = Inst ( 'rf2_dec_nor3' + , 'sela%d' % ( 2 * j + 1 ) + , map = { 'i0' : nandra[j] + , 'i1' : nadra0x + , 'i2' : nrena + , 'nq' : self._sela[2 * j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.RenA = Inst ( 'rf2_dec_nbuf' + , 'rena' + , map = { 'i' : self._rena + , 'nq' : nrena + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne decodeur lecture A + if adrange == 5 : # adresse sur 5 bits + self.Adra12 = Inst ( 'rf2_dec_bufad2_l' + , 'adra12' + , map = { 'i0' : self._adra[1] + , 'i1' : self._adra[2] + , 'nq0' : nadra1x + , 'q0' : adra1x + , 'nq1' : nadra2x + , 'q1' : adra2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand4Ra = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandra[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadra1x + else : thisMap['i0'] = adra1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadra2x + else : thisMap['i1'] = adra2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadra3x + else : thisMap['i2'] = adra3x + if ( j >> 3 ) % 2 == 0 : thisMap['i3'] = nadra4x + else : thisMap['i3'] = adra4x + + self.Nand4Ra[j] = Inst ( 'rf2_dec_nand4' + , 'nand4ra%d' % j + , map = thisMap + ) + + self.Adra34 = Inst ( 'rf2_dec_bufad2_r' + , 'adra34' + , map = { 'i0' : self._adra[3] + , 'i1' : self._adra[4] + , 'nq0' : nadra3x + , 'q0' : adra3x + , 'nq1' : nadra4x + , 'q1' : adra4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 4 : # adresse sur 4 bits + self.Adra12 = Inst ( 'rf2_dec_bufad2_l' + , 'adra12' + , map = { 'i0' : self._adra[1] + , 'i1' : self._adra[2] + , 'nq0' : nadra1x + , 'q0' : adra1x + , 'nq1' : nadra2x + , 'q1' : adra2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand3Ra = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandra[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadra1x + else : thisMap['i0'] = adra1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadra2x + else : thisMap['i1'] = adra2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadra3x + else : thisMap['i2'] = adra3x + + self.Nand3Ra[j] = Inst ( 'rf2_dec_nand3' + , 'nand3ra%d' % j + , map = thisMap + ) + + self.Adra3 = Inst ( 'rf2_dec_bufad1_r' + , 'adra3' + , map = { 'i' : self._adra[3] + , 'nq' : nadra3x + , 'q' : adra3x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 3 : # adresse sur 3 bits + self.Adra1 = Inst ( 'rf2_dec_bufad1_l' + , 'adra1' + , map = { 'i' : self._adra[1] + , 'nq' : nadra1x + , 'q' : adra1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand2Ra = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandra[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadra1x + else : thisMap['i0'] = adra1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadra2x + else : thisMap['i1'] = adra2x + + self.Nand2Ra[j] = Inst ( 'rf2_dec_nand2' + , 'nand2ra%d' % j + , map = thisMap + ) + + self.Adra2 = Inst ( 'rf2_dec_bufad1_r' + , 'adra2' + , map = { 'i' : self._adra[2] + , 'nq' : nadra2x + , 'q' : adra2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # placement des cellules du decodeur lecture B + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur lecture A + self.Adrb0 = Inst ( 'rf2_dec_bufad0' + , 'adrb0' + , map = { 'i' : self._adrb[0] + , 'nq' : nadrb0x + , 'q' : adrb0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelRb = {} + + for j in range ( half ) : + if j == 0 : + self.SelRb[2*j] = Inst ( 'rf2_dec_nao3' + , 'selb%d' % ( 2 * j ) + , map = { 'i0' : nandrb[j] + , 'i1' : adrb0x + , 'i2' : self._renb + , 'nq' : self._selb[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.SelRb[2*j] = Inst ( 'rf2_dec_nor3' + , 'selb%d' % ( 2 * j ) + , map = { 'i0' : nandrb[j] + , 'i1' : adrb0x + , 'i2' : nrenb + , 'nq' : self._selb[2 * j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.SelRb[2*j+1] = Inst ( 'rf2_dec_nor3' + , 'selb%d' % ( 2 * j + 1 ) + , map = { 'i0' : nandrb[j] + , 'i1' : nadrb0x + , 'i2' : nrenb + , 'nq' : self._selb[2 * j + 1] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.RenB = Inst ( 'rf2_dec_nbuf' + , 'renb' + , map = { 'i' : self._renb + , 'nq' : nrenb + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Deuxieme ligne decodeur lecture A + if adrange == 5 : # adresse sur 5 bits + self.Adrb12 = Inst ( 'rf2_dec_bufad2_l' + , 'adrb12' + , map = { 'i0' : self._adrb[1] + , 'i1' : self._adrb[2] + , 'nq0' : nadrb1x + , 'q0' : adrb1x + , 'nq1' : nadrb2x + , 'q1' : adrb2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand4Rb = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandrb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + if j % 2 == 0 : thisMap['i0'] = nadrb1x + else : thisMap['i0'] = adrb1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadrb2x + else : thisMap['i1'] = adrb2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadrb3x + else : thisMap['i2'] = adrb3x + if ( j >> 3 ) % 2 == 0 : thisMap['i3'] = nadrb4x + else : thisMap['i3'] = adrb4x + + self.Nand4Rb[j] = Inst ( 'rf2_dec_nand4' + , 'nand4rb%d' % j + , map = thisMap + ) + + self.Adrb34 = Inst ( 'rf2_dec_bufad2_r' + ,'adrb34' + , map = { 'i0' : self._adrb[3] + , 'i1' : self._adrb[4] + , 'nq0' : nadrb3x + , 'q0' : adrb3x + , 'nq1' : nadrb4x + , 'q1' : adrb4x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 4 : # adresse sur 4 bits + self.Adrb12 = Inst ( 'rf2_dec_bufad2_l' + , 'adrb12' + , map = { 'i0' : self._adrb[1] + , 'i1' : self._adrb[2] + , 'nq0' : nadrb1x + , 'q0' : adrb1x + , 'nq1' : nadrb2x + , 'q1' : adrb2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand3Rb = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandrb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadrb1x + else : thisMap['i0'] = adrb1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadrb2x + else : thisMap['i1'] = adrb2x + if ( j >> 2 ) % 2 == 0 : thisMap['i2'] = nadrb3x + else : thisMap['i2'] = adrb3x + + self.Nand3Rb[j] = Inst ( 'rf2_dec_nand3' + , 'nand3rb%d' % j + , map = thisMap + ) + + self.Adrb3 = Inst ( 'rf2_dec_bufad1_r' + , 'adrb3' + , map = { 'i' : self._adrb[3] + , 'nq' : nadrb3x + , 'q' : adrb3x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + if adrange == 3 : # adresse sur 3 bits + self.Adrb1 = Inst ( 'rf2_dec_bufad1_l' + , 'adrb1' + , map = { 'i' : self._adrb[1] + , 'nq' : nadrb1x + , 'q' : adrb1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.Nand2Rb = {} + + for j in range ( half ) : + thisMap = { 'nq' : nandrb[j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j % 2 == 0 : thisMap['i0'] = nadrb1x + else : thisMap['i0'] = adrb1x + if ( j >> 1 ) % 2 == 0 : thisMap['i1'] = nadrb2x + else : thisMap['i1'] = adrb2x + + self.Nand2Rb[j] = Inst ( 'rf2_dec_nand2' + , 'nand2rb%d' % j + , map = thisMap + ) + + self.Adrb2 = Inst ( 'rf2_dec_bufad1_r' + , 'adrb2' + , map = { 'i' : self._adrb[2] + , 'nq' : nadrb2x + , 'q' : adrb2x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Layout ## + ############ + def Layout ( self, nbit, nword, type ) : + global adrange + + HCELL = 50 + + # placement des lignes de bit en dessous des buffers + bottom = 0 + + sym1 = NOSYM + sym2 = SYM_X + for i in range ( nbit ) : + if i % 2 : # lignes impaires + sym1 = SYM_Y + sym2 = SYMXY + else : # lignes paires + sym1 = NOSYM + sym2 = SYM_X + + Place ( self.In[i], sym1, XY ( 0, bottom + i * HCELL ) ) + + for j in range ( 0, nword, 2 ) : + if j == 0 and ( type == 1 or type == 3 ) : PlaceRight ( self.Bit[i][j], sym1 ) + else : PlaceRight ( self.Bit[i][j], sym1 ) + + PlaceRight ( self.Bit[i][j + 1], sym2 ) + + PlaceRight ( self.Out[i], sym1 ) + + # s_placement de la ligne contenant les buffers + bottom = nbit * HCELL + + Place ( self.InBuf, NOSYM, XY ( 0, bottom ) ) + + for j in range ( 0, nword, 2 ) : + PlaceRight ( self.Buf[j], NOSYM ) + PlaceRight ( self.Buf[j + 1], SYM_X ) + + PlaceRight ( self.OutBuf, NOSYM ) + + # s_placement des cellules du decodeur ecriture + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur ecriture + bottom = ( nbit + 2 ) * HCELL + + Place ( self.Adw0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half ) : + PlaceRight ( self.SelW[2 * j], SYM_X ) + PlaceRight ( self.SelW[2 * j + 1], NOSYM ) + + PlaceRight ( self.Wen, NOSYM ) + + # Deuxieme ligne decodeur ecriture + bottom = ( nbit + 3 ) * HCELL + + if adrange == 5 : # adresse sur 5 bits + Place ( self.Adw12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand4W[j], SYM_Y, FIXED ) + PlaceRight ( self.Adw34, SYMXY ) + + if adrange == 4 : # adresse sur 4 bits + Place ( self.Adw12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand3W[j], SYM_Y ) + PlaceRight ( self.Adw3, SYMXY ) + + if adrange == 3 : # adresse sur 3 bits + Place ( self.Adw1, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand2W[j], SYM_Y ) + PlaceRight ( self.Adw2, SYMXY ) + + # s_placement des cellules du decodeur lecture A + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur lecture A + bottom = ( nbit + 4 ) * HCELL + + Place ( self.Adra0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half ) : + PlaceRight ( self.SelRa[2 * j], NOSYM ) + PlaceRight ( self.SelRa[2 * j + 1], SYM_X ) + + PlaceRight ( self.RenA, NOSYM ) + + # Deuxieme ligne decodeur lecture A + bottom = ( nbit + 5 ) * HCELL + + if adrange == 5 : # adresse sur 5 bits + Place ( self.Adra12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand4Ra[j], SYM_Y ) + PlaceRight ( self.Adra34, SYMXY ) + + if adrange == 4 : # adresse sur 4 bits + Place ( self.Adra12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand3Ra[j], SYM_Y ) + PlaceRight ( self.Adra3, SYMXY ) + + if adrange == 3 : # adresse sur 3 bits + Place ( self.Adra1, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand2Ra[j], SYM_Y ) + PlaceRight ( self.Adra2, SYMXY ) + + # s_placement des cellules du decodeur lecture B + if type == 2 or type == 3 : + half = nword >> 1 + + # Premiere ligne decodeur lecture A + bottom = ( nbit + 6 ) * HCELL + + Place ( self.Adrb0, NOSYM, XY ( 0, bottom ) ) + + for j in range ( half ) : + PlaceRight ( self.SelRb[2 * j], NOSYM ) + PlaceRight ( self.SelRb[2 * j + 1], SYM_X ) + + PlaceRight ( self.RenB, NOSYM ) + + # Deuxieme ligne decodeur lecture A + bottom = ( nbit + 7 ) * HCELL + + if adrange == 5 : # adresse sur 5 bits + Place ( self.Adrb12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand4Rb[j], SYM_Y ) + PlaceRight ( self.Adrb34, SYMXY ) + + if adrange == 4 : # adresse sur 4 bits + Place ( self.Adrb12, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand3Rb[j], SYM_Y ) + PlaceRight ( self.Adrb3, SYMXY ) + + if adrange == 3 : # adresse sur 3 bits + Place ( self.Adrb1, SYM_Y, XY ( 0, bottom ) ) + for j in range ( half ) : PlaceRight ( self.Nand2Rb[j], SYM_Y ) + PlaceRight ( self.Adrb2, SYMXY ) + + + + ## VBE ## + ######### + def Vbe ( self ) : + print 'RF2 behavior not implemented' + + + + + +##################### +##### DPGEN_RF2 ##### +##################### +class DpgenRf2 ( top_rf2 ) : + + def Interface ( self ) : + top_rf2.Interface ( self, self._param['nbit'], self._param['nword'], 0 ) + + def Netlist ( self ) : + top_rf2.Netlist ( self, self._param['nbit'], self._param['nword'], 0 ) + + def Layout ( self ) : + top_rf2.Layout ( self, self._param['nbit'], self._param['nword'], 0 ) + + +####################### +##### DPGEN_RF2R0 ##### +####################### +class DpgenRf2r0 ( top_rf2 ) : + + def Interface ( self ) : + top_rf2.Interface ( self, self._param['nbit'], self._param['nword'], 1 ) + + def Netlist ( self ) : + top_rf2.Netlist ( self, self._param['nbit'], self._param['nword'], 1 ) + + def Layout ( self ) : + top_rf2.Layout ( self, self._param['nbit'], self._param['nword'], 1 ) + + +###################### +##### DPGEN_RF2D ##### +###################### +class DpgenRf2d ( top_rf2 ) : + + def Interface ( self ) : + top_rf2.Interface ( self, self._param['nbit'], self._param['nword'], 2 ) + + def Netlist ( self ) : + top_rf2.Netlist ( self, self._param['nbit'], self._param['nword'], 2 ) + + def Layout ( self ) : + top_rf2.Layout ( self, self._param['nbit'], self._param['nword'], 2 ) + + +######################## +##### DPGEN_RF2DR0 ##### +######################## +class DpgenRf2dr0 ( top_rf2 ) : + + def Interface ( self ) : + top_rf2.Interface ( self, self._param['nbit'], self._param['nword'], 3 ) + + def Netlist ( self ) : + top_rf2.Netlist ( self, self._param['nbit'], self._param['nword'], 3 ) + + def Layout ( self ) : + top_rf2.Layout ( self, self._param['nbit'], self._param['nword'], 3 ) diff --git a/stratus1/src/dpgen/dpgen_ROM.py b/stratus1/src/dpgen/dpgen_ROM.py new file mode 100644 index 00000000..9f300ba6 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_ROM.py @@ -0,0 +1,937 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_ROM.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +# Le nombre de mots peut prendre cinq valeurs : 64, 128, 256, 512, 1024 +# Le nombre de bits est un multiple de 4 et doit etre inferieur ou egal a 64 +# On peut avoir une sortie tri-state en option (pour construire des ROMs +# de capacite superieure a 1024 mots. +# La largeur est egale a ( nmot / 64 * 50) + 150 (+ 20 si option tristate) +# La hauteur est egale a ( nbit + 8) * 50 pour 64 ou 128 mots +# ( nbit + 9) * 50 pour 256, 512 ou 1024 mots +# +# Les valeurs a encoder dans la ROM sont recuperees dans le tableau data[2048] +# qui contient des "mots" de 32 bits : une valeur est stockee dans deux cases +# consecutives de ce tableau, ce qui permet d'avoir des mots de 64 bits. +# Les poids faibles de la valeur i sont a l'adresse data[2*i] +# Les poids forts de la valeur i sont a l'adresse data[2*i+1] +# +# Les lignes de bit horizontales en ALU2 sont hors grilles et pre-routees +# la ROM respecte le gabarit SXLIB pour ce qui concerne les caissons et les +# alimentations en ALU1 sur les faces est et ouest, mais il n'y a pas +# de continuite des alimentations en ALU1 dans la zone data. +# Pour la partie "donnees", on utilise les cellules suivantes : +# - rom_data_invss +# - rom_data_insel +# - rom_data_midvss +# - rom_data_midsel +# - rom_data_outvss +# - rom_data_outsel +# - rom_data_outvss_ts +# - rom_data_outsel_ts +# +# Pour le decodeur, on utilise les cellules suivantes : +# - rom_dec_adbuf +# - rom_dec_nop +# - rom_dec_prech +# - rom_dec_col2 +# - rom_dec_col3 +# - rom_dec_col4 +# - rom_dec_colbuf +# - rom_dec_line01 +# - rom_dec_line23 +# - rom_dec_line45 +# - rom_dec_line67 +# - rom_dec_selmux01 +# - rom_dec_selmux23 +# - rom_dec_selmux45 +# - rom_dec_selmux67 +# - rom_dec_selmux67_128 +# - rom_dec_selmux01_ts +# - rom_dec_selmux23_ts +# - rom_dec_selmux45_ts +# - rom_dec_selmux67_ts +# - rom_dec_selmux67_128_ts + +class TopRom ( Model ) : + + def Interface ( self ) : + self.nbit = self._param['nbit'] + self.nword = self._param['nword'] + + if self.nword == 64 : adrange = 6 + elif self.nword == 128 : adrange = 7 + elif self.nword == 256 : adrange = 8 + elif self.nword == 512 : adrange = 9 + elif self.nword == 1024 : adrange = 10 + else : + print "Error : DPGEN_ROM" + print "The word number (nword := %d) ", nword, "can only takes values : 64, 128, 256, 512 or 1024.\n" + sys.exit ( 3 ) + + if self.nbit % 4 != 0 or self.nbit > 64 or self.nbit < 4 : + raise "\n[Stratus ERROR] DPGEN_ROM : The bus width (nbit := %d) ", nbit, "must be multiple of 4 and no larger than 64.\n" + + self.ck = SignalIn ( "ck", 1 ) + self.selrom = SignalIn ( "selrom", 1 ) + + self.ad = SignalIn ( "ad", adrange ) + self.data = SignalOut ( "data", self.nbit ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self, type ) : + + ### Acquisition du tableau des valeurs a encoder ### +# ICI IL FAUT APPELER LE PARSER +# for(i=0 ; i<1024 ; i++) { +# data[2*i] = i; +# data[2*i+1] = 1024 - i; +# } +# dpgen_ROM_code ( LV_name, self.nbit, self.nword, 0, 0, data ) + + # Signaux internes + nck = Signal ( "nck", 1 ) + + prech = Signal ( "prech", 1 ) + nprech = Signal ( "nprech", 1 ) + + mux0 = Signal ( "mux0", 1 ) + mux1 = Signal ( "mux1", 1 ) + mux2 = Signal ( "mux2", 1 ) + mux3 = Signal ( "mux3", 1 ) + mux4 = Signal ( "mux4", 1 ) + mux5 = Signal ( "mux5", 1 ) + mux6 = Signal ( "mux6", 1 ) + mux7 = Signal ( "mux7", 1 ) + + sel0 = Signal ( "sel0", 1 ) + sel1 = Signal ( "sel1", 1 ) + sel2 = Signal ( "sel2", 1 ) + sel3 = Signal ( "sel3", 1 ) + sel4 = Signal ( "sel4", 1 ) + sel5 = Signal ( "sel5", 1 ) + sel6 = Signal ( "sel6", 1 ) + sel7 = Signal ( "sel7", 1 ) + + bit0 = Signal ( "bit0", self.nbit ) + bit1 = Signal ( "bit1", self.nbit ) + bit2 = Signal ( "bit2", self.nbit ) + bit3 = Signal ( "bit3", self.nbit ) + bit4 = Signal ( "bit4", self.nbit ) + bit5 = Signal ( "bit5", self.nbit ) + bit6 = Signal ( "bit6", self.nbit ) + bit7 = Signal ( "bit7", self.nbit ) + line0 = Signal ( "line0", self.nbit ) + line1 = Signal ( "line1", self.nbit ) + line2 = Signal ( "line2", self.nbit ) + line3 = Signal ( "line3", self.nbit ) + line4 = Signal ( "line4", self.nbit ) + line5 = Signal ( "line5", self.nbit ) + line6 = Signal ( "line6", self.nbit ) + line7 = Signal ( "line7", self.nbit ) + + mux0 = Signal ( "mux0", 1 ) + mux1 = Signal ( "mux1", 1 ) + mux2 = Signal ( "mux2", 1 ) + mux3 = Signal ( "mux3", 1 ) + mux4 = Signal ( "mux4", 1 ) + mux5 = Signal ( "mux5", 1 ) + mux6 = Signal ( "mux6", 1 ) + mux7 = Signal ( "mux7", 1 ) + + a0 = Signal ( "a0", 1 ) + na0 = Signal ( "na0", 1 ) + a1 = Signal ( "a1", 1 ) + na1 = Signal ( "na1", 1 ) + a2 = Signal ( "a2", 1 ) + na2 = Signal ( "na2", 1 ) + a3 = Signal ( "a3", 1 ) + na3 = Signal ( "na3", 1 ) + a4 = Signal ( "a4", 1 ) + na4 = Signal ( "na4", 1 ) + a5 = Signal ( "a5", 1 ) + na5 = Signal ( "na5", 1 ) + a6x = Signal ( "a6x", 1 ) + na6x = Signal ( "na6x", 1 ) + a7x = Signal ( "a7x", 1 ) + na7x = Signal ( "na7x", 1 ) + a8x = Signal ( "a8x", 1 ) + na8x = Signal ( "na8x", 1 ) + a9x = Signal ( "a9x", 1 ) + na9x = Signal ( "na9x", 1 ) + + col = Signal ( "col", self.nbit ) + + In = {} + Bit = {} + Out = {} + for i in range ( self.nbit ) : + valeur = i % 4 + if valeur == 0 : + cellin = "rom_data_invss" + cellmid = "rom_data_midvss" + if type == 0 : cellout = "rom_data_outvss" + else : cellout = "rom_data_outvss_ts" + elif valeur == 1 : + cellin = "rom_data_insel" + cellmid = "rom_data_midsel" + if type == 0 : cellout = "rom_data_outsel" + else : cellout = "rom_data_outsel_ts" + elif valeur == 2: + cellin = "rom_data_insel" + cellmid = "rom_data_midsel" + if type == 0 : cellout = "rom_data_outsel" + else : cellout = "rom_data_outsel_ts" + elif valeur == 3 : + cellin = "rom_data_invss" + cellmid = "rom_data_midvss" + if type == 0 : cellout = "rom_data_outvss" + else : cellout = "rom_data_outvss_ts" + + In[i] = Inst ( cellin + , "in%d" % i + , map = { 'prech' : prech + , 'bit0' : bit0[i] + , 'bit1' : bit1[i] + , 'bit2' : bit2[i] + , 'bit3' : bit3[i] + , 'bit4' : bit4[i] + , 'bit5' : bit5[i] + , 'bit6' : bit6[i] + , 'bit7' : bit7[i] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + BitBis = {} + Bit[i] = BitBis + for j in range ( 0, self.nword, 64 ) : + Bit[i][j] = Inst ( cellmid + , "bit%d_%d" % ( i, j ) + , map = { 'sela' : line0[j] + , 'selb' : line2[j] + , 'selc' : line4[j] + , 'seld' : line6[j] + , 'bit0' : bit0 [i] + , 'bit1' : bit1 [i] + , 'bit2' : bit2 [i] + , 'bit3' : bit3 [i] + , 'bit4' : bit4 [i] + , 'bit5' : bit5 [i] + , 'bit6' : bit6 [i] + , 'bit7' : bit7 [i] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Bit[i][j+32] = Inst ( cellmid + , "bit%d_%d" % ( i, j+32 ) + , map = { 'sela' : line1[j] + , 'selb' : line3[j] + , 'selc' : line5[j] + , 'seld' : line7[j] + , 'bit0' : bit0 [i] + , 'bit1' : bit1 [i] + , 'bit2' : bit2 [i] + , 'bit3' : bit3 [i] + , 'bit4' : bit4 [i] + , 'bit5' : bit5 [i] + , 'bit6' : bit6 [i] + , 'bit7' : bit7 [i] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + thisMap = { 'nprech' : nprech + , 'mux0' : mux0 + , 'mux1' : mux1 + , 'mux2' : mux2 + , 'mux3' : mux3 + , 'mux4' : mux4 + , 'mux5' : mux5 + , 'mux6' : mux6 + , 'mux7' : mux7 + , 'bit0' : bit0[i] + , 'bit1' : bit1[i] + , 'bit2' : bit2[i] + , 'bit3' : bit3[i] + , 'bit4' : bit4[i] + , 'bit5' : bit5[i] + , 'bit6' : bit6[i] + , 'bit7' : bit7[i] + , 'q' : data[i] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Out[i] = Inst ( cellout + , "out%d" % i + , map = thisMap + ) + + ## Cellules decodeur ## + # Lignes 0 et 1 + Prech = Inst ( "rom_dec_prech" + , "prech" + , map = { 'nck' : nck + , 'prech' : prech + , 'nprech' : nprech + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + And01 = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'nck0' : nck + , 'nck1' : nck + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'line0' : line0[j] + , 'line1' : line1[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if self.nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = One ( 1 ) + And01[j] = Inst ( "rom_dec_line01" + , "and01_%d" % j + , map = thisMap + ) + + if type == 0 : model = "rom_dec_selmux01" + else : model = "rom_dec_selmux01_rs" + thisMap = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : self.ck + , 'selrom' : self.selrom + , 'nck' : nck + , 'mux0' : mux0 + , 'sel0' : sel0 + , 'mux1' : mux1 + , 'sel1' : sel1 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Selmux01 = Inst ( model + , "selmux01" + , map = thisMap + ) + + # Lignes 2 et 3 + Ad4 = Inst ( "rom_dec_adbuf" + , "ad4" + , map = { 'ad' : self.ad[4] + , 'adx' : a4 + , 'nadx' : na4 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Ad5 = Inst ( "rom_dec_adbuf" + , "ad5" + , map = { 'ad' : self.ad[5] + , 'adx' : a5 + , 'nadx' : na5 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + And23 = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'nck2' : nck + , 'nck3' : nck + , 'sel2' : sel2 + , 'sel3' : sel3 + , 'line2' : line2[j] + , 'line3' : line3[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if self.nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = One ( 1 ) + And23[j] = Inst ( "rom_dec_line23" + , "and23_%d" % j + , map = thisMap + ) + + if type == 0 : model = "rom_dec_selmux23" + else : model = "rom_dec_selmux23_rs" + thisMap = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : self.ck + , 'selrom' : self.selrom + , 'nck' : nck + , 'mux2' : mux2 + , 'sel2' : sel2 + , 'mux3' : mux3 + , 'sel3' : sel3 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Selmux23 = Inst ( "rom_dec_selmux23" + , "selmux23" + , map = thisMap + ) + + # Lignes 4 et 5 + Ad2 = Inst ( "rom_dec_adbuf" + , "ad2" + , map = { 'ad' : self.ad[2] + , 'adx' : a2 + , 'nadx' : na2 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Ad3 = Inst ( "rom_dec_adbuf" + , "ad3" + , map = { 'ad' : self.ad[3] + , 'adx' : a3 + , 'nadx' : na3 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + And45 = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'nck4' : nck + , 'nck5' : nck + , 'sel4' : sel4 + , 'sel5' : sel5 + , 'line4' : line4[j] + , 'line5' : line5[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if self.nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = One ( 1 ) + And45[j] = Inst ( "rom_dec_line45" + , "and45_%d" % j + , map = thisMap + ) + + if type == 0 : model = "rom_dec_selmux45" + else : model = "rom_dec_selmux45_rs" + thisMap = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : self.ck + , 'selrom' : self.selrom + , 'nck' : nck + , 'mux4' : mux4 + , 'sel5' : sel4 + , 'mux5' : mux5 + , 'sek5' : sel5 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Selmux45 = Inst ( model + , "selmux23" + , map = thisMap + ) + + # Lignes 6 et 7 + Ad0 = Inst ( "rom_dec_adbuf" + , "ad0" + , map = { 'ad' : self.ad[0] + , 'adx' : a0 + , 'nadx' : na0 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Ad1 = Inst ( "rom_dec_adbuf" + , "ad1" + , map = { 'ad' : self.ad[1] + , 'adx' : a1 + , 'nadx' : na1 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + And67 = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'nck6' : nck + , 'nck7' : nck + , 'sel6' : sel6 + , 'sel7' : sel7 + , 'line6' : line6[j] + , 'line7' : line7[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if self.nword != 64 : thisMap['col'] = col[j] + else : thisMap['col'] = One ( 1 ) + And67[j] = Inst ( "rom_dec_line67" + , "and67_%d" % j + , map = thisMap + ) + + if self.nword != 128 : # pas de sortie tristate + if type == 0 : model = "rom_dec_selmux67" + else : model = "rom_dec_selmux67_ts" + thisMap = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'ck' : self.ck + , 'selrom' : self.selrom + , 'nck' : nck + , 'mux6' : mux6 + , 'sel6' : sel6 + , 'mux7' : mux7 + , 'sel7' : sel7 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Selmux67 = Inst ( model + , "selmux67" + , map = thisMap + ) + else : # pas de sortie tristate - 128 mots + if type == 0 : model = "rom_dec_selmux128" + else : model = "rom_dec_selmux128_ts" + thisMap = { 'a0' : a0 + , 'na0' : na0 + , 'a1' : a1 + , 'na1' : na1 + , 'a2' : a2 + , 'na2' : na2 + , 'a3' : a3 + , 'na3' : na3 + , 'a4' : a4 + , 'na4' : na4 + , 'a5' : a5 + , 'na5' : na5 + , 'a6' : self.ad[6] + , 'selrom' : self.selrom + , 'a6x' : col[64] + , 'na6x' : col[0] + , 'mux6' : mux6 + , 'sel6' : sel6 + , 'mux7' : mux7 + , 'sel7' : sel7 + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if type == 1 : + thisMap['enx'] = enx + thisMap['nenx'] = nenx + Selmux67 = Inst ( model + , "selmux67" + , map = thisMap + ) + + # Ligne 9 dans le cas 1024 mots + if self.nword == 1024 : + Nop = Inst ( "rom_dec_nop" + , "nop" + , map = { 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + Col = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'q' : col[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if ( j >> 6 ) % 2 == 0 : thisMap['i0'] = na6x + else : thisMap['i0'] = a6x + if ( j >> 7 ) % 2 == 0 : thisMap['i1'] = na7x + else : thisMap['i1'] = a7x + if ( j >> 8 ) % 2 == 0 : thisMap['i2'] = na8x + else : thisMap['i2'] = a8x + if ( j >> 9 ) % 2 == 0 : thisMap['i3'] = na9x + else : thisMap['i3'] = a9x + Col[j] = Inst ( "rom_dec_col4" + , "col_%d" % j + , map = thisMap + ) + + ColBuf6 = Inst ( "rom_dec_colbuf" + , "colbuf6" + , map = { 'a' : self.ad[6] + , 'ax' : a6x + , 'nax' : na6x + , 'vdd' : self.vdd + , 'vss' : self.vss + ) + ColBuf7 = Inst ( "rom_dec_colbuf" + , "colbuf7" + , map = { 'a' : self.ad[7] + , 'ax' : a7x + , 'nax' : na7x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + ColBuf8 = Inst ( "rom_dec_colbuf" + , "colbuf8" + , map = { 'a' : self.ad[8] + , 'ax' : a8x + , 'nax' : na8x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + ColBuf9 = Inst ( "rom_dec_colbuf" + , "colbuf9" + , map = { 'a' : self.ad[9] + , 'ax' : a9x + , 'nax' : na9x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + # Ligne 9 dans le cas 512 mots + if self.nword == 512 : + Nop = Inst ( "rom_dec_nop" + , "nop" + , map = { 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'q' : col[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if ( j >> 6 ) % 2 == 0 : thisMap['i0'] = na6x + else : thisMap['i0'] = a6x + if ( j >> 7 ) % 2 == 0 : thisMap['i1'] = na7x + else : thisMap['i1'] = a7x + if ( j >> 8 ) % 2 == 0 : thisMap['i2'] = na8x + else : thisMap['i2'] = a8x + Col[j] = Inst ( "rom_dec_col3" + , "col_%d" % j + , map = thisMap + ) + + Colbuf6 = Inst ( "rom_dec_colbuf" + , "colbuf6" + , map = { 'a' : ad[6] + , 'ax' : a6x + , 'nax' : na6x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Colbuf7 = Inst ( "rom_dec_colbuf" + , "colbuf7" + , map = { 'a' : ad[7] + , 'ax' : a7x + , 'nax' : na7x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + Colbuf8 = Inst ( "rom_dec_colbuf" + , "colbuf8" + , map = { 'a' : ad[8] + , 'ax' : a8x + , 'nax' : na8x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + # Ligne 9 dans le cas 256 mots + if self.nword == 256 : + Nop = Inst ( "rom_dec_nop" + , "nop" + , map = { 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + Col = {} + for j in range ( 0, self.nword, 64 ) : + thisMap = { 'q' : col[j] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + if ( j >> 6 ) % 2 == 0 : thisMap['i0'] = na6x + else : thisMap['i0'] = a6x + if ( j >> 7 ) % 2 == 0 : thisMap['i1'] = na7x + else : thisMap['i1'] = a7x + Col[j] = Inst ( "rom_dec_col2" + , "col_%d" % j + , map = thisMap + ) + + Colbuf6 = Inst ( "rom_dec_colbuf" + , "colbuf6" + , map = { 'a' : ad[6] + , 'ax' : a6x + , 'nax' : na6x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + ColBuf7 = Inst ( "rom_dec_colbuf" + , "colbuf7" + , map = { 'a' : ad[7] + , 'ax' : a7x + , 'nax' : na7x + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def Layout ( self ) : + ## Placement des lignes du plan memoire ## + for i in range ( self.nbit ) : + val = i % 4 + if val == 0 : sym = NOSYM + elif val == 1 : sym = SYM_Y + elif val == 2 : sym = NOSYM + elif val == 3 : sym = SYM_Y + + Place ( In(i], sym, 0, i*HCELL ) + + for j in range ( 0, self.nword, 64 ) : + PlaceRight ( Bit[i][j], sym ) + PlaceRight ( Bit[i][j+32], sym ) + + PlaceRight ( Out[i], sym ) + + ## Placement des cellules decodeur ## + + # Lignes 0 et 1 + Place ( Prech, NOSYM, 0, nbit*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( And01[j], NOSYM ) + PlaceRight ( Selmux01, NOSYM ) + + # Lignes 2 et 3 + Place ( Ad4, SYM_Y, 0, (nbit+3)*HCELL ) + Place ( Ad5, NOSYM, 0, (nbit+2)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( And23[j], NOSYM ) + PlaceRight ( Selmux23, NOSYM ) + + # Lignes 4 et 5 + Place ( Ad2, SYM_Y, 0, (nbit+5)*HCELL ) + Place ( Ad3, NOSYM, 0, (nbit+4)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( And45[j], NOSYM ) + Place ( Selmux45, NOSYM ) + + # Lignes 6 et 7 + Place ( Ad0, SYM_Y, 0, (nbit+7)*HCELL ) + Place ( Ad1, NOSYM, 0, (nbit+6)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( And67[j], NOSYM ) + PlaceRight ( Selmux67, NOSYM ) + + # Ligne 9 dans le cas 1024 mots + if self.nword == 1024 : + Place ( Nop, NOSYM, 0, (nbit+8)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( Col, NOSYM ) + PlaceRight ( ColBuf6, NOSYM ) + PlaceRight ( ColBuf7, NOSYM ) + PlaceRight ( ColBuf8, NOSYM ) + PlaceRight ( ColBuf9, NOSYM ) + # Ligne 9 dans le cas 512 mots + elif self.nword == 512 : + Place ( Nop, NOSYM, 0, (nbit+8)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( Col[j], NOSYM ) + PlaceRight ( ColBuf6, NOSYM ) + PlaceRight ( ColBuf7, NOSYM ) + PlaceRight ( ColBuf8, NOSYM ) + # Ligne 9 dans le cas 256 mots + elif self.nword == 256 : + Place ( Nop, NOSYM, 0, (nbit+8)*HCELL ) + for j in range ( 0, self.nword, 64 ) : PlaceRight ( Col[j], NOSYM ) + PlaceRight ( ColBuf6, NOSYM ) + PlaceRight ( ColBuf7, NOSYM ) + + def ROM_VHDL ( self ) : + global LV_flags + global LV_ModelName + + pass +# fileName = LV_ModelName + ".vbe" +# +# file = open ( fileName, "w+" ) +# +# if self.nword == 64 : adrange = 6 +# elif self.nword == 128 : adrange = 7 +# elif self.nword == 256 : adrange = 8 +# elif self.nword == 512 : adrange = 9 +# elif self.nword == 1024 : adrange = 10 +# +# sBusWide0 = VHDL_BUS_WIDE ( self.nbit - 1, 0, self.nbit, LV_flags ) +# sBusWide1 = VHDL_BUS_WIDE ( adrange - 1, 0, self.nbit, LV_flags ) +# +# ## Entity description ## +# file.write ( "\nENTITY %s IS\n PORT (\n" % LV_ModelName ) +# +# file.write ( "%14s : in BIT;\n" % "ck" ) +# file.write ( "%14s : in BIT;\n" % "selrom" ) +# file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "ad", sBusWide1 ) ) +# file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "data", sBusWide0 ) ) +# +# ## Power supplies terminals ## +# file.write ( "%14s : in BIT;\n" % "vdd" ) +# file.write ( "%14s : in BIT\n" % "vss" ) +# +# ## End of entity description ## +# file.write ( " );\nEND %s;\n\n\n" % LV_ModelName ) +# +# ## Architecture description ## +# file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % LV_ModelName ) +# +# ## Signals ## +# +# +# +# ## Behavior ## +# file.write ( "\nBEGIN\n\n" ) +# +# +# +# +# +# ## Assert ## +# file.write ( " ASSERT (vdd = '1')\n" ) +# file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % LV_modelName ) +# file.write ( " SEVERITY WARNING;\n\n" ) +# +# +# file.write ( " ASSERT (vss = '0')\n" ) +# file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % LV_modelName ) +# file.write ( " SEVERITY WARNING;\n\n" ) +# +# ## End of Architectural description ## +# file.write ( "END VBE;\n" ) +# +# file.close () + +#################### +##### DpgenROM ##### +#################### +class DpgenROM ( TopRom ) : + + def Interface ( self ) : TopRom.Interface ( self ) + def Netlist ( self ) : TopRom.Netlist ( self, 0 ) + def Layout ( self ) : topRom.Layout ( self ) + def Vbe ( self ) : topRom.Vbe ( self ) + + +###################### +##### DpgenROMTS ##### +###################### +class DpgenROMTS ( TopRom ) : + + def Interface ( self ) : TopRom.Interface ( self ) + def Netlist ( self ) : TopRom.Netlist ( self, 1 ) + def Layout ( self ) : topRom.Layout ( self ) + def Vbe ( self ) : topRom.Vbe ( self ) diff --git a/stratus1/src/dpgen/dpgen_ROM2.py b/stratus1/src/dpgen/dpgen_ROM2.py new file mode 100644 index 00000000..2550b934 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_ROM2.py @@ -0,0 +1,226 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_ROM2.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenRom2 ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + + self._nbit = self._param['nbit'] + + self._sel0 = SignalIn ( "sel0", 1 ) + self._q = SignalOut ( "q", self._nbit ) + + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ################## + def Netlist ( self ) : + global LV_xl0, LV_xl1, LV_iLeafCell + + val = [] + val.append ( self._param['val0'] ) + val.append ( self._param['val1'] ) + + # Parses the constants + LV_xl0 = newxl () + LV_xl0.atoxl ( val[0] ) + LV_xl0._size = self._nbit + + LV_xl1 = newxl () + LV_xl1.atoxl ( val[1] ) + LV_xl1._size = self._nbit + + LV_iLeafCell = 0 + + # Signal + ni0x = Signal ( "ni0x", 1 ) + + + # Loop for all the data slices + self.Cell = {} + + for iSlice in range ( self._nbit ) : + iCell = get_index_Cell ( iSlice, DPGEN_ROM2, LV_xl0, LV_xl1 ) + sModel = get_model_Cell ( iSlice, DPGEN_ROM2, iCell, LV_iLeafCell ) + + if iCell == 0 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'nq' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif iCell == 3 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif iCell == 1 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : ni0x + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif iCell == 2 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : ni0x + , 'nq' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Add the buffer + if iSlice % 2 : iSlice += 1 + + sModel = get_model_Buffer ( DPGEN_ROM2, LV_iLeafCell ) + + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._sel0 + , 'nix' : ni0x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Layout ## + ############ + def Layout ( self ) : + + # Loop for all the data slices + for iSlice in range ( self._nbit ) : + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + # Add the buffer cell + if iSlice % 2 : iSlice += 1 + + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + + ########## uROM_VHDL ########## + ############################### + def Vbe ( self ) : + global LV_xl0 + global LV_xl1 + global LV_xl2 + global LV_xl3 + + flags = self._param['flags'] + + fileName = self._name + ".vbe" + + file = open ( fileName, "w+" ) + + sBusWide = VHDL_BUS_WIDE ( self._nbit - 1, 0, self._nbit, flag ) + + ## Entity description ## + file.write ( "\nENTITY %s IS\n PORT (\n" % self._name ) + + file.write ( "%14s : in BIT;\n" % "sel0" ) + + ## Output data bus ## + file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "q", sBusWide ) ) + + ## Power supplies terminals ## + file.write ( "%14s : in BIT;\n" % "vdd" ) + file.write ( "%14s : in BIT\n" % "vss" ) + + ## End of entity description ## + file.write ( " );\nEND %s;\n\n\n" % self._name ) + + ## Architecture description ## + file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % self._name ) + + file.write ( "BEGIN\n\n") + + ## Behavior ## + file.write ( " WITH sel0 SELECT\n" ) + file.write ( " q <= %s WHEN \'0\',\n" % LV_xl0.xltovhdl () ) + file.write ( " %s WHEN \'1\';\n\n" % LV_xl1.xltovhdl () ) + + ## Assert ## + file.write ( " ASSERT (vdd = '1')\n" ) + file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + file.write ( " ASSERT (vss = '0')\n" ) + file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + ## End of architecture description ## + file.write ( "END VBE;\n" ) + + file.close () diff --git a/stratus1/src/dpgen/dpgen_ROM4.py b/stratus1/src/dpgen/dpgen_ROM4.py new file mode 100644 index 00000000..ba3e4154 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_ROM4.py @@ -0,0 +1,294 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_ROM4.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenRom4 ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + + self._nbit = self._param['nbit'] + + self._sel0 = SignalIn ( "sel0", 1 ) + self._sel1 = SignalIn ( "sel1", 1 ) + + self._q = SignalOut ( "q", self._nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + ## Netlist ## + ############# + def Netlist ( self ) : + global LV_xl0, LV_xl1, LV_xl2, LV_xl3, LV_iLeafCell + + # Parses the constants + LV_xl0 = newxl () + LV_xl0.atoxl ( self._param['val0'] ) + LV_xl0._size = self._nbit + + LV_xl1 = newxl () + LV_xl1.atoxl ( self._param['val1'] ) + LV_xl1._size = self._nbit + + LV_xl2 = newxl () + LV_xl2.atoxl ( self._param['val2'] ) + LV_xl2._size = self._nbit + + LV_xl3 = newxl () + LV_xl3.atoxl ( self._param['val3'] ) + LV_xl3._size = self._nbit + + + LV_iLeafCell = CELLS_ROM2 + + + # Signal + i0x = Signal ( "i0x", 1 ) + ni0x = Signal ( "ni0x", 1 ) + i1x = Signal ( "i1x", 1 ) + ni1x = Signal ( "ni1x", 1 ) + + sI0 = Signal ( "si0" ) + sI1 = Signal ( "si1" ) + + + # Loop for all the data slices + self.Cell = {} + + for iSlice in range ( self._nbit ) : + iCell = get_index_Cell ( iSlice, DPGEN_ROM4, LV_xl0, LV_xl1, LV_xl2, LV_xl3 ) + sModel = get_model_Cell ( iSlice, DPGEN_ROM4, iCell, LV_iLeafCell ) + + sI0 = i0x + sI1 = i1x + + # Select the inputs + if iCell == 8 or iCell == 9 or iCell == 10 or iCell == 14 : + sI0 = i0x + sI1 = i1x + elif iCell == 2 or iCell == 11 : + sI0 = i0x + sI1 = ni1x + elif iCell == 4 or iCell == 13 : + sI0 = ni0x + sI1 = i1x + elif iCell == 1 or iCell == 5 or iCell == 6 or iCell == 7 : + sI0 = ni0x + sI1 = ni1x + elif iCell == 3 : + sI0 = ni1x + elif iCell == 12 : + sI0 = i1x + + # Select the gate + if sModel[0:4] == "zero" : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'nq' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif sModel[0:3] == "one" : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif sModel[0:3] == "buf" : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : sI0 + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif sModel[0:3] == "inv" : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : sI0 + , 'nq' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif sModel[0:2] in ( "a2", "o2" ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : sI0 + , 'i1' : sI1 + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif sModel[0:11] == "dp_rom4_xr2" or sModel[0:12] == "dp_rom4_nxr2" : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0x' : i0x + , 'i1x' : i1x + , 'ni0x' : ni0x + , 'ni1x' : ni1x + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + # Add the buffer + if iSlice % 2 : iSlice += 1 + + sModel = get_model_Buffer ( DPGEN_ROM4, LV_iLeafCell ) + + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._sel0 + , 'i1' : self._sel1 + , 'i0x' : i0x + , 'i1x' : i1x + , 'ni0x' : ni0x + , 'ni1x' : ni1x + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Layout ## + ############ + def Layout (self ) : + + # Loop for all the data slices + for iSlice in range ( self._nbit ) : + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + # Add the buffer cell + if iSlice % 2 : iSlice += 1 + + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + + ## VBE ## + ######### + def Vbe ( self ) : + global LV_xl0 + global LV_xl1 + global LV_xl2 + global LV_xl3 + + flags = self._param['flags'] + + fileName = self._name + ".vbe" + + file = open ( fileName, "w+" ) + + sBusWide = VHDL_BUS_WIDE ( self._nbit - 1, 0, self._nbit, flag ) + + ## Entity description ## + file.write ( "\nENTITY %s IS\n PORT (\n" % self._name ) + + ## Controls Terminals ## + file.write ( "%14s : in BIT;\n" % "sel1" ) + + file.write ( "%14s : in BIT;\n" % "sel0" ) + + ## Output data bus ## + file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "q", sBusWide ) ) + + ## Power supplies terminals ## + file.write ( "%14s : in BIT;\n" % "vdd" ) + file.write ( "%14s : in BIT\n" % "vss" ) + + ## End of entity description ## + file.write ( " );\nEND %s;\n\n\n" % self._name ) + + ## Architecture description ## + file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % self._name ) + + file.write ( "BEGIN\n\n") + + ## Behavior ## + file.write ( " WITH sel1 & sel0 SELECT\n" ) + file.write ( " q <= %s WHEN B\"00\",\n" % LV_xl0.xltovhdl () ) + file.write ( " %s WHEN B\"01\",\n" % LV_xl1.xltovhdl () ) + file.write ( " %s WHEN B\"10\",\n" % LV_xl2.xltovhdl () ) + file.write ( " %s WHEN B\"11\";\n\n" % LV_xl3.xltovhdl () ) + + ## Assert ## + file.write ( " ASSERT (vdd = '1')\n" ) + file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + file.write ( " ASSERT (vss = '0')\n" ) + file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + ## End of architecture description ## + file.write ( "END VBE;\n" ) + + file.close () diff --git a/stratus1/src/dpgen/dpgen_Regular.py b/stratus1/src/dpgen/dpgen_Regular.py new file mode 100644 index 00000000..7945bb09 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_Regular.py @@ -0,0 +1,1463 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_Regular.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + + +# Local constants +MAX_TDRIVE = 8 +ERROR_INDEX = 4096 +SIZE_SNAME = 1024 + + +# Local variables (prefix "LV_") +LV_ttDrive = [] +LV_ttDrive.append ( [1, 0, 0, 0, 0, 0, 0, 0] ) +LV_ttDrive.append ( [1, 2, 4, 8, 0, 0, 0, 0] ) +LV_ttDrive.append ( [2, 4, 8, 0, 0, 0, 0, 0] ) +LV_ttDrive.append ( [1, 4, 0, 0, 0, 0, 0, 0] ) +LV_ttDrive.append ( [2, 4, 0, 0, 0, 0, 0, 0] ) +LV_ttDrive.append ( [4, 8, 0, 0, 0, 0, 0, 0] ) + +LV_tsLeafCell = [] +LV_tsLeafCell.append ( "inv_x1" ) +LV_tsLeafCell.append ( "inv_x2" ) +LV_tsLeafCell.append ( "inv_x4" ) +LV_tsLeafCell.append ( "inv_x8" ) +LV_tsLeafCell.append ( "buf_x2" ) +LV_tsLeafCell.append ( "buf_x4" ) +LV_tsLeafCell.append ( "buf_x8" ) +LV_tsLeafCell.append ( "na2_x1" ) +LV_tsLeafCell.append ( "na2_x4" ) +LV_tsLeafCell.append ( "na3_x1" ) +LV_tsLeafCell.append ( "na3_x4" ) +LV_tsLeafCell.append ( "na4_x1" ) +LV_tsLeafCell.append ( "na4_x4" ) +LV_tsLeafCell.append ( "a2_x2" ) +LV_tsLeafCell.append ( "a2_x4" ) +LV_tsLeafCell.append ( "a3_x2" ) +LV_tsLeafCell.append ( "a3_x4" ) +LV_tsLeafCell.append ( "a4_x2" ) +LV_tsLeafCell.append ( "a4_x4" ) +LV_tsLeafCell.append ( "no2_x1" ) +LV_tsLeafCell.append ( "no2_x4" ) +LV_tsLeafCell.append ( "no3_x1" ) +LV_tsLeafCell.append ( "no3_x4" ) +LV_tsLeafCell.append ( "no4_x1" ) +LV_tsLeafCell.append ( "no4_x4" ) +LV_tsLeafCell.append ( "o2_x2" ) +LV_tsLeafCell.append ( "o2_x4" ) +LV_tsLeafCell.append ( "o3_x2" ) +LV_tsLeafCell.append ( "o3_x4" ) +LV_tsLeafCell.append ( "o4_x2" ) +LV_tsLeafCell.append ( "o4_x4" ) +LV_tsLeafCell.append ( "nxr2_x1" ) +LV_tsLeafCell.append ( "nxr2_x4" ) +LV_tsLeafCell.append ( "xr2_x1" ) +LV_tsLeafCell.append ( "xr2_x4" ) +LV_tsLeafCell.append ( "dp_nmux_x1_buf" ) +LV_tsLeafCell.append ( "dp_nmux_x1" ) +LV_tsLeafCell.append ( "dp_mux_x2_buf" ) +LV_tsLeafCell.append ( "dp_mux_x2" ) +LV_tsLeafCell.append ( "dp_mux_x4_buf" ) +LV_tsLeafCell.append ( "dp_mux_x4" ) +LV_tsLeafCell.append ( "dp_nts_x2_buf" ) +LV_tsLeafCell.append ( "dp_nts_x2" ) +LV_tsLeafCell.append ( "dp_ts_x4_buf" ) +LV_tsLeafCell.append ( "dp_ts_x4" ) +LV_tsLeafCell.append ( "dp_ts_x8_buf" ) +LV_tsLeafCell.append ( "dp_ts_x8" ) +LV_tsLeafCell.append ( "inv_x8" ) +LV_tsLeafCell.append ( "na2_x4" ) +LV_tsLeafCell.append ( "inv_x4" ) +LV_tsLeafCell.append ( "buf_x8" ) +LV_tsLeafCell.append ( "inv_x4" ) +LV_tsLeafCell.append ( "no2_x4" ) +LV_tsLeafCell.append ( "buf_x8" ) +LV_tsLeafCell.append ( "inv_x4" ) +LV_tsLeafCell.append ( "nxr2_x4" ) +LV_tsLeafCell.append ( "zero_x0" ) +LV_tsLeafCell.append ( "one_x0" ) +LV_tsLeafCell.append ( "dp_dff_x4_buf" ) +LV_tsLeafCell.append ( "dp_dff_x4" ) +LV_tsLeafCell.append ( "dp_dff_scan_x4_buf" ) +LV_tsLeafCell.append ( "dp_dff_scan_x4" ) +LV_tsLeafCell.append ( "dp_sff_x4_buf" ) +LV_tsLeafCell.append ( "dp_sff_x4" ) +LV_tsLeafCell.append ( "dp_sff_scan_x4_buf" ) +LV_tsLeafCell.append ( "dp_sff_scan_x4" ) + +########################### +## Functions Definitions ## +########################### + +################### +def set_tDrive ( LV_Function ) : + global LV_tDrive + global LV_ttDrive + + + if LV_Function == DPGEN_INV : LV_tDrive = LV_ttDrive[1] + elif LV_Function == DPGEN_BUFF : LV_tDrive = LV_ttDrive[2] + elif LV_Function == DPGEN_NAND2 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_NAND3 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_NAND4 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_NOR2 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_NOR3 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_NOR4 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_XNOR2 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_XOR2 : LV_tDrive = LV_ttDrive[3] + elif LV_Function == DPGEN_AND2 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_AND3 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_AND4 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_OR2 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_OR3 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_OR4 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_MUX2 : LV_tDrive = LV_ttDrive[4] + elif LV_Function == DPGEN_BUSE : LV_tDrive = LV_ttDrive[5] + elif LV_Function == DPGEN_NMUX2 : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_NBUSE : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_NAND2MASK : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_NOR2MASK : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_XNOR2MASK : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_CONST : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_DFF : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_DFFT : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_SFF : LV_tDrive = LV_ttDrive[0] + elif LV_Function == DPGEN_SFFT : LV_tDrive = LV_ttDrive[0] + else : LV_tDrive = LV_ttDrive[0] + +###################### +def set_iLeafCell ( LV_Function ) : + global LV_iLeafCell + + LV_iLeafCell = 0 + + if LV_Function == DPGEN_SFFT : LV_iLeafCell += 64 + elif LV_Function == DPGEN_SFF : LV_iLeafCell += 62 + elif LV_Function == DPGEN_DFFT : LV_iLeafCell += 60 + elif LV_Function == DPGEN_DFF : LV_iLeafCell += 58 + elif LV_Function == DPGEN_CONST : LV_iLeafCell += 56 + elif LV_Function == DPGEN_XNOR2MASK : LV_iLeafCell += 53 + elif LV_Function == DPGEN_NOR2MASK : LV_iLeafCell += 50 + elif LV_Function == DPGEN_NAND2MASK : LV_iLeafCell += 47 + elif LV_Function == DPGEN_BUSE : LV_iLeafCell += 43 + elif LV_Function == DPGEN_NBUSE : LV_iLeafCell += 41 + elif LV_Function == DPGEN_MUX2 : LV_iLeafCell += 37 + elif LV_Function == DPGEN_NMUX2 : LV_iLeafCell += 35 + elif LV_Function == DPGEN_XOR2 : LV_iLeafCell += 33 + elif LV_Function == DPGEN_XNOR2 : LV_iLeafCell += 31 + elif LV_Function == DPGEN_OR4 : LV_iLeafCell += 29 + elif LV_Function == DPGEN_OR3 : LV_iLeafCell += 27 + elif LV_Function == DPGEN_OR2 : LV_iLeafCell += 25 + elif LV_Function == DPGEN_NOR4 : LV_iLeafCell += 23 + elif LV_Function == DPGEN_NOR3 : LV_iLeafCell += 21 + elif LV_Function == DPGEN_NOR2 : LV_iLeafCell += 19 + elif LV_Function == DPGEN_AND4 : LV_iLeafCell += 17 + elif LV_Function == DPGEN_AND3 : LV_iLeafCell += 15 + elif LV_Function == DPGEN_AND2 : LV_iLeafCell += 13 + elif LV_Function == DPGEN_NAND4 : LV_iLeafCell += 11 + elif LV_Function == DPGEN_NAND3 : LV_iLeafCell += 9 + elif LV_Function == DPGEN_NAND2 : LV_iLeafCell += 7 + elif LV_Function == DPGEN_BUFF : LV_iLeafCell += 4 + +################################## +def init_Generator ( aFunction ) : + global LV_Function + + # Set the function once and for all. + LV_Function = aFunction + + set_tDrive ( LV_Function ) + set_iLeafCell ( LV_Function ) + +################### +def has_Buffer ( LV_Function ) : + + if LV_Function in ( DPGEN_INV, DPGEN_BUFF, DPGEN_NAND2, DPGEN_NAND3, DPGEN_NAND4, DPGEN_AND2, DPGEN_AND3, DPGEN_AND4, DPGEN_NOR2, DPGEN_NOR3, DPGEN_NOR4, DPGEN_OR2, DPGEN_OR3, DPGEN_OR4, DPGEN_XNOR2, DPGEN_XOR2, DPGEN_CONST ) : + return 0 + + elif LV_Function in ( DPGEN_NMUX2, DPGEN_NBUSE, DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT, DPGEN_BUSE, DPGEN_MUX2, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + return 1 + + return 0 + +################################ +def get_Model_Cell ( aiSlice ) : + global LV_Function + global LV_iLeafCell + global LV_tsLeafCell + global LV_macroDrive + global LV_xl + + index = ERROR_INDEX + + if LV_Function in ( DPGEN_INV, DPGEN_BUFF, DPGEN_NAND2, DPGEN_NAND3, DPGEN_NAND4, DPGEN_AND2, DPGEN_AND3, DPGEN_AND4, DPGEN_NOR2, DPGEN_NOR3, DPGEN_NOR4, DPGEN_OR2, DPGEN_OR3, DPGEN_OR4, DPGEN_XNOR2, DPGEN_XOR2 ) : + index = LV_iLeafCell + LV_macroDrive + + elif LV_Function in ( DPGEN_NMUX2, DPGEN_NBUSE, DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : + index = LV_iLeafCell + 1 + + elif LV_Function in ( DPGEN_MUX2, DPGEN_BUSE ) : + index = LV_iLeafCell + ( LV_macroDrive * 2 ) + 1 # LV_macroDrive << 1 + + elif LV_Function in ( DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + index = LV_iLeafCell + 1 + LV_xl.getxlbit ( aiSlice ) + + elif LV_Function == DPGEN_CONST : + index = LV_iLeafCell + LV_xl.getxlbit ( aiSlice ) + + if ( index == ERROR_INDEX ) : return "bug_leaf" + + return LV_tsLeafCell[index] + +######################### +def get_Model_Buffer () : + global LV_Function + global LV_iLeafCell + global LV_tsLeafCell + global LV_macroDrive + + index = ERROR_INDEX + + if LV_Function in ( DPGEN_NMUX2, DPGEN_NBUSE, DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + index = LV_iLeafCell + + elif LV_Function in ( DPGEN_BUSE, DPGEN_MUX2 ) : + index = LV_iLeafCell + ( LV_macroDrive * 2 ) # LV_macroDrive << 1 + + if index == ERROR_INDEX : return "bug_buff" + + return LV_tsLeafCell[index] + + +################## +## DpgenRegular ## +################## +class DpgenRegular ( Model ) : + + ## Interface ## + ############### + def Interface ( self, LV_N, LV_Function ) : + + # Control terminals + if LV_Function in ( DPGEN_NMUX2, DPGEN_MUX2, DPGEN_NBUSE, DPGEN_BUSE, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + self._cmd = SignalIn ( "cmd", 1 ) + + if LV_Function in ( DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : + self._wen = SignalIn ( "wen", 1 ) + self._ck = SignalIn ( "ck", 1 ) + + if LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + self._scan = SignalIn ( "scan", 1 ) + self._scin = SignalIn ( "scin", 1 ) + + # Input data buses terminals + if LV_Function in ( DPGEN_OR4, DPGEN_NOR4, DPGEN_AND4, DPGEN_NAND4 ) : + self._i3 = SignalIn ( "i3", LV_N ) + self._i2 = SignalIn ( "i2", LV_N ) + self._i1 = SignalIn ( "i1", LV_N ) + self._i0 = SignalIn ( "i0", LV_N ) + + elif LV_Function in ( DPGEN_OR3, DPGEN_NOR3, DPGEN_AND3, DPGEN_NAND3 ) : + self._i2 = SignalIn ( "i2", LV_N ) + self._i1 = SignalIn ( "i1", LV_N ) + self._i0 = SignalIn ( "i0", LV_N ) + + elif LV_Function in ( DPGEN_MUX2, DPGEN_NMUX2, DPGEN_XOR2, DPGEN_XNOR2, DPGEN_OR2, DPGEN_NOR2, DPGEN_AND2, DPGEN_NAND2 ) : + self._i1 = SignalIn ( "i1", LV_N ) + self._i0 = SignalIn ( "i0", LV_N ) + + elif LV_Function in ( DPGEN_DFFT, DPGEN_DFF, DPGEN_SFFT, DPGEN_SFF, DPGEN_XNOR2MASK, DPGEN_NOR2MASK, DPGEN_NAND2MASK, DPGEN_BUSE, DPGEN_NBUSE, DPGEN_BUFF, DPGEN_INV ) : + self._i0 = SignalIn ( "i0", LV_N ) + + # Output data buses terminals + if LV_Function in ( DPGEN_CONST, DPGEN_MUX2, DPGEN_DFFT, DPGEN_DFF, DPGEN_SFFT, DPGEN_SFF, DPGEN_XOR2, DPGEN_OR4, DPGEN_OR3, DPGEN_OR2, DPGEN_AND4, DPGEN_AND3, DPGEN_AND2, DPGEN_BUFF ) : + self._q = SignalOut ( "q", LV_N ) + + elif LV_Function == DPGEN_BUSE: + self._q = TriState ( "q", LV_N ) + + elif LV_Function in ( DPGEN_INV, DPGEN_NAND2, DPGEN_NAND3, DPGEN_NAND4, DPGEN_NOR2, DPGEN_NOR3, DPGEN_NOR4, DPGEN_XNOR2, DPGEN_NMUX2, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + self._nq = SignalOut ( "nq", LV_N ) + + elif LV_Function == DPGEN_NBUSE: + self._nq = TriState ( "nq", LV_N ) + + # Power terminals + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self, LV_N, LV_Function, *val ) : + global LV_drive, LV_macroDrive, LV_xl + + # Initializes for the requested generator + init_Generator ( LV_Function ) + + LV_drive = 1 + LV_macroDrive = 0 + + # Parses the optionals arguments + if LV_Function in ( DPGEN_INV, DPGEN_BUFF, DPGEN_NAND2, DPGEN_NAND3, DPGEN_NAND4, DPGEN_AND2, DPGEN_AND3, DPGEN_AND4, DPGEN_NOR2, DPGEN_NOR3, DPGEN_NOR4, DPGEN_OR2, DPGEN_OR3, DPGEN_OR4, DPGEN_XNOR2, DPGEN_XOR2, DPGEN_MUX2, DPGEN_BUSE ) : + LV_drive = val[0] + + elif LV_Function in ( DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK, DPGEN_CONST ) : + LV_xl = newxl () + LV_xl.atoxl ( val[0] ) + temp1 = LV_xl.xltovhdl() + LV_xl._size = LV_N + temp2 = LV_xl.xltovhdl() + + if temp1 != temp2 : + print "[Stratus Warning] : Due to its wrong size, the constant", temp1, "has been modified to :", temp2, ". Check if it's the value one wanted." + + # Check the drive argument + for iDrive in range ( MAX_TDRIVE ) : + if ( LV_tDrive[iDrive] and ( LV_tDrive[iDrive] == LV_drive ) ) : + LV_macroDrive = iDrive + break + + if iDrive == MAX_TDRIVE - 1 : iDrive += 1 + + if iDrive >= MAX_TDRIVE : + raise "\n[Stratus ERROR] Dpgen : Invalid drive value %ld.\n" % LV_drive + + # Internal signals + if LV_Function in ( DPGEN_NBUSE, DPGEN_BUSE ) : + enx = Signal ( "enx", 1 ) + nenx = Signal ( "nenx", 1 ) + elif LV_Function in ( DPGEN_DFF, DPGEN_SFF ) : + ckx = Signal ( "ckx", 1 ) + nckx = Signal ( "nckx", 1 ) + wenx = Signal ( "wenx", 1 ) + nwenx = Signal ( "nwenx", 1 ) + elif LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + ckx = Signal ( "ckx", 1 ) + nckx = Signal ( "nckx", 1 ) + wenx = Signal ( "wenx", 1 ) + nwenx = Signal ( "nwenx", 1 ) + scanx = Signal ( "scanx", 1 ) + nscanx = Signal ( "nscanx", 1 ) + scoutx = Signal ( "scoutx", 1 ) + elif LV_Function in ( DPGEN_MUX2, DPGEN_NMUX2 ) : + sel0 = Signal ( "sel0", 1 ) + sel1 = Signal ( "sel1", 1 ) + elif LV_Function == DPGEN_NAND2MASK : + ncmd = Signal ( "ncmd", 1 ) + elif LV_Function in ( DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + for iSlice in range ( LV_N ) : + if LV_xl.getxlbit ( iSlice ) : + bcmd = Signal ( "bcmd", 1 ) + break + + + # Loop for all the data slices + self.Cell = {} + + for iSlice in range ( LV_N ) : + sModel = get_Model_Cell ( iSlice ) + + if LV_Function == DPGEN_INV : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_BUFF : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NAND2, DPGEN_NOR2, DPGEN_XNOR2 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_AND2, DPGEN_OR2, DPGEN_XOR2 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NAND3, DPGEN_NOR3 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'i2' : self._i2[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_AND3, DPGEN_OR3 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'i2' : self._i2[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NAND4, DPGEN_NOR4 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'i2' : self._i2[iSlice] + , 'i3' : self._i3[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_AND4, DPGEN_OR4 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i0' : self._i0[iSlice] + , 'i1' : self._i1[iSlice] + , 'i2' : self._i2[iSlice] + , 'i3' : self._i3[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_NMUX2 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'sel0' : sel0 + , 'sel1' : sel1 + , 'i1' : self._i1[iSlice] + , 'i0' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_MUX2 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'sel0' : sel0 + , 'sel1' : sel1 + , 'i1' : self._i1[iSlice] + , 'i0' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_NBUSE : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'enx' : enx + , 'nenx' : nenx + , 'i' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_BUSE : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'enx' : enx + , 'nenx' : nenx + , 'i' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_NAND2MASK : + if LV_xl.getxlbit ( iSlice ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i1' : ncmd + , 'i0' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + if LV_xl.getxlbit ( iSlice ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i1' : bcmd + , 'i0' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._i0[iSlice] + , 'nq' : self._nq[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function == DPGEN_CONST : + if LV_xl.getxlbit ( iSlice ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'nq' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif ( LV_Function == DPGEN_DFF ) or ( LV_Function == DPGEN_SFF ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'ckx' : ckx + , 'nckx' : nckx + , 'wenx' : wenx + , 'nwenx' : nwenx + , 'i' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + if iSlice == 0 : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'ckx' : ckx + , 'nckx' : nckx + , 'wenx' : wenx + , 'nwenx' : nwenx + , 'scanx' : scanx + , 'nscanx' : nscanx + , 'scin' : scoutx + , 'i' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + else : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'ckx' : ckx + , 'nckx' : nckx + , 'wenx' : wenx + , 'nwenx' : nwenx + , 'scanx' : scanx + , 'nscanx' : nscanx + , 'scin' : self._q[iSlice - 1] + , 'i' : self._i0[iSlice] + , 'q' : self._q[iSlice] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + iSlice += 1 # attention : difference entre les boucles en c et les boucles en python + + if has_Buffer ( LV_Function ) : + if iSlice % 2 : iSlice += 1 + + sModel = get_Model_Buffer () + + if LV_Function == DPGEN_NAND2MASK : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._cmd + , 'nq' : ncmd + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'i' : self._cmd + , 'q' : bcmd + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NMUX2, DPGEN_MUX2 ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'sel' : self._cmd + , 'sel0' : sel0 + , 'sel1' : sel1 + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_NBUSE, DPGEN_BUSE ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'en' : self._cmd + , 'nenx' : nenx + , 'enx' : enx + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_DFF, DPGEN_SFF ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'ck' : self._ck + , 'wen' : self._wen + , 'ckx' : ckx + , 'nckx' : nckx + , 'wenx' : wenx + , 'nwenx' : nwenx + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + elif LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + self.Cell[iSlice] = Inst ( sModel + , "cell_%ld" % iSlice + , map = { 'ck' : self._ck + , 'wen' : self._wen + , 'scan' : self._scan + , 'ckx' : ckx + , 'nckx' : nckx + , 'wenx' : wenx + , 'nwenx' : nwenx + , 'scanx' : scanx + , 'nscanx' : nscanx + , 'scin' : self._scin + , 'scout' : scoutx + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ## Layout ## + ############ + def Layout ( self, LV_N, LV_Function ) : + + # Loop for all the data slices + for iSlice in range ( LV_N ) : + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + iSlice += 1 # attention : difference entre les boucles en c et les boucles en python + + # Add the buffer cell + if has_Buffer ( LV_Function ) : + if iSlice % 2 : iSlice += 1 + + Place ( self.Cell[iSlice] + , slice_to_sym ( iSlice ) + , XY ( 0, slice_to_y ( iSlice ) ) + ) + + + ## VBE ## + ######### + def Vbe ( self, LV_N, LV_flags, LV_Function ) : + + global file + + fileName = self._name + ".vbe" + + file = open ( fileName, "w+" ) + + sBusWide = VHDL_BUS_WIDE ( LV_N - 1, 0, LV_N, LV_flags ) + + ## Entity Description ## + file.write ( "\nENTITY %s IS\n PORT (\n" % self._name ) + + ## Controls Terminals ## + if LV_Function in ( DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK, DPGEN_BUSE, DPGEN_NBUSE, DPGEN_MUX2, DPGEN_NMUX2 ) : + file.write ( "%14s : in BIT;\n" % "cmd") + + if LV_Function in ( DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : + file.write ( "%14s : in BIT;\n" % "wen" ) + file.write ( "%14s : in BIT;\n" % "ck" ) + + if LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + file.write ( "%14s : in BIT;\n" % "scan") + file.write ( "%14s : in BIT;\n" % "scin") + + ## Input data buses terminals ## + if LV_Function in ( DPGEN_NAND4, DPGEN_AND4, DPGEN_NOR4, DPGEN_OR4 ) : + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i3", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i2", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i1", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide ) ) + + elif LV_Function in (DPGEN_NAND3, DPGEN_OR3, DPGEN_AND3, DPGEN_NOR3 ) : + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i2", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i1", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide ) ) + + elif LV_Function in ( DPGEN_NAND2, DPGEN_AND2, DPGEN_NOR2, DPGEN_OR2, DPGEN_XNOR2, DPGEN_XOR2, DPGEN_NMUX2, DPGEN_MUX2 ) : + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i1", sBusWide ) ) + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide ) ) + + elif LV_Function in ( DPGEN_INV, DPGEN_BUFF, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK, DPGEN_NBUSE, DPGEN_BUSE, DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : + file.write ( "%14s : in BIT_VECTOR %s;\n" % ( "i0", sBusWide ) ) + + ## Output data buses terminals ## + if LV_Function in ( DPGEN_NAND4, DPGEN_NOR4, DPGEN_NAND3, DPGEN_NOR3, DPGEN_NAND2, DPGEN_NOR2, DPGEN_XNOR2, DPGEN_NMUX2, DPGEN_INV, DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : + file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "nq", sBusWide ) ) + + elif LV_Function == DPGEN_NBUSE : + file.write ( "%14s : out MUX_VECTOR %s BUS;\n" % ( "nq", sBusWide ) ) + + elif LV_Function in ( DPGEN_AND2, DPGEN_AND3, DPGEN_AND4, DPGEN_OR2, DPGEN_OR3, DPGEN_OR4, DPGEN_XOR2, DPGEN_MUX2, DPGEN_BUFF, DPGEN_CONST, DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : + file.write ( "%14s : out BIT_VECTOR %s;\n" % ( "q", sBusWide ) ) + + elif LV_Function == DPGEN_BUSE : + file.write ( "%14s : out MUX_VECTOR %s BUS;\n" % ( "q", sBusWide ) ) + + ## Power supplies terminals ## + file.write ( "%14s : in BIT;\n" % "vdd") + file.write ( "%14s : in BIT\n" % "vss") + + ## End of entity description ## + file.write ( " );\nEND %s;\n\n\n" % self._name ) + + ## Architecture description ## + file.write ( "ARCHITECTURE VBE OF %s IS\n\n" % self._name ) + + ## Signals ## + if LV_Function in ( DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK, DPGEN_NMUX2 ) : + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "q", sBusWide ) ) + + elif LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "d_test", sBusWide ) ) + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "d_wen", sBusWide ) ) + file.write ( " SIGNAL %20s : REG_VECTOR %s REGISTER;\n" % ( "ff", sBusWide ) ) + + elif LV_Function in ( DPGEN_DFF, DPGEN_SFF ) : + file.write ( " SIGNAL %20s : BIT_VECTOR %s;\n" % ( "d_wen", sBusWide ) ) + file.write ( " SIGNAL %20s : REG_VECTOR %s REGISTER;\n" % ( "ff", sBusWide ) ) + + ## Behavior ## + file.write ( "\nBEGIN\n\n" ) + + if LV_Function in ( DPGEN_NAND4, DPGEN_AND4, DPGEN_NOR4, DPGEN_OR4, DPGEN_NAND3, DPGEN_OR3, DPGEN_AND3, DPGEN_NOR3, DPGEN_NAND2, DPGEN_AND2, DPGEN_NOR2, DPGEN_OR2, DPGEN_XNOR2, DPGEN_XOR2, DPGEN_INV, DPGEN_BUFF ) : self.VHDL_boolean ( LV_Function ) + + elif LV_Function in ( DPGEN_NAND2MASK, DPGEN_NOR2MASK, DPGEN_XNOR2MASK ) : self.VHDL_mask ( LV_Function ) + + elif LV_Function in ( DPGEN_NMUX2, DPGEN_MUX2 ) : self.VHDL_mux ( LV_Function ) + + elif LV_Function in ( DPGEN_BUSE, DPGEN_NBUSE ) : self.VHDL_buse ( LV_Function ) + + elif LV_Function == DPGEN_CONST : self.VHDL_const () + + elif LV_Function in ( DPGEN_DFF, DPGEN_DFFT, DPGEN_SFF, DPGEN_SFFT ) : self.VHDL_ff ( LV_Function, LV_N, LV_flags ) + + ## Assert ## + file.write ( " ASSERT (vdd = '1')\n" ) + file.write ( " REPORT \"Power supply is missing on vdd of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + file.write ( " ASSERT (vss = '0')\n" ) + file.write ( " REPORT \"Power supply is missing on vss of Model %s.\"\n" % self._name ) + file.write ( " SEVERITY WARNING;\n\n" ) + + ## End of behavioral view ## + file.write ( "END VBE;\n" ) + + file.close () + + + ## VHDL_boolean ## + ################## + def VHDL_boolean ( self, LV_Function ) : + global file + + if LV_Function == DPGEN_INV : file.write ( " nq <= not i0;\n\n" ) + elif LV_Function == DPGEN_BUFF : file.write ( " q <= i0;\n\n" ) + elif LV_Function == DPGEN_NAND2 : file.write ( " nq <= not (i0 and i1);\n\n" ) + elif LV_Function == DPGEN_AND2 : file.write ( " q <= (i0 and i1);\n\n" ) + elif LV_Function == DPGEN_NOR2 : file.write ( " nq <= not (i0 or i1);\n\n" ) + elif LV_Function == DPGEN_OR2 : file.write ( " q <= (i0 or i1);\n\n" ) + elif LV_Function == DPGEN_XNOR2 : file.write ( " nq <= not (i0 xor i1);\n\n" ) + elif LV_Function == DPGEN_XOR2 : file.write ( " q <= (i0 xor i1);\n\n" ) + elif LV_Function == DPGEN_NOR3 : file.write ( " nq <= not (i0 or i1 or i2);\n\n" ) + elif LV_Function == DPGEN_OR3 : file.write ( " q <= (i0 or i1 or i2);\n\n" ) + elif LV_Function == DPGEN_NAND3 : file.write ( " nq <= not (i0 and i1 and i2);\n\n" ) + elif LV_Function == DPGEN_AND3 : file.write ( " q <= (i0 and i1 and i2);\n\n" ) + elif LV_Function == DPGEN_NAND4 : file.write ( " nq <= not (i0 and i1 and i2 and i3);\n\n" ) + elif LV_Function == DPGEN_AND4 : file.write ( " q <= (i0 and i1 and i2 and i3);\n\n" ) + elif LV_Function == DPGEN_NOR4 : file.write ( " nq <= not (i0 or i1 or i2 or i3);\n\n" ) + elif LV_Function == DPGEN_OR4 : file.write ( " q <= (i0 or i1 or i2 or i3);\n\n" ) + + ## VHDL_mask ## + ############### + def VHDL_mask ( self, LV_Function ) : + global LV_xl + + global file + + file.write ( " WITH cmd SELECT\n" ) + file.write ( " q <= i0 WHEN \'0\',\n" ) + + if LV_Function == DPGEN_NAND2MASK : + file.write ( " (i0 and %s) WHEN \'1\';\n" % LV_xl.xltovhdl ( ) ) + + elif LV_Function == DPGEN_NOR2MASK : + file.write ( " (i0 or %s) WHEN \'1\';\n" % LV_xl.xltovhdl ( ) ) + + elif LV_Function == DPGEN_XNOR2MASK : + file.write ( " (i0 xor %s) WHEN \'1\';\n" % LV_xl.xltovhdl ( ) ) + + file.write ( "\n nq <= not q;\n\n" ) + + ## VHDL_const ## + ################ + def VHDL_const ( self ) : + global LV_xl + + global file + + file.write ( " q <= %s;\n\n" % LV_xl.xltovhdl ( ) ) + + ## VHDL_mux ## + ############## + def VHDL_mux ( self, LV_Function ) : + + global file + + if LV_Function in ( DPGEN_NMUX2, DPGEN_MUX2 ) : + file.write ( " WITH cmd SELECT\n" ) + file.write ( " q <= i0 WHEN \'0\',\n" ) + file.write ( " i1 WHEN \'1\';\n" ) + + if LV_Function == DPGEN_NMUX2 : + file.write ( "\n nq <= not q;\n" ) + + file.write ( "\n" ) + + ## VHDL_buse ## + ############### + def VHDL_buse ( self, LV_Function ) : + + global file + + file.write ( " label_buse:BLOCK(cmd = '1')\n" ) + file.write ( " BEGIN\n" ) + + if LV_Function == DPGEN_NBUSE : + file.write ( " nq <= GUARDED not i0;\n" ) + + elif LV_Function == DPGEN_BUSE : + file.write ( " q <= GUARDED i0;\n" ) + + file.write ( " END BLOCK label_buse;\n\n" ) + + ## VHDL_ff () ## + ################ + def VHDL_ff ( self, LV_Function, LV_N, LV_flags ) : + + global file + + sBusWide = VHDL_BUS_WIDE ( LV_N - 2, 0, LV_N, LV_flags ) + + dwrite = "d_wen" + + if LV_Function in ( DPGEN_DFFT, DPGEN_SFFT ) : + file.write ( " WITH scan SELECT\n" ) + file.write ( " d_test <= d_wen WHEN \'0\',\n" ) + file.write ( " q %s & scin WHEN \'1\';\n\n" % sBusWide ) + + dwrite = "d_test"; + + file.write ( " WITH wen SELECT\n" ) + file.write ( " d_wen <= q WHEN \'0\',\n" ) + file.write ( " i0 WHEN \'1\';\n\n" ) + + + elif LV_Function in ( DPGEN_DFF, DPGEN_SFF ) : + file.write ( " WITH wen SELECT\n" ) + file.write ( " d_wen <= q WHEN \'0\',\n" ) + file.write ( " i0 WHEN \'1\';\n\n" ) + + + file.write ( " label_ff:BLOCK ((ck and not (ck'STABLE)) = \'1\')\n" ) + file.write ( " BEGIN\n" ) + file.write ( " ff <= GUARDED %s;\n" % dwrite ) + file.write ( " END BLOCK label_ff;\n\n" ) + + file.write ( " q <= ff;\n\n" ) + + +########################################################################## + +## AND2 ## +class DpgenAnd2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_AND2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_AND2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_AND2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_AND2 ) + +## AND3 ## +class DpgenAnd3 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_AND3 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_AND3, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_AND3 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_AND3 ) + +## AND4 ## +class DpgenAnd4 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_AND4 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_AND4, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_AND4) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_AND4 ) + +## BUFF ## +class DpgenBuff ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_BUFF ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_BUFF, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_BUFF ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self,self._param['nbit'], self._param['flags'], DPGEN_BUFF ) + +## BUSE ## +class DpgenBuse ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 4 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_BUSE ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_BUSE, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_BUSE ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_BUSE ) + +## CONST ## +class DpgenConst ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_CONST ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_CONST, self._param['const'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_CONST ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_CONST ) + +## DFF ## +class DpgenDff ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_DFF ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_DFF, 0 ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_DFF ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_DFF ) + +## DFFT ## +class DpgenDfft ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_DFFT ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_DFFT, 0 ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_DFFT ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_DFFT ) + +## INV ## +class DpgenInv ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_INV ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_INV, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_INV ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_INV ) + +## MUX2 ## +class DpgenMux2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_MUX2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_MUX2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_MUX2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_MUX2 ) + +## NAND2 ## +class DpgenNand2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NAND2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NAND2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NAND2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NAND2 ) + +## NAND2MASK ## +class DpgenNand2mask ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NAND2MASK ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NAND2MASK, self._param['const'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NAND2MASK ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NAND2MASK ) + +## NAND3 ## +class DpgenNand3 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NAND3 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NAND3, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NAND3 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NAND3 ) + +## NAND4 ## +class DpgenNand4 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NAND4 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NAND4, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NAND4 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NAND4 ) + +## NBUSE ## +class DpgenNbuse ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NBUSE ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NBUSE ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NBUSE ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NBUSE ) + +## NMUX2 ## +class DpgenNmux2 ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NMUX2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NMUX2 ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NMUX2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NMUX2 ) + +## NOR2 ## +class DpgenNor2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NOR2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NOR2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NOR2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NOR2 ) + +## NOR2MASK ## +class DpgenNor2mask ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NOR2MASK ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NOR2MASK, self._param['const'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NOR2MASK ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NOR2MASK ) + +## NOR3 ## +class DpgenNor3 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NOR3 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NOR3, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NOR3 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NOR3 ) + +## NOR4 ## +class DpgenNor4 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_NOR4 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_NOR4, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_NOR4 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_NOR4 ) + +## OR2 ## +class DpgenOr2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_OR2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_OR2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_OR2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_OR2 ) + +## OR3 ## +class DpgenOr3 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_OR3 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_OR3, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_OR3 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_OR3 ) + +## OR4 ## +class DpgenOr4 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 2 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_OR4 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_OR4, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_OR4 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_OR4 ) + +## SFF ## +class DpgenSff ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_SFF ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_SFF, 0 ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_SFF ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_SFF ) + +## SFFT ## +class DpgenSfft ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_SFFT ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_SFFT, 0 ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_SFFT ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_SFFT ) + +## XNOR2 ## +class DpgenXnor2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_XNOR2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_XNOR2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_XNOR2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_XNOR2 ) + +## XNOR2MASK ## +class DpgenXnor2mask ( DpgenRegular ) : + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_XNOR2MASK ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_XNOR2MASK, self._param['const'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_XNOR2MASK ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_XNOR2MASK ) + +## XOR2 ## +class DpgenXor2 ( DpgenRegular ) : + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + if 'drive' not in param : self._param['drive'] = 1 + + def Interface ( self ) : + DpgenRegular.Interface ( self, self._param['nbit'], DPGEN_XOR2 ) + + def Netlist ( self ) : + DpgenRegular.Netlist ( self, self._param['nbit'], DPGEN_XOR2, self._param['drive'] ) + + def Layout ( self ) : + DpgenRegular.Layout ( self, self._param['nbit'], DPGEN_XOR2 ) + + def Vbe ( self ) : + DpgenRegular.Vbe ( self, self._param['nbit'], self._param['flags'], DPGEN_XOR2 ) diff --git a/stratus1/src/dpgen/dpgen_Shifter.py b/stratus1/src/dpgen/dpgen_Shifter.py new file mode 100644 index 00000000..709b5293 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_Shifter.py @@ -0,0 +1,263 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_Shifter.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenShifter ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + global Slices + global BitIndex + + self._nbit = self._param['nbit'] + + Slices = ln2p ( self._nbit ) + + self._op = SignalIn ( "op", 2 ) + self._shamt = SignalIn ( "shamt", Slices ) + + self._i = SignalIn ( "i", self._nbit ) + + self._o = SignalOut ( "o", self._nbit ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self ) : + global SliceIndex + + AndIndex = 0 + + # Signals + MuxOutput = Signal ( "muxoutput", self._nbit * Slices + self._nbit ) + + c0 = Signal ( "c0", Slices ) + c1 = Signal ( "c1", Slices ) + + msb = Signal ( "msb", 1 ) + + + # Arithmetic or input extension + self.A0 = Inst ( "a2_x2" + , "a_0" + , map = { 'i0' : self._i[self._nbit-1] + , 'i1' : self._op[1] + , 'q' : msb + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + + # Normalizing the input signals names + for BitIndex in range ( self._nbit ) : self._i[BitIndex].Alias ( MuxOutput[BitIndex] ) + + self.M = {} + + # Connecting the mux matrix + for SliceIndex in range ( Slices ) : + for BitIndex in range ( self._nbit ) : + + LeftIndex = BitIndex - ( 1 << SliceIndex ) + RightIndex = BitIndex + ( 1 << SliceIndex ) + + if LeftIndex >= 0 : + if RightIndex < self._nbit : + self.M[SliceIndex*self._nbit+BitIndex] = Inst ( "mx3_x2" + , "m_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'cmd0' : c0[SliceIndex] + , 'cmd1' : c1[SliceIndex] + , 'i0' : MuxOutput[SliceIndex * self._nbit + LeftIndex] + , 'i1' : MuxOutput[SliceIndex * self._nbit + BitIndex] + , 'i2' : MuxOutput[SliceIndex * self._nbit + RightIndex] + , 'q' : MuxOutput[( SliceIndex + 1 ) * self._nbit + BitIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + else : + self.M[SliceIndex*self._nbit+BitIndex] = Inst ( "mx3_x2" + , "m_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'cmd0' : c0[SliceIndex] + , 'cmd1' : c1[SliceIndex] + , 'i0' : MuxOutput[SliceIndex * self._nbit + LeftIndex] + , 'i1' : MuxOutput[SliceIndex * self._nbit + BitIndex] + , 'i2' : msb + , 'q' : MuxOutput[( SliceIndex + 1 ) * self._nbit + BitIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + else : + if RightIndex < self._nbit : + self.M[SliceIndex*self._nbit+BitIndex] = Inst ( "mx3_x2" + , "m_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'cmd0' : c0[SliceIndex] + , 'cmd1' : c1[SliceIndex] + , 'i0' : self._op[0] + , 'i1' : MuxOutput[SliceIndex * self._nbit + BitIndex] + , 'i2' : MuxOutput[SliceIndex * self._nbit + RightIndex] + , 'q' : MuxOutput[( SliceIndex + 1 ) * self._nbit + BitIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + else : + self.M[SliceIndex*self._nbit+BitIndex] = Inst ( "mx3_x2" + , "m_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'cmd0' : c0[SliceIndex] + , 'cmd1' : c1[SliceIndex] + , 'i0' : self._op[0] + , 'i1' : MuxOutput[SliceIndex * self._nbit + BitIndex] + , 'i2' : msb + , 'q' : MuxOutput[( SliceIndex + 1 ) * self._nbit + BitIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + # Normalizing the output signals names + for BitIndex in range ( self._nbit ) : self._o[BitIndex] <= MuxOutput[Slices * self._nbit + BitIndex] + + # Building the control signals + if self._nbit < 16 : Model = "inv_x2" + elif self._nbit < 32 : Model = "inv_x4" + else : Model = "inv_x8" + + self.I = {} + self.O = {} + + for SliceIndex in range ( Slices ) : + self.I[SliceIndex] = Inst ( Model + , "i_%d" % SliceIndex + , map = { 'i' : self._shamt[SliceIndex] + , 'nq' : c1[SliceIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + self.O[SliceIndex] = Inst ( "o2_x2" + , "o_%d" % SliceIndex + , map = { 'i0' : c1[SliceIndex] + , 'i1' : self._op[0] + , 'q' : c0[SliceIndex] + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + + ########## Layout ########## + ############################ + def Layout ( self ) : + global SliceIndex + global BitIndex + + Slices = ln2p ( self._nbit ) + + if self._nbit & 1 : + sym = SYM_Y + mys = NOSYM + else : + sym = NOSYM + mys = SYM_Y + + BitIndex = self._nbit - 1 + SliceIndex = 0 + + Place ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + , XY ( 0, 0 ) + ) + + for SliceIndex in range ( 1, Slices ) : + PlaceRight ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + for SliceIndex in range ( Slices ) : + SetRefIns ( self.M[SliceIndex * self._nbit + self._nbit - 1] ) + + for BitIndex in range ( self._nbit - 2, -1, -1 ) : + PlaceBottom ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + + BitIndex = self._nbit # Upper line, this is necessary for the computation of the symetry + SliceIndex = 0 + + SetRefIns ( self.M[SliceIndex * self._nbit + self._nbit - 1] ) + + PlaceTop ( self.A0 + , SYM ( BitIndex, sym, mys ) + ) + + for SliceIndex in range ( Slices ) : + if SliceIndex == 0 : SetRefIns ( self.A0 ) + + + PlaceRight ( self.I[SliceIndex] + , SYM ( BitIndex, sym, mys ) + ) + + PlaceRight ( self.O[SliceIndex] + , SYM ( BitIndex, sym, mys ) + ) + + ## VBE ## + ######### + def Vbe ( self ) : + print "vbe of DpgenShifter not implemented" diff --git a/stratus1/src/dpgen/dpgen_Shrot.py b/stratus1/src/dpgen/dpgen_Shrot.py new file mode 100644 index 00000000..4b0b6050 --- /dev/null +++ b/stratus1/src/dpgen/dpgen_Shrot.py @@ -0,0 +1,343 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./dpgen_Shrot.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class DpgenShrot ( Model ) : + + ## Interface ## + ############### + def Interface ( self ) : + global Slices + global AndIndex + + self._nbit = self._param['nbit'] + + Slices = ln2p ( self._nbit ) + + self._op = SignalIn ( "op", 3 ) + self._shamt = SignalIn ( "shamt", Slices ) + + self._i = SignalIn ( "i", self._nbit ) + self._o = SignalOut ( "o", self._nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + + ## Netlist ## + ############# + def Netlist ( self ) : + global Slices + + AndIndex = 0 + + # Signals + MuxOutput = Signal ( "muxoutput", self._nbit * Slices + self._nbit ) + + c0 = Signal ( "c0", Slices ) + c1 = Signal ( "c1", Slices ) + + msb = Signal ( "msb", 1 ) + op2b = Signal ( "op2b", 1 ) + + x = Signal ( "x", Slices * self._nbit ) + + MuxInput0 = Signal ( "muxinput0" ) + MuxInput2 = Signal ( "muxinput2" ) + + self.I = {} + self.A3 = {} + self.A = {} + self.OA = {} + self.O = {} + self.M = {} + self.Tie = {} + + + # Arithmetic or input extension + self.I[Slices] = Inst ( "inv_x2" + , "i_%d" % Slices + , map = { 'i' : self._op[2] + , 'nq' : op2b + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.A3[Slices] = Inst ( "a3_x2" + , "a3_%d" % Slices + , map = { 'i0' : self._i[self._nbit-1] + , 'i1' : op2b + , 'i2' : self._op[1] + , 'q' : msb + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + # Normalizing the input signals names + for BitIndex in range ( self._nbit ) : self._i[BitIndex].Alias ( MuxOutput[BitIndex] ) + + # Connecting the mux matrix + for SliceIndex in range ( Slices ) : + for BitIndex in range ( self._nbit ) : + + LeftIndex = BitIndex - ( 1 << SliceIndex ) + RightIndex = BitIndex + ( 1 << SliceIndex ) + + if LeftIndex >= 0 : +# MuxOutput[SliceIndex * self._nbit + LeftIndex].Alias ( MuxInput0 ) + MuxInput0 = MuxOutput[SliceIndex * self._nbit + LeftIndex] + else : +# x[AndIndex].Alias ( MuxInput0 ) + MuxInput0 = x[AndIndex] + + self.A[SliceIndex*self._nbit+BitIndex]= Inst ( "a2_x2" + , "a_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'i0' : self._op[2] + , 'i1' : MuxOutput[SliceIndex * self._nbit + self._nbit + LeftIndex] + , 'q' : x[AndIndex] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + AndIndex += 1 + + if RightIndex < self._nbit: +# MuxOutput[SliceIndex * self._nbit + RightIndex].Alias ( MuxInput2 ) + MuxInput2 = MuxOutput[SliceIndex * self._nbit + RightIndex] + else : +# x[AndIndex].Alias ( MuxInput2 ) + MuxInput2 = x[AndIndex] + + self.OA[SliceIndex*self._nbit+BitIndex] = Inst ( "oa22_x4" + , "oa_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'i0' : self._op[2] + , 'i1' : MuxOutput[SliceIndex * self._nbit + RightIndex - self._nbit] + , 'i2' : msb + , 'q' : x[AndIndex] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + AndIndex += 1 + + self.M[SliceIndex*self._nbit+BitIndex] = Inst ( "mx3_x2" + , "m_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'cmd0' : c0[SliceIndex] + , 'cmd1' : c1[SliceIndex] + , 'i0' : MuxInput0 + , 'i1' : MuxOutput[SliceIndex * self._nbit + BitIndex] + , 'i2' : MuxInput2 + , 'q' : MuxOutput[( SliceIndex + 1 ) * self._nbit + BitIndex] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + # Normalizing the output signals names + for BitIndex in range ( self._nbit ) : + MuxOutput[Slices * self._nbit + BitIndex]._temp = 1 + self._o[BitIndex] <= MuxOutput[Slices * self._nbit + BitIndex] + + # Building the control signals + for SliceIndex in range ( Slices ) : + self.I[SliceIndex] = Inst ( "inv_x2" + , "i_%d" % SliceIndex + , map = { 'i' : self._shamt[SliceIndex] + , 'nq' : c1[SliceIndex] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + self.O[SliceIndex]= Inst ( "o2_x2" + , "o_%d" % SliceIndex + , map = { 'i0' : c1[SliceIndex] + , 'i1' : self._op[0] + , 'q' : c0[SliceIndex] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + for SliceIndex in range ( Slices ) : + for BitIndex in range ( self._nbit - 1, -1, -1 ) : + l = 0 + r = 0 + LeftIndex = BitIndex - ( 1 << SliceIndex ) + RightIndex = BitIndex + ( 1 << SliceIndex ) + + if RightIndex >= self._nbit : r = 1 + if LeftIndex < 0 : l = 1 + + if l == 0 and r == 0 : + self.Tie[SliceIndex*self._nbit+BitIndex] = Inst ( "tie_x0" + , "tie_%d" % ( SliceIndex * self._nbit + BitIndex ) + , map = { 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + + ########## Layout ########## + ############################ + def Layout ( self ) : + + Slices = ln2p ( self._nbit ) + + if self._nbit & 1 : + sym = SYM_Y + mys = NOSYM + else : + sym = NOSYM + mys = SYM_Y + + BitIndex = self._nbit - 1 + SliceIndex = 0 + + Place ( self.OA[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + , XY ( 0, 0 ) + ) + PlaceRight ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + for SliceIndex in range ( 1, Slices ) : + PlaceRight ( self.OA[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + PlaceRight ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + for SliceIndex in range ( Slices ) : + SetXYIns ( self.OA[SliceIndex * self._nbit + self._nbit - 1] ) + + for BitIndex in range ( self._nbit - 1, -1, -1 ) : + l = 0 + r = 0 + LeftIndex = BitIndex - ( 1 << SliceIndex ) + RightIndex = BitIndex + ( 1 << SliceIndex ) + + if RightIndex >= self._nbit : + if BitIndex != ( self._nbit - 1 ) : + PlaceBottom ( self.OA[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + r = 1 + + if LeftIndex < 0 : + if r == 1 : + PlaceRight ( self.A[SliceIndex * self._nbit + BitIndex ] + , SYM ( BitIndex, sym, mys ) + ) + SetXYIns ( self.OA[SliceIndex * self._nbit + BitIndex] ) + + else : + PlaceBottom ( self.A[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + l = 1 + + if l == 0 and r == 0 : + PlaceBottom ( self.Tie[SliceIndex * self._nbit + BitIndex] + , NOSYM + ) + + SetRefIns ( self.M[SliceIndex * self._nbit + self._nbit - 1] ) + + for BitIndex in range ( self._nbit - 2, -1, -1 ) : + PlaceBottom ( self.M[SliceIndex * self._nbit + BitIndex] + , SYM ( BitIndex, sym, mys ) + ) + + + BitIndex = self._nbit # Upper line, this is necessary for the computation of the symetry + SliceIndex = 0 + + SetRefIns ( self.OA[SliceIndex * self._nbit + self._nbit - 1] ) + + PlaceTop ( self.I[Slices] + , SYM ( BitIndex, sym, mys ) + ) + PlaceRight ( self.A3[Slices] + , SYM ( BitIndex, sym, mys ) + ) + + for SliceIndex in range ( Slices ) : + if SliceIndex > 0 : + SetRefIns ( self.OA[SliceIndex * self._nbit + self._nbit - 1] ) + + if SliceIndex == 0: + PlaceRight ( self.I[SliceIndex] + , SYM ( BitIndex, sym, mys ) + ) + else : + PlaceTop ( self.I[SliceIndex] + , SYM ( BitIndex, sym, mys ) + ) + + PlaceRight ( self.O[SliceIndex] + , SYM ( BitIndex, sym, mys ) + ) + + ## VBE ## + ######### + def Vbe ( self ) : + print "vbe of DpgenShrot not implemented" diff --git a/stratus1/src/lib/fulladder.vst b/stratus1/src/lib/fulladder.vst new file mode 100644 index 00000000..c01a1ef0 --- /dev/null +++ b/stratus1/src/lib/fulladder.vst @@ -0,0 +1,102 @@ +-- This file is part of the Coriolis Project. +-- Copyright (C) Laboratoire LIP6 - Departement ASIM +-- Universite Pierre et Marie Curie +-- +-- Main contributors : +-- Christophe Alexandre +-- Sophie Belloeil +-- Hugo Clement +-- Jean-Paul Chaput +-- Damien Dupuis +-- Christian Masson +-- Marek Sroka +-- +-- The Coriolis Project is free software; you can redistribute it +-- and/or modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 of +-- the License, or (at your option) any later version. +-- +-- The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +-- USA +-- +-- License-Tag +-- Authors-Tag +-- =================================================================== +-- +-- x-----------------------------------------------------------------x +-- | | +-- | C O R I O L I S | +-- | S t r a t u s - Netlists Description | +-- | | +-- | Author : Sophie BELLOEIL | +-- | E-mail : Sophie.Belloeil@asim.lip6.fr | +-- | =============================================================== | +-- | Vst Module : "./fulladder.vst" | +-- | *************************************************************** | +-- | U p d a t e s | +-- | | +-- x-----------------------------------------------------------------x + + +entity fulladder is + port ( + a : in bit; + b : in bit; + cin : in bit; + sout : out bit; + cout : out bit; + vdd : in bit; + vss : in bit + ); +end fulladder; + +architecture structural of fulladder is +component fulladder_x2 + port ( + a1 : in bit; + a2 : in bit; + a3 : in bit; + a4 : in bit; + b1 : in bit; + b2 : in bit; + b3 : in bit; + b4 : in bit; + cin1 : in bit; + cin2 : in bit; + cin3 : in bit; + sout : out bit; + cout : out bit; + vdd : in bit; + vss : in bit + ); +end component; + +begin + +cell : fulladder_x2 + port map ( + a1 => a, + a2 => a, + a3 => a, + a4 => a, + b1 => b, + b2 => b, + b3 => b, + b4 => b, + cin1 => cin, + cin2 => cin, + cin3 => cin, + sout => sout, + cout => cout, + vdd => vdd, + vss => vss + ); + +end structural; diff --git a/stratus1/src/modules/CMakeLists.txt b/stratus1/src/modules/CMakeLists.txt new file mode 100644 index 00000000..fbd5d3b8 --- /dev/null +++ b/stratus1/src/modules/CMakeLists.txt @@ -0,0 +1,2 @@ + + add_subdirectory ( patterns ) diff --git a/stratus1/src/modules/patterns/CMakeLists.txt b/stratus1/src/modules/patterns/CMakeLists.txt new file mode 100644 index 00000000..874a7182 --- /dev/null +++ b/stratus1/src/modules/patterns/CMakeLists.txt @@ -0,0 +1,9 @@ + + set ( pysources ${CMAKE_CURRENT_SOURCE_DIR}/patread.py + ${CMAKE_CURRENT_SOURCE_DIR}/patterns.py + ${CMAKE_CURRENT_SOURCE_DIR}/patwrite.py + ${CMAKE_CURRENT_SOURCE_DIR}/synopsys.py + ${CMAKE_CURRENT_SOURCE_DIR}/utils.py + ) + + install ( FILES ${pysources} DESTINATION ${PYTHON_SITE_PACKAGES}/stratus ) diff --git a/stratus1/src/modules/patterns/Makefile.am b/stratus1/src/modules/patterns/Makefile.am new file mode 100644 index 00000000..ab049f29 --- /dev/null +++ b/stratus1/src/modules/patterns/Makefile.am @@ -0,0 +1,8 @@ + + patternsdir = $(pkgpyexecdir) + + patterns_PYTHON = patterns.py \ + patread.py \ + patwrite.py \ + synopsys.py \ + utils.py diff --git a/stratus1/src/modules/patterns/patread.py b/stratus1/src/modules/patterns/patread.py new file mode 100644 index 00000000..c305c83a --- /dev/null +++ b/stratus1/src/modules/patterns/patread.py @@ -0,0 +1,203 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Ludovic NOURY | +# | E-mail : Ludovic.Noury@lip6.fr | +# | =============================================================== | +# | Py Module : "./stratus.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +# $Id: patread.py,v 1.1 2007/07/20 13:30:15 cobell Exp $ +# LIP6/ASIM ludovic.noury@lip6.fr +__all__ = ['PatRead'] + +from stratus import * + +## Read a pattern file and analyze it +# +# This class is designed to load and analyze output result test +# vectors from simulation. Currently it only supports Alliance ".pat" +# format. +# +# @remark we suppose that the source vector was created by a PatWrite +# instance (See PatWrite documentation). +# @todo also get time unit (with first pattern) +# @todo add code for '?uuuu' and 'uuuu' +# @todo replace compile regexps +# @version $Id: patread.py,v 1.1 2007/07/20 13:30:15 cobell Exp $ +class PatRead: + # Public attributes doxydoc ---------------------------- + ## @var connectors + # store input/output connectors order. + + ## @var connectors_current_values + # dictionary, key=connector_name + + ## @var current_time + # current pattern time stamp + + # Private attributes ----------------------------------- + ## @var _f + # file object linked to the output file. + ## @var _p + # Shortcut to the regular expression used to split strings + + # ------------------------------------------------------ + ## The constructor + # + # Open the pattern file, initialize instance attributes and call + # _get_interface method. + # + # @param filename Pattern to load & analyze filename + def __init__(self, filename): + # Init instance attributes + self.connectors = [] + self.connectors_current_values = {} + self.current_time = 0 + self._p=re.compile(r'\W+') + + # Open input file + self._f = open(filename, 'r') + + # Get interface + self._get_interface() + + # Regular expressions + + # used to dermine if a value can be used + self._re_valid = re.compile('[XxUu]') + + # ------------------------------------------------------ + ## Extract interface from input pattern file + # + # Read the input pattern until the line with "begin" indicating + # interface declaration end. + # For each connector (or internal signal) extracts direction, name + # and arity. + # + # @remark arity extraction suppose N+1 downto 0 declaration form + # and 'B' option. Ok, if pattern generated by PatWrite instance. + # + # @remark For signal, the direction is set to the value 'signal' + def _get_interface(self): + # Shortcuts to regexps + re_in=re.compile("^in") + re_out=re.compile("^out") + re_signal=re.compile("^signal") + + # Extract connectors data from file until "begin" line. + for line in self._f: + # Remove leading spaces + line = line.lstrip() + + # Stop if end of interface + if re.compile("^begin").search(line): + break + # Connector + if (re_in.search(line) or re_out.search(line) or re_signal.search(line)): + pieces = self._p.split(line) + connector = {} + connector['direction'] = pieces[0] + connector['name'] = pieces[1] + # (arity>1) => vector + # '' is to pass synopsys output pattern bug : + # in ck ;; instead of + # in ck B;; gives pieces[2] == '' instead of 'B' + if (pieces[2] != 'B') and (pieces[2] != ''): + connector['arity'] = int(pieces[2])-int(pieces[4])+1 + else: + connector['arity'] = 1 + #DEBUG: print '%s=>%s\n' % (line, connector) + self.connectors.append(connector) + + # ------------------------------------------------------ + ## Update current_time and connectors_current_values with next + # pattern values. + # + # @return Return True if a pattern has been loaded. Else return + # False. + # @todo call end method if end of patterns ? + def get_next_pattern(self): + for line in self._f: + # Stop if end of patterns + if re.compile("^end").search(line): + return False + # Special case, only one pattern + if re.compile("\s*:").match(line): + pieces = self._p.split(line) + # Update time + self.current_time = 0 + # Update connectors values dictionary + for pos in range(len(self.connectors)): + name = self.connectors[pos]['name'] + self.connectors_current_values[name] = pieces[pos+1] + return True + # We got a pattern + if re.compile("^<").search(line): + pieces = self._p.split(line) + # Update time + self.current_time = int(pieces[1]) + # Update connectors values dictionary + for pos in range(len(self.connectors)): + name = self.connectors[pos]['name'] + self.connectors_current_values[name] = pieces[pos+3] + return True + + + # ---------------------------------------------------------------- + ## Return true if the value is either X or U. + # + # @param signal signal name (string). + # @return True is the signal is invalid. + # + # Before trying to convert a value we need to be sure it's a valid + # value. + def is_invalid(self, signal): + # match is not ok because we wouldn't find partial invalid as '01XXX' + return self._re_valid.search(self.connectors_current_values[signal]) + + + + + # ---------------------------------------------------------------- + def __del__(self): + self._f.close() diff --git a/stratus1/src/modules/patterns/patterns.py b/stratus1/src/modules/patterns/patterns.py new file mode 100644 index 00000000..6e0e39b0 --- /dev/null +++ b/stratus1/src/modules/patterns/patterns.py @@ -0,0 +1,86 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Ludovic NOURY | +# | E-mail : Ludovic.Noury@lip6.fr | +# | =============================================================== | +# | Py Module : "./__init__.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +# $Id: patterns.py,v 1.1 2007/07/20 13:30:16 cobell Exp $ +# LIP6/ASIM ludovic.noury@lip6.fr + +## @package patterns +# Package : regroups pattern analyzis and generation Stratus modules +# +# - PatRead module (class: patterns.patread.PatRead) +# - PatWrite module (class: patterns.patwrite.PatWrite) +# - Synopsys link module (class: patterns.synopsys.Synopsys) +# - \ref patterns_utils module (conversion fonctions and LoadSig class) +# (also see exemple section) +# - \ref patfloat module (all need for generating floating-point patterns) + +from patread import * +from patwrite import * +from utils import * +from synopsys import * + +## \example test_patterns.py +# +# This is a simple example of how to use the patterns package. +# +# To use it you need to add the to $PYTHONPATH the directory where +# "patterns" is. Exemple (if you run directly from the example dir add +# : export PYTHONPATH=../../:$PYTHONPATH) + +## \example test_patterns_fixed.py +# +# This is an example of how to use the patterns package with fixed +# point data. It's also a good exemple of PatRead class usage. +# +# To use it you need to add the to $PYTHONPATH the directory where +# "patterns" is. Exemple (if you run directly from the example dir add +# : export PYTHONPATH=../../:$PYTHONPATH) + +## \example adder.py +# +# Complete example of Synopsys class usage diff --git a/stratus1/src/modules/patterns/patwrite.py b/stratus1/src/modules/patterns/patwrite.py new file mode 100644 index 00000000..c4d5c521 --- /dev/null +++ b/stratus1/src/modules/patterns/patwrite.py @@ -0,0 +1,683 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Ludovic NOURY | +# | Roselyne CHOTIN-AVOT | +# | E-mail : Ludovic.Noury@lip6.fr | +# | =============================================================== | +# | Py Module : "./__init__.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +# $Id: patwrite.py,v 1.6 2009/02/10 09:38:18 roselyne Exp $ +# Author: LIP6/ASIM ludovic.noury@lip6.fr +# Contributor: Roselyne.Chotin-Avot@lip6.fr +__all__ =['PatWrite'] + +from stratus import * +from utils import * +from math import ceil + +## Create new patterns +# +# This class is used to create patterns for Stratus models. Currently +# it only supports Alliance ".pat" pattern format. +# +# Patterns time stamps are in the "absolute date" format, "relative +# date" isn't allowed. Legal time unit are ps, ns, us and ms. Default +# is ps. +# +# @remark we suppose output pattern files won't be read by a +# human. So to simplify the implementation we don't provide +# hexadecimal or octal representation for signal values. All the +# signals values are written in binary. +# +# @todo add another constructor with time interval as parameter. +# @todo add checks. +# @todo add another constructor and variable to select time unit. +# @todo add automatic vdd/vss declaration and affect. (?) +# @todo modify declar() to be able to declar "name",arity,type +# +# @version $Id: patwrite.py,v 1.6 2009/02/10 09:38:18 roselyne Exp $ +class PatWrite: + + # Public attributes doxydoc ---------------------------- + ## @var connectors_list + # store input/output connectors order + + ## @var connectors_current_values + # dictionary, key=connector_name + + ## @var self.connectors_format + # dictionary, key=connector_name, value=connector format + + ## @var current_time + # auto-incremented after addpat() + + ## @var time_interval + # time interval + + ## @var time_unit + # time unit, valid values are ps, ns, us and ms. + + # Private attributes ----------------------------------- + ## @var _f + # file object linked to the output file + + ## @var _finished + # true if the pattern file has been written and closed. Used by + # the destructor. + + ## @var _cell + # Reference to the input Stratus cell. Used to be able to use + # design net by theirs string name. Value 0 indicates that the + # reference is unknown. + + # ------------------------------------------------------ + ## The constructor + # @param filename New pattern output filename (example: \c adder.pat). + # @param cell Optional, reference to Stratus cell. + def __init__(self, filename, cell=None): + # Instance attributes declaration + self._f = open(filename, 'w') + self._finished = False + self.connectors_list = [] + self.connectors_current_values = {} + self.connectors_format = {} + self.current_time = 0 + self.time_interval = 10 + self.time_unit = 'ns' + self._cell = cell + + + # ------------------------------------------------------ + ## The destructor + # + # Call pattern_end if it hasn't been called yet. + def __del__(self): + if self._finished == False: + self.pattern_end() + + # ------------------------------------------------------ + ## Get direction string from a net + # + # @param net Stratus net + # + # @remark: if InOut we default to out + # @todo add inout mode, but we can't select automagically in or out ! + # @todo add code for all modes (ask sophie) + def _get_direction(self, net): + return {'st_net.SignalIn' : 'in', + 'st_net.SignalOut' : 'out', + 'st_net.Signal' : 'out', + 'st_net.VddIn' : 'in', + 'st_net.VssIn' : 'in', + 'st_net.CkIn' : 'in', + 'st_net.Signal' : 'signal', + 'st_net.TriState' : 'out', + 'st_net.SignalInOut': 'out' + }[str(net.__class__)] + + #'st_net.SignalInOut': in ou out selon le voeux de util' + #'st_net.SignalUnknown': je sais pas quoi faire + #'st_net.TriState' : je sais pas quoi faire + # VddInFromHur, VssInFromHur, Signal_virtuel + + + # ------------------------------------------------------ + # Predicate, true of the connector is an output + # @remark: considers that SignalInOut is an output + # + # @param self object reference + # @param connector Stratus connector + def _is_output(self, connector): + return ((str(connector.__class__ ) == "st_net.SignalOut") or + (str(connector.__class__ ) == "st_net.SignalInOut")) + + # ------------------------------------------------------ + ## Adds a connector from a Stratus model to the pattern interface. + # + # Writes the corresponding connector declaration in the pattern + # file with name, arity and direction automatically extracted from + # the connector properties. + # + # Also adds the connector to \e connectors_list. It is used when + # add patterns to respect the connectors order. + # + # Supported Stratus connectors are: + # - SignalIn, + # - SignalOut (only supported if used as an output), + # - VddIn, + # - VssIn, + # - CkIn, + # - SignalInOut, + # - TriState (always an output), + # - Signals. + # + # @param connector Can either be a reference to a stratus net or a + # string containing the name of the stratus net. + # + # @param format Optional format for the connectors values into the + # pattern file, accepted values are : + # - 'B': binary (default), + # - 'X': hexadecimal, + # - 'O': octal. + # + # @remark if the connector arity is greater than 1 it will always + # be written in the form N downto 0. + # + # @remark if the connector arity is 1 the format is set 'B' even if + # the format parameter is set to another value. + # + # @remark To be able to use a string as connector parameter the + # constructor must have been given a reference to the net. + # + # @warning string connector don't seem to work for vdd/vss + # + # @todo add exception when string command and self._cell unset + # @todo add exception when string command signal not found + def declar(self, connector, format='B'): + + # 1. Check connector type: + # - if stratus net, then nothing to do + # - if string name, then search for a net with this name + from types import StringType + if type(connector) is StringType: + for net in self._cell._st_sigs: + if (net._name == connector): + connector_ref = net + else: + connector_ref = connector + + # 2.write declaration to output file + # 2.a write connector direction + self._f.write(self._get_direction(connector_ref).rjust(5) + + " " + connector_ref._name) + # 2.b write: "N downto 0" if necessary + if(connector_ref._arity != 1): + self._f.write(" (" + str(connector_ref._arity-1) + " downto 0)") + + # 2.c write format + if ((format == 'B') or (connector_ref._arity == 1)): + self._f.write(" B;;\n") + elif format == 'X': + self._f.write(" X;;\n") + elif format == 'O': + self._f.write(" O;;\n") + + # 3. add connector to list (we need an ordered connectors lists) + self.connectors_list.append(connector_ref._name) + self.connectors_format[connector_ref._name] = format + + # 4. if output connector or signal set value to any + if ((self._get_direction(connector_ref) == 'out') or + (self._get_direction(connector_ref) == 'signal')): + self.affect_any(connector_ref) + + # ------------------------------------------------------ + ## Subcomponents internal signals declaration + # + # Imported vst signals aren't in the database. Hence we can't + # easily import data. So the designer has to set all the parameter + # with this command to allow pattern check of subcomponents + # internal signals values. + # + # @param self object reference + # @param signame string with the full signal name eg: + # instance0_modpmfs8_fsm.chip_ep + # @param msb signal msb, default value 0 + # @param lsb signal lsb, default value 0 + # @param format optional, default value B, repport + # declar_interface documentation + def declar_subsig(self, signame, msb=0, lsb=0, format='B'): + self.connectors_list.append(signame) + self.connectors_format[signame] = format + + if msb == lsb : + self._f.write('signal %s %s;;\n' % \ + (signame, format)) + else: + self._f.write('signal %s (%d downto %d) %s;;\n' % \ + (signame, msb, lsb, format)) + + # create output value + any_str = '' + arity = msb-lsb+1 + if format == 'B': + any_str += arity*'*' + elif format == 'O': + any_str += int(ceil(arity/3.))*'*' + elif format == 'X': + any_str += int(ceil(arity/4.))*'*' + + # Update connectors values dictionary + self.connectors_current_values[signame] = any_str + + + + # ------------------------------------------------------ + ## Adds all the connectors from a Stratus model to the pattern + # interface. + # + # Write the corresponding connector declaration in the pattern + # file with name, arity and direction directly taken from the + # connector proprieties. + # + # Also add the connector to the connectors_list. The connector + # list is used to store the connectors order. It's used later when + # we'll write the patterns. + # + # @remark Declarare in the following order: clock, input, output, + # vdd, vss. The fixed connector order is a constraint for Synopsys + # testbench generation. + # + # @remark The only supported connectors are instance of SignalIn, + # SignalOut, VddIn, VssIn and CkIn. + # + # @remark If the connector arity is greater than 1 it will always + # be written in the form N downto 0. + # + # @param self The object pointer + # @param cell The tested Stratus model reference. Optional if a + # reference to the tested Stratus model was given during + # instanciation (patterns.patwrite.PatWrite.__init__ cell parameter). + # @param format Optional format for the connectors values into the + # pattern file, accepted values are : + # - 'B': binary (default), + # - 'X': hexadecimal, + # - 'O': octal. + # + # @remark if the conector arity is 1 the format is 'B' + # @todo use get_interface simplify + def declar_interface(self, cell=None, format='B'): + # + if (cell==None): + if self._cell == None: + raise Exception("PatWrite.declar_interface() " + "cell reference no given during PatWrite instanciation," + " thus the cell parameter is mandatory.") + else: + cell = self._cell + + # 1. Clocks + for port in cell._st_cks: + if isinstance(port, CkIn): + self.declar(port, format) + + # 2. Inputs + for port in cell._st_ports: + if isinstance(port, SignalIn): + self.declar(port, format) + + # 3. Outputs + for port in cell._st_ports: + if isinstance(port, SignalOut): + self.declar(port, format) + + # 4. VDDs + for port in cell._st_vdds: + if isinstance(port, VddIn): + self.declar(port, format) + + # 5. VSSs + for port in cell._st_vsss: + if isinstance(port, VssIn): + self.declar(port, format) + + # 6. TriState + for port in cell._st_ports: + if isinstance(port, TriState): + self.declar(port, format) + + ## Return interface connectors dictionnary where key is the conector's name + # and value the connector's format ('B' or 'X' or 'O') + # + # @param name is the tested Stratus model reference name + # @return connectors dictionnary + def get_interface_format(self, name): + file = open(name+'.pat', 'r') + dict = {} + for line in file : + # stop at end of the declaration + if re.compile(r"^begin$", re.I).search(line): + break; + # skip blank line + if re.compile(r"^ *$", re.I).search(line): + continue + # get name and format + res = re.search("[in|out]+ *(\w*).*([X|B|O]) *;*",line).group(1,2) + dict[res[0]] = res[1] + file.close() + return dict + + + ## Return interface connectors list + # + # Construct an ordered connectors list corresponding to + # declare_interface() order. + # + # @param cell tested Stratus model reference. Optional if a + # reference to the tested Stratus model was given during + # instanciation (patterns.patwrite.PatWrite.__init__ cell parameter). + # @return connectors list + def get_interface(self, cell=None): + l = [] + + if (cell==None): + if self._cell == None: + raise Exception("PatWrite.get_interface() " + "cell reference no given during PatWrite instanciation," + " thus the cell parameter is mandatory.") + else: + cell = self._cell + + # 1. Clocks + for port in cell._st_cks: + if isinstance(port, CkIn): + port._format = self.connectors_format[port._name] + l.append(port) + + # 2. Inputs + for port in cell._st_ports: + if isinstance(port, SignalIn): + port._format = self.connectors_format[port._name] + l.append(port) + + # 3. Outputs + for port in cell._st_ports: + if isinstance(port, SignalOut): + port._format = self.connectors_format[port._name] + l.append(port) + + # 4. VDDs + for port in cell._st_vdds: + if isinstance(port, VddIn): + port._format = self.connectors_format[port._name] + l.append(port) + + # 5. VSSs + for port in cell._st_vsss: + if isinstance(port, VssIn): + port._format = self.connectors_format[port._name] + l.append(port) + + return l + + + # ------------------------------------------------------ + ## Affect a string value to a connector + # + # Update the connectors_current_values dictionary with value. + # + # @param connector Stratus connector + # @param value String to affect to connector + def affect(self, connector, value): + self.connectors_current_values[connector._name] = value + + # ------------------------------------------------------ + ## Affect an integer (CA2) value to a connector + # + # Convert the 2's complement value to the corresponding binary + # value. The binary size is taken from the connector arity. Then, + # update the connectors_current_values dictionary with the + # computed binary value. + # + # If the connector is an output, the binary value is preceded by + # "?". + # + # @param connector Stratus connector. + # @param value 2's complement value to affect to the connector. + # @todo add code for octal format and execption ... + def affect_int(self, connector, value): + # Test if the connector is a connector + if str(connector.__class__ ) not in ( "st_net.SignalIn", "st_net.SignalOut", "st_net.SignalInOut", "st_net.SignalUnknown", "st_net.TriState", "st_net.VddIn", "st_net.VssIn", "st_net.CkIn" ) : + raise Exception("PatWrite.affect_int() the first argument must be an external net.") + + # 1.Test if output connector + if self._is_output(connector): + tmp = "?" + else: + tmp ="" + + # 2. Get connector format + format = self.connectors_format[connector._name] + + # 3. Create output string + if format == 'B': + tmp += int2str(value, connector._arity) + elif format == 'O': + pass + elif format == 'X': + tmp += int2strhex(value, connector._arity) + + # 4. Update connector value + self.connectors_current_values[connector._name] = tmp + + + + # ------------------------------------------------------ + ## Affect a fixed point value to a connector. + # + # Convert the floating point input value to the corresponding + # fixed point value with word_length=connector.arity() and + # integer_word_length=iwl. + # + # If the connector is an output, the binary value is preceded by + # "?". + # + # @param connector Stratus connector. + # @param value floating point value to convert and asign to connector. + # @param iwl integer word length + def affect_fix(self, connector, value, iwl): + # 1.Test if output connector + if self._is_output(connector): + tmp = "?" + else: + tmp ="" + + # 2.Finish to compute binary string and update connectors + # values dictionary. + self.connectors_current_values[connector._name] = \ + tmp+float2strfix(value, connector._arity, iwl) + + # ------------------------------------------------------ + ## Disable comparison between this connector value and the one + # calculated during simulation. + # + # @param connector Stratus connector. + # + # @remark We systematicaly write the optional "?" mark before the + # "*" symbols. This is to allow the Synopsys module generated + # testbench to correctly detect output values. With this all the + # output values are begin with "?". + # + # @todo add exception if unknown type + def affect_any(self, connector): + # search connector format + format = self.connectors_format[connector._name] + + # create output value + any_str = '?' + if format == 'B': + any_str += connector._arity*'*' + elif format == 'O': + any_str += int(ceil(connector._arity/3.))*'*' + elif format == 'X': + any_str += int(ceil(connector._arity/4.))*'*' + + + # Update connectors values dictionary + self.connectors_current_values[connector._name] = any_str + + + + # ------------------------------------------------------ + ## Adds a pattern + # + # Add the pattern with @e current_time time and + # @e connectors_current_values values. Then increment + # @e current_time by @e time_interval. + def addpat(self): + # write time and comment + self._f.write("< " + str(self.current_time).rjust(10) + + " " + self.time_unit + ">" + " : ") + # write connectors values + for connector in self.connectors_list: + if connector not in self.connectors_current_values : + raise Exception("PatWrite.addpat() : connector %s is missing." % connector) + self._f.write(self.connectors_current_values[connector] + " ") + # end pattern + self._f.write(";\n") + + # increment time for next pattern + self.current_time += self.time_interval + + # ------------------------------------------------------ + ## Mark the end of the interface declaration and the beginning of + # the test vectors. + def pattern_begin(self): + self._f.write("\nbegin\n\n") + + # ------------------------------------------------------ + ## Mark the end of the test vectors and of the patterns file. + def pattern_end(self): + self._f.write("\nend;\n") + self._f.close() + self._finished = True + + + # ------------------------------------------------------ + ## Automatically create the pattern values for arithmetic function + # of 2 inputs + # + # @param cell is the tested Stratus model + # @param val_mask is the value of the MaskNumber + # @param function is the arithmetic function to test defined as a python lambda + # function of (a,b) operands (ex: function = lambda a,b : a+b) + # @param mode is the mode for the patterns : + # - 'zd' : zero delay simulation + # - 'delay' : the current pattern affects the inputs and the next the output + # - 'dense delay' : the current pattern affects the inputs and the output of the last pattern + # + # @remark this function can be used only if the cell's ports are : + # - i0 corresponding to the 1st operand signal + # - i1 corresponding to the 2nd operand signal + # - o corresponding to the output signal + # - cin corresponding to the input carry signal (optionnal) + # - cout corresponding to the output carry signal (optionnal) + def pat_function(self, cell, val_mask, function, mode = 'zd'): + res = res_cout = None + if 'cin' not in cell._param : cin = False + else : cin = param['cin'] + if 'cout' not in cell._param : cout = False + else : cout = param['cout'] + + # extends the sign of a given value from width1 to width2 + def extend(val,width): + if val >= 2**(width-1): + mask = ~(2**width-1) + return (val | mask) + else: + return val + # cout calculation + def cout_cal(valA,valB,valCin): + mask = 2**cell._nbit - 1 + val = (valA & mask) + (valB & mask) + valCin + if val >= 2**cell._nbit: + return 1 + else: + return 0 + + # Affectation + self.affect_int(cell._st_vdds[0], 1) + self.affect_int(cell._st_vsss[0], 0) + # use of a MaskNumber value of val_mask for the 2 input + valuesA = MaskNumber(cell.i0._arity,val_mask) + for valA in valuesA: + valuesB = MaskNumber(cell.i1._arity,val_mask) + for valB in valuesB: + self.affect_int(cell.i0,valA) + self.affect_int(cell.i1,valB) + # take account of sign extension + if cell._signed : + valAe = extend(valA,cell.i0._arity) + valBe = extend(valB,cell.i1._arity) + else: + valAe = valA + valBe = valB + if cin: + for valCin in (0,1): + self.affect_int(cell.cin,valCin) + # the output is affected with the parameter function + res_old = res + res = function(valAe,valBe)+valCin + res_cout_old = res_cout + res_cout = cout_cal(valAe,valBe,valCin) + if mode == 'zd' : + self.affect_int(cell.o,res) + if cout: + self.affect_int(cell.cout,res_cout) + elif mode == 'delay' : + self.affect_any(cell.o) + if cout: + self.affect_any(cell.cout) + self.addpat() + self.affect_int(cell.o,res) + if cout: + self.affect_int(cell.cout,res_cout) + elif mode == 'dense delay' : + if res_old == None : + self.affect_any(cell.o) + else: + self.affect_int(cell.o,res_old) + if cout: + if res_cout_old == None : + self.affect_any(cell.cout) + else: + self.affect_int(cell.cout,res_cout_old) + self.addpat() + else: + # the output is affected with the parameter function + res = function(valAe,valBe) + self.affect_int(cell.o,res) + if cout: + self.affect_int(cell.cout,cout_cal(valA,valB,0)) + self.addpat() diff --git a/stratus1/src/modules/patterns/synopsys.py b/stratus1/src/modules/patterns/synopsys.py new file mode 100644 index 00000000..c7499c34 --- /dev/null +++ b/stratus1/src/modules/patterns/synopsys.py @@ -0,0 +1,867 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Ludovic NOURY | +# | Roselyne CHOTIN-AVOT | +# | E-mail : Ludovic.Noury@lip6.fr | +# | =============================================================== | +# | Py Module : "./__init__.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +# ---------------------------------------------------------------------------- +# $Id: synopsys.py,v 1.6 2008/11/26 15:19:11 roselyne Exp $ +# Author: LIP6/ASIM ludovic.noury@lip6.fr +# Contributor: Roselyne.Chotin-Avot@lip6.fr +# ---------------------------------------------------------------------------- +import os +import re +from tempfile import TemporaryFile + +from stratus import * + + +# ---------------------------------------------------------------------------- +## Everything to simulate with Synopsys +# +# - export design to VHDL. +# - create testbench and run blocks +# - Synopsys compilaltion +# - Synopsys simulation +# +# See complete example into the example section +# +# @remark ".pat" connectors order is important, the call to patWrite +# instance to get it. +# +# @remark Currently all values must be in binary in the ".pat". +# +# @remark This is a first draft. This class should be edited a lot and +# maybe merged (or dervived from) with patwrite +# +# @todo signal errors to output pat like asimut does +# @todo separate debug to (verbose and debug) +# @bug description bloc copy to res has some missing caracters. Hack +# adds missing ';' ... +class Synopsys: + + # @var self._cell cell + + # ------------------------------------------------------------- + ## Constructor + # @var cell reference to Stratus design cell + def __init__(self, cell): + self._cell = cell + self._name = cell._name + + # ------------------------------------------------------------- + ## Convert the VST netlist to VHDL + # + # Uses VASY to convert from VST to VHDL, then remove VDD/VSS from + # resulting VHD files. Optionaly rename fd1qll cells input clock + # from 'ck' to 'cp' (st option). + # + # raise Exception if error + # @param debug debug mode (default=False) + # @param st must be set to True if we use ST CORE9GP standard cells + # @bug as the function is generic and don't depend on synopsys it + # should be defined somewhere else. (But it depends on VASY) + def convert_to_vhdl(self, debug=False, st=False): + # Convert to VHDL + if debug: + print('VST to VHDL conversion ---------------' + '--------------------------------------\n' + ' - VASY (%s) ...'% self._name) + if os.system('vasy -o -V -S -I vst -H %s %s 1> %s_vasy.log' % + (self._name, self._name, self._name)): + raise Exception('VASY error (see "%s_vasy.log")'% self._name) + vhdl = re.compile(r'\.vhd$') + + # Remove VDD/VSS and change CK to ST name + if debug and st: + print(' - remove vdd/vss connectors declarations and change registers\n' + ' input connector name (ST mode) ...') + elif debug: + print(' - remove vdd/vss connectors declarations ...') + + for filename in os.listdir('./'): + if vhdl.search(filename): + self._remove_power(filename, False) # false for no debug + if st: + self._change_ck2st(filename, False) # false for no debug + + if debug: + print ' - VHDL conversion done.' + + # ------------------------------------------------------------- + ## Remove power supply connectors from a VHDL file. + # + # Overwrite input file. + # + # @param filename VHDL input file name. + # @param debug debug mode (default False). + # @bug if instances names have vdd/vss in !!! + def _remove_power(self, filename, debug=False): + # STEP1: remove vdd/vss ------------------------------------- + input = open(filename, 'r') + temp = TemporaryFile('w+') + alim = re.compile('.*(vdd|vss)+.*', re.IGNORECASE) + removed = 0 + + for line in input: + if not alim.search(line): + temp.write(line) + else: + removed += 1 + + if debug: + print ' - removed %d power supply declarations'%removed + + input.close() + + # STEP2: remove ";\n)" and ",\n)" syntax errors ------------- + temp.seek(0) + + out = open(filename, 'w') + + comma = re.compile('.*\w+.*(;|,)') + close = re.compile('^\s*\);') + corrige = re.compile('(;|,)') + corrected = 0 + + previous = temp.next() + for current in temp: + if close.search(current) and comma.search(previous): + out.write(corrige.sub('', previous)) + corrected += 1 + else: + out.write(previous) + previous = current + out.write(previous) + + if debug: + print ' - corrected %s syntax errors'%corrected + + # END ------------------------------------------------------- + temp.close() + input.close() + out.close() + + # ------------------------------------------------------------- + ## Correct clocks names for ST CORE9GP fd1qll cells + # + # Change 'ck' connector name to 'cp'. Overwrite input file + # + # @param filename VHDL input filename. + # @param debug Debug mode (default=False) + def _change_ck2st(self, filename, debug=False): + # STEP1: change CKs ----------------------------------------- + input = open(filename, 'r') + temp = TemporaryFile('w+') + + alim = re.compile('.*(vdd|vss)+.*', re.IGNORECASE) + changed = 0 + + reg_declare = re.compile('COMPONENT fd1qll') + reg_inst = re.compile(': fd1qll') + reg_aff = re.compile('ck =>') + + for line in input: + if reg_declare.search(line): + temp.write(line) + temp.write(input.next()) + temp.write(' cp : IN STD_LOGIC;\n') + input.next() + changed += 1 + elif reg_inst.search(line): + temp.write(line) + temp.write(input.next()) + line = input.next() + temp.write(reg_aff.sub('cp =>', line)) + changed += 1 + else: + temp.write(line) + + if debug: + print ' - changed %d ck'%changed + + # STEP2: write changes to input file ------------------------ + temp.seek(0) + input.close() + input = open(filename, 'w') + for line in temp: + input.write(line) + + # END ------------------------------------------------------- + input.close() + temp.close() + + # ------------------------------------------------------------- + def create_testbench(self, interface, delay, unit, debug=False, downto=False, logic=False): + name = self._cell._name + '_tb' + outfilename = self._cell._name + '_res.pat' + infilename = self._cell._name + '.pat' + tb = open('%s_tb.vhd'%self._cell._name, 'w') + + if debug: + print('Testbench module ---------------------' + '--------------------------------------\n' + ' - module name : %s.vhd\n' + ' - patterns input : %s\n' + ' - patterns output: %s' + % (name, infilename, outfilename)) + + # Libraries --------------------------------------------------- + tb.write('library ieee;\n' + 'use ieee.std_logic_1164.all;\n' + 'use ieee.std_logic_textio.all;\n' + 'use std.textio.all;\n\n') + + # Entity ------------------------------------------------------ + # Declar input, outputs and clocks. No support inout yet. + tb.write('entity %s IS\n\n' + ' port (\n' % name) + for signal in self._cell._st_ports: + # SignalIn + if isinstance(signal, SignalIn): + tb.write(' %s : out std_logic' % signal._name) + # SignalOut + elif isinstance(signal, SignalOut): + tb.write(' %s : in std_logic' % signal._name) + # SignalInOut (unsupported) + elif isinstance(signal, SignalInOut): + raise Exception('unsupported connector (SignalInOut: %s)' % signal._name) + # Skip to next if not a IO + else: + continue + # Bit vectors + if signal._arity != 1: + if downto : + tb.write('_vector(%d downto 0)'% (signal._arity-1)) + else: + tb.write('_vector(0 to %d)'% (signal._arity-1)) + tb.write(';\n') + + # CkIn + for signal in self._cell._st_cks: + tb.write(' %s : out std_logic;\n' % signal._name) + + # Remove last ';' + tb.seek(-2,1) + tb.write(');\n\n' + 'end %s;\n\n' % name) + + # Architecture ------------------------------------------------ + tb.write('architecture rtl of %s is\n\n' % name) + + # Procedures + tb.write(' -- Skip whitespaces\n' + ' procedure skip_spaces(l :inout line) is\n' + ' variable c : character;\n' + ' begin\n' + ' loop\n' + " if l(1) = ' ' then\n" + ' read(l, c);\n' + ' else\n' + ' exit;\n' + ' end if;\n' + ' end loop;\n' + ' end skip_spaces;\n\n') + + tb.write(' -- Skip asterisks\n' + ' procedure skip_asterisks(l :inout line) is\n' + ' variable c : character;\n' + ' begin\n' + ' loop\n' + " if l(1) = '*' then\n" + ' read(l, c);\n' + ' else\n' + ' exit;\n' + ' end if;\n' + ' end loop;\n' + ' end skip_asterisks;\n\n') + + tb.write(' -- Check for end of declaration block\n' + ' procedure is_begin(l : inout LINE; declaration_block : inout boolean) is\n' + ' begin\n' + " if l(1)='b' and l(2)='e' and l(3)='g' and l(4)='i' and l(5)='n' then\n" + ' declaration_block := false;\n' + ' end if;\n' + ' end is_begin;\n\n') + + + tb.write(' -- change end_pat to true if end detected\n' + ' procedure is_end (l : inout line; end_pat : inout boolean) is\n' + ' begin\n' + " if l(1)='e' and l(2)='n' and l(3)='d' and l(4)=';' then\n" + ' end_pat := true;\n' + ' end if;\n' + ' end is_end;\n\n') + + + + tb.write('begin -- rtl\n\n') + + # Variables + tb.write(' process\n' + ' -- VARIABLES\n' + ' variable l : line; -- input line\n' + ' variable lout : line; -- output line\n' + ' variable ldebug : line; -- termial output line\n' + ' variable empty_line : line;\n' + ' variable declaration_block : boolean := true;\n' + ' variable end_of_patterns : boolean := false;\n' + ' variable char : character;\n' + ' file TTY_OUTPUT: TEXT open WRITE_MODE is "STD_OUTPUT";\n' + ) + + tb.write(' -- INPUT PATTERNS VARIABLES\n') + in_list = [] + for c in interface: + if isinstance(c, SignalIn) or isinstance(c, CkIn): + in_list.append(c) + if (c._format == 'X') and (c._arity % 4 != 0) and (c._arity != 1): + tb.write(' variable v_%s_ext: std_logic' % c._name) + if downto : + tb.write('_vector(%d downto 0)'% (c._arity-1 + (4 - c._arity % 4))) + else: + tb.write('_vector(0 to %d)'% (c._arity-1) + (4 - c._arity % 4)) + tb.write(';\n') + tb.write(' variable v_%s: std_logic' % c._name) + if c._arity != 1: + if downto : + tb.write('_vector(%d downto 0)'% (c._arity-1)) + else: + tb.write('_vector(0 to %d)'% (c._arity-1)) + tb.write(';\n') + + tb.write(' -- OUTPUT PATTERNS VARIABLES\n') + out_list = [] + for c in interface: + if isinstance(c, SignalOut): + out_list.append(c) + if (c._format == 'X') and (c._arity % 4 != 0) and (c._arity != 1): + tb.write(' variable vpat_%s_ext: std_logic' % c._name) + if downto : + tb.write('_vector(%d downto 0)'% (c._arity-1 + (4 - c._arity % 4))) + else: + tb.write('_vector(0 to %d)'% (c._arity-1) + (4 - c._arity % 4)) + tb.write(';\n') + tb.write(' variable vpat_%s: std_logic' % c._name) + if c._arity != 1: + if downto: + tb.write('_vector(%d downto 0)'% (c._arity-1)) + else: + tb.write('_vector(0 to %d)'% (c._arity-1)) + tb.write(';\n') + if (c._format == 'X') and (c._arity % 4 != 0): + tb.write(' variable v_%s_ext: std_logic' % c._name) + if c._arity != 1: + if downto : + tb.write('_vector(%d downto 0)'% (c._arity-1 + (4 - c._arity % 4))) + else: + tb.write('_vector(0 to %d)'% (c._arity-1) + (4 - c._arity % 4)) + tb.write(';\n') + tb.write(' variable v_%s : std_logic' % c._name) + if c._arity != 1: + if downto: + tb.write('_vector(%d downto 0)'% (c._arity-1)) + else: + tb.write('_vector(0 to %d)'% (c._arity-1)) + tb.write(';\n') + + + tb.write(' -- FILES\n' + ' file outfile : TEXT is OUT "%s"; -- input patterns\n' + ' file infile : TEXT is IN "%s"; -- output patterns\n' % + (outfilename, infilename)) + tb.write(' begin -- process\n') + tb.write(' write(empty_line, string\'(""));') + # Write header to pat + tb.write(' -- Write Header\n' + ' write(l, string\'("-- Synopsys VHDL simulation results"));\n' + ' writeline(outfile, empty_line);\n\n') + # MAIN LOOP + tb.write(' -- main loop\n' + ' while not endfile(infile) loop\n' + ' readline(infile, l);\n') + # Comments and empty lines + tb.write(' ---------------------------------------------------------\n' + ' -- Comments and empty lines\n' + ' ---------------------------------------------------------\n' + ' -- skip empty lines\n' + ' if L\'length = 0 then\n' + ' writeline(outfile, empty_line);\n' + ' next;\n' + ' end if;\n\n' + + " -- Skip '--' comments\n" + " if (l(1) = '-') and (l(2) = '-') then\n" + ' next;\n' + ' end if;\n\n' + + " -- Copy '#' comments to output file\n" + " if l(1) = '#' then\n" + ' writeline(outfile, l);\n' + ' next;\n' + ' end if;\n') + # Declaration block + tb.write(' ---------------------------------------------------------\n' + ' -- Declaration block\n' + ' ---------------------------------------------------------\n' + ' skip_spaces(l);\n' + ' if declaration_block then\n' + ' -- Check for end of declaration block and copy to output\n' + ' is_begin(l, declaration_block);\n' + ' -- Ugly hack : add mysteriously missing ending ";;"\n' + ' if declaration_block then\n' + ' write(l, string\'(";;"));\n' + ' end if;\n' + ' writeline(outfile, l);\n' + ) + + # Description block + # - time + tb.write(' ---------------------------------------------------------\n' + ' -- Description block\n' + ' ---------------------------------------------------------\n' + " elsif l(1) = '<' then -- lines begin with <\n" + " -- we don't copy time, instead we use simulation time\n" + ' read(l, char);\n' + " while char /= '>' loop\n" + ' read(l,char);\n' + ' end loop;\n' + ' write(lout, string\'("< "));\n' + ' write(lout, now);\n' + ' write(lout, string\'(" >"));\n\n' + + ' -- Copy label to outfile\n' + ' read(l, char);\n' + " while char /= ':' loop\n" + ' write(lout, char);\n' + ' read(l,char);\n' + ' end loop;\n' + ' write(lout, char);\n' + " write(lout, character'(' '));\n\n") + # - read pattern values and affect them netlist + tb.write(' -- read inputs values from connectors and write them to output\n') + for c in in_list: + n = c._name + hex='' + ext='' + if ((c._format == 'X') and (c._arity > 1)): + hex = 'h' + if (c._arity % 4) != 0: + ext = '_ext' + #else: + # hex = '' + tb.write(' -- %s\n' + ' skip_spaces(l);\n' + ' %sread(l, v_%s%s);\n' + ' %swrite(lout, v_%s%s);\n' + " write(lout, ' ');\n" % (n, hex, n, ext, hex, n, ext)) + tb.write(' %s <= ' % n) + + if c._arity == 1: + tb.write('v_%s;' % n) + else: + for b in range(c._arity-1, -1, -1): + tb.write('v_%s%s(%d)&' % (n, ext, b)) + tb.seek(-1,1) + tb.write('; -- to respect order in .pat\n') + + + # - get output connectors values and write them to outfile + # - delay beetween input and output + if logic : + tb.write('\n -- delay\n' + ' wait for %d %s;\n\n' % (delay, unit)) + tb.write('\n -- get output connectors values and write them to outfile\n') + for c in out_list: + n = c._name + hex='' + ext='' + if ((c._format == 'X') and (c._arity > 1)): + hex = 'h' + if (c._arity % 4) != 0: + ext = '_ext' + #else: + # hex = '' + tb.write(' -- %s\n' + ' v_%s := ' % (n, n)) + if c._arity == 1: + tb.write('%s;' % n) + else: + for b in range(c._arity-1, -1, -1): + tb.write('%s(%d)&' % (n, b)) + tb.seek(-1,1) + tb.write('; -- to respect order in .pat\n') + + tb.write(' write(lout, string\'("?"));\n' + ' %swrite(lout, v_%s%s);\n' + " write(lout, character'(' '));\n" + ' skip_spaces(l);\n' + " read(l, char); -- skip '?'\n" + " if l(1) /= '*' then\n" + ' %sread(l, vpat_%s%s);\n' % (hex, n, ext, hex, n, ext)) + if (c._format == 'X') and ((c._arity % 4) != 0) and (c._arity > 1) : + tb.write(' vpat_%s := vpat_%s_ext(vpat_%s\'range);\n' %(n, n, n)) + tb.write(' if vpat_%s /= v_%s then\n' + ' write(ldebug, string\'("- at time="));\n' + ' write(ldebug, now);\n' + ' write(ldebug, string\'(" error: %s="));\n' + ' %swrite(ldebug, v_%s%s);\n' + ' write(ldebug, string\'(" (expected "));\n' + ' %swrite(ldebug, vpat_%s%s);\n' + ' write(ldebug, string\'(")"));\n' + ' writeline(TTY_OUTPUT, ldebug);\n' + ' end if;\n' + ' end if;\n' + ' skip_asterisks(l);\n' + % (n, n , n, hex, n, ext, hex, n, ext)) + + # - write vdd vss + tb.write('\n -- write vdd/vss\n' + ' write(lout, string\'("1 0;"));\n') + # - save line + tb.write('\n -- save line\n' + ' writeline(outfile, lout);\n\n') + + # - delay beetween 2 patterns + if not logic: + tb.write('\n -- delay\n' + ' wait for %d %s;\n\n' % (delay, unit)) + + # End of pattern + tb.write(' ---------------------------------------------------------\n' + ' -- End\n' + ' ---------------------------------------------------------\n' + ' else\n' + ' is_end(l, end_of_patterns);\n' + ' if end_of_patterns then\n' + ' writeline(outfile, l);\n' + ' assert false report "End of simulation."\n' + ' severity note;\n' + ' wait;\n' + ' end if;\n' + ' end if;\n' + ' end loop;\n' + ' ASSERT FALSE REPORT "End of simulation without end signal !"\n' + ' severity ERROR;\n' + ' wait;\n' + ' end process;\n' + '\nend rtl;\n') + tb.close() + + + if debug: + print(' - testbench successfully created') + + + + # ---------------------------------------------------------------- + ## Remove STCells empty vhd files + # + # To allow the use of ST macroblocks we declare them a ".vst". + # As a consequence, VASY outputs .vhd files corresponding to these + # blocks, which belonging to the library musn't be here a ".vhd". + def remove_stcells_vhds(self, debug=False): + stmacro = 'b2cr_65.vhd dphs9gp_72x12m4d4_h.vhd schmitc_65.vhd' + + if debug: + print('Remove macroblocks ".vhd"-------------' + '--------------------------------------\n' + ' - block list: %s' % stmacro) + + os.system('rm -f %s'%stmacro) + + if debug: + print(' - macroblocks vhds removed') + + + # ---------------------------------------------------------------- + ## Create run block + # + # run block instanciate both design and testbench + def create_run(self, interface, debug=False, downto=False): + name = self._cell._name + '_run' + run = open('%s.vhd' % name, 'w') + + if debug: + print('Run module ---------------------------' + '--------------------------------------\n' + ' - module name : %s.vhd' % name) + + # Libraries --------------------------------------------------- + run.write('library ieee;\n' + 'use ieee.std_logic_1164.all;\n' + 'use ieee.std_logic_textio.all;\n' + 'use std.textio.all;\n\n') + # Entity ------------------------------------------------------ + run.write('entity %s is\n' + 'end %s;\n\n' % (name, name)) + + # Architecture ------------------------------------------------ + run.write('architecture rtl of %s is\n\n' % name) + # - signals + run.write(' -- SIGNALS\n') + + for c in interface: + if (isinstance(c, SignalIn) or isinstance(c, SignalOut) or + isinstance(c, CkIn)): + run.write(' signal %s: std_logic' % c._name) + if c._arity != 1: + if downto: + run.write('_vector(%d downto 0)'% (c._arity-1)) + else: + run.write('_vector(0 to %d)'% (c._arity-1)) + run.write(';\n') + + # - components + run.write('\n -- COMPONENTS\n') + + run.write(' component %s\n' + ' Port(\n' % self._cell._name) + for c in interface: + if isinstance(c, SignalIn) or isinstance(c, CkIn): + run.write(' %s: in std_logic' % c._name) + elif isinstance(c, SignalOut): + run.write(' %s: out std_logic' % c._name) + else: + continue # skip vdd/vss + if c._arity != 1: + if downto: + run.write('_vector(%d downto 0)'% (c._arity-1)) + else: + run.write('_vector(0 to %d)'% (c._arity-1)) + run.write(';\n') + # Remove last ';' + run.seek(-2,1) + run.write(');\n' + ' end component;\n\n') + + run.write(' component %s_tb\n' + ' Port(\n' % self._cell._name) + for c in interface: + if isinstance(c, SignalIn) or isinstance(c, CkIn): + run.write(' %s: out std_logic' % c._name) + elif isinstance(c, SignalOut): + run.write(' %s: in std_logic' % c._name) + else: + continue # skip vdd/vss + if c._arity != 1: + if downto : + run.write('_vector(%d downto 0)'% (c._arity-1)) + else: + run.write('_vector(0 to %d)'% (c._arity-1)) + run.write(';\n') + # Remove last ';' + run.seek(-2,1) + run.write(');\n' + ' end component;\n\n') + + # - main + run.write('begin\n\n' + ' CHIP: %s\n' + ' port map (' % self._cell._name) + for c in interface: + if (isinstance(c, SignalIn) or isinstance(c, SignalOut) or + isinstance(c, CkIn)): + run.write(c._name+', ') + # remove last ', ' + run.seek(-2,1) + run.write(');\n\n') + + run.write(' STIM: %s_tb\n' + ' port map (' % self._cell._name) + for c in interface: + if (isinstance(c, SignalIn) or isinstance(c, SignalOut) or + isinstance(c, CkIn)): + run.write(c._name+', ') + # remove last ', ' + run.seek(-2,1) + run.write(');\n\n') + + + run.write('end rtl;') + run.close() + + if debug: + print(' - run module successfully created') + + + + # --------------------------------------------------------------- + ## Compile for Synopsys VHDL simulation + def compile(self, debug=False): + if debug: + print('Compile design Synopsys simulator ----' + '--------------------------------------\n' + ' - vhdlan ...') + os.system('mkdir WORK') + vhdl = re.compile(r'\.vhd$') + for filename in os.listdir('./'): + if vhdl.search(filename): + #if debug: + # print('vhdlan: %s' % filename) + if (os.system('vhdlan -nc -debug %s' % filename) != 0): + raise Exception('vhdlan error: vhdlan failure on "%s" analysis or ' + 'Synopsys environment not set.' % filename) + if debug: + print(' - scs %s (ignore "sys_errlist" and "sys_nerr" warnings) ...' + % self._name) + os.system('scs -nc -debug %s_run' % self._name) + + if debug: + print(' - simulator successfully created') + + # --------------------------------------------------------------- + ## Run Synopsys simulation + def run(self, debug=False): + if debug: + print('Executing simulation -----------------' + '--------------------------------------') + os.system("echo 'run; quit' | ./scsim -nc") + if debug: + print(' - end of simulation') + + + # ------------------------------------------------------------------------- + ## If called after Inst.Save() and Inst.Pattern() will build a Synopsys + # simulator + # + # 1 (optional) convert the netlist from vst to vhd through VASY + # (with "self.convert_to_vhdl") + # 2 create vhdl module sending the patterns + # (with "self.create_testbench") + # 3 create main vhdl which connect : the chip and the patterns block + # (with "self.create_run method") + # 4 run the simulator compilation (withe "self.compile") + # @remark Don't forget that you may need a "synopsys_sim.setup" file + # to configure Synopsys for the target library. + def build_simulator(self, debug=False, convert_vst=True, st=True): + if convert_vst: + self.convert_to_vhdl(st=st, debug=debug) + + if debug: + print ' - generate test bench and build simulator (Synopsys) ...' + try: + self._cell.pat + except AttributeError: + # On plante car ne fait pas sens sans pattern + raise Exception("build_simulator: paterns are mandatory") + self.create_testbench(self._cell.pat.get_interface(), + self._cell.pat.time_interval, + self._cell.pat.time_unit) + self.create_run(self._cell.pat.get_interface()) + self.compile(debug=debug) + + # ------------------------------------------------------------------------- + ## Convert the netlist vst to hierachical verilog + # + # + # We consider that this method is called after module.Save(), + # i.e. that the vst as been exported. + # + # 1. (optional) use VASY to convert from VST to VHDL + # 2. use Synopsys to convert from VHDL to VERILOG + # + # @remark this is very usefull to export stratus designs to Cadence + # SOC Encounter. + # + # @remark Creates a file named 'convert_to_verilog.cmd' (name can be + # changed with command_file parameter) + # + # @remark Create a directory named 'BG' (name can be changed with + # the library_dir parameter) + # + # @remark Don't forget that you may need a ".synopsys_dc.setup" file + # to configure Synopsys for the target library. + # + # @warning delete modulename_tb.vhd and modulename_run.vhd + def convert_vhdl2verilog(self, debug=False, + command_file='convert_to_verilog.cmd', + library_dir='BG', + convert_vst=True, + uniquify=True, + st=False): + # Debug messages + if debug: + print(' - converting vhdl to verilog (uses Synopsys, uniquify=%s) ...' + %uniquify) + + # Optionnal vst2vhd conversion + if convert_vst: + self.convert_to_vhdl(st=st, debug=debug) + + # We don't want the test bench components into the output verilog + os.system("rm %s_run.vhd %s_tb.vhd 2> /dev/null"% + (self._name,self._name)) + + # Write Synopsys command file ----------------------------------- + # First part + command_file = 'convert_to_verilog.cmd' + output = open(command_file, 'w') + output.write('sh mkdir %s\n' + 'define_design_lib %s -path ./%s\n' + 'analyze -library %s -format vhdl {\n'% + (library_dir,library_dir,library_dir,library_dir)) + output.close() + + # Add the vhd files names to the conversion script + # (as we use a shell command we need to close the command_file and + # reopen it after) + if (os.system("ls *.vhd >> %s" % command_file) != 0): + raise Exception("error : no vhd files found (missing conversion ?)") + + # End + output = open(command_file, 'a+') + output.write('}\n' + 'elaborate %s -architecture RTL -library %s\n' + %(self._name, library_dir)) + if uniquify: + output.write('uniquify\n') + output.write('write -hierarchy -format verilog -output %s.v\n' + 'exit\n'%self._name) + output.close() + + # Call synopsys to make the conversion -------------------------- + os.system('dc_shell -tcl_mode < %s' % command_file) diff --git a/stratus1/src/modules/patterns/utils.py b/stratus1/src/modules/patterns/utils.py new file mode 100644 index 00000000..8224d09b --- /dev/null +++ b/stratus1/src/modules/patterns/utils.py @@ -0,0 +1,616 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Ludovic NOURY | +# | Roselyne CHOTIN-AVOT | +# | E-mail : Ludovic.Noury@lip6.fr | +# | =============================================================== | +# | Py Module : "./__init__.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +# ------------------------------------------------------ +# $Id: utils.py,v 1.3 2009/11/18 15:35:02 cobell Exp $ +# Author: LIP6/ASIM ludovic.noury@lip6.fr +# Contributor: Roselyne.Chotin-Avot@lip6.fr +# ------------------------------------------------------ +__all__ = ['strfix2float', 'str2int', 'str2uint', 'int2str', 'int2strhex', + 'float2strfix', 'runpat', 'LoadSig', 'MaskNumber', 'runsynop', + 'cout_cal'] + +import math +import re +from math import ceil +from os import system +from stratus import * + +# ------------------------------------------------------ +## @defgroup patterns_utils patterns.utils +# Module: conversion functions +# +# @todo add parameters checks everywhere ... +# +# @version $Id: utils.py,v 1.3 2009/11/18 15:35:02 cobell Exp $ + +# ------------------------------------------------------ +## Convert string to int list (with LSB at res[0]) +# +# @param val input string +# @return corresponding list +# +# @ingroup patterns_utils +def _str2list(val): + binlist = list(val) + binlist.reverse() + binlist = map(int, binlist) + return binlist + +# ------------------------------------------------------ +## Convert the binary representation of a CA2 signed fixed point +# number to the corresponding floating point number. +# +# @param val input string +# @param iwl integer word length +# @return corresponding floating point value +# @todo make a function of "1" as we also use it for PatRead ? +# @remark iwl includes sign bit. +# +# @ingroup patterns_utils +def strfix2float(val, iwl): + # 1. Convert string to int list (with LSB at binlist[0]) + binlist = _str2list(val) + + # 2. Get word length & fractional word length + wl = len(binlist) + fwl = wl-iwl + + # 3. Compute + res = -(2**(iwl-1)) * binlist[wl-1] + for i in range(wl-2, -1, -1): + res += binlist[i]*(2**(i-fwl)) + + # 4. Return + return res + +# ------------------------------------------------------ +## Convert the binary representation of a CA2 signed fixed point +# number to the corresponding int number. +# +# @remark Warning ! works only on signed numbers !! +# +# @param val input string +# @return corresponding int value +# +# @ingroup patterns_utils +def str2int(val): + # 1. Convert string to int list (with LSB at binlist[0]) + binlist = _str2list(val) + + # 2. Get word length + wl = len(binlist) + + # 3. Compute + res = -pow(2,wl-1) * binlist[wl-1] + for i in range(wl-1): + res += binlist[i]*(2**i) + + # 4. Return + return res + +# ------------------------------------------------------ +## Convert the binary representation of a CA2 unsigned fixed point +# number to the corresponding int number. +# +# @param val input string +# @return corresponding int value +# +# @ingroup patterns_utils +def str2uint(val): + # 1. Convert string to int list (with LSB at binlist[0]) + binlist = _str2list(val) + + # 2. Get word length + wl = len(binlist) + + # 3. Compute + res = 0 + for i in range(wl): + res += binlist[i]*(2**i) + + # 4. Return + return res + + +# ------------------------------------------------------ +## Convert an int value to the corresponding 2's complement binary +# string value on wl bits. +# +# We suppose that the machine representation of "value" is in 2's +# complement. Hence we just decode it with binary operations and +# put the result into a string. +# +# @param value int value to convert +# @param wl size of the binary output string : word length +# +# @ingroup patterns_utils +def int2str(value, wl): + res = "" + for pos in range(wl): + res = str( (value & 1L<>pos) + res + return res + +# ------------------------------------------------------ +## Convert an int on wl bit to the corresponding hexadecimal +# representation string. +# +# @param value int value to convert +# @param wl input value word size +# +# @ingroup patterns_utils +def int2strhex(value, wl): + mask = 2**wl-1 + format = '%%0%dx' %int(ceil(wl/4.)) + return format %(value & mask) + + +# ------------------------------------------------------ +## Convert a float value to the corresponding signed fixed point +# string on wl bit and with an integer word size of iwl bits. +# +# @param value int value to convert +# @param wl word length +# @param iwl interger word length (including sign bit) +# +# @ingroup patterns_utils +def float2strfix(value, wl, iwl): + # Put into an int corresponding fixed point number + fixed_value = int(value*2**(wl-iwl)) + + # Convert the number to string + return int2str(fixed_value, wl) + +# ------------------------------------------------------ +## Pattern simulation with asimut +# +# Run netlist simulation with Asimut using the following parameters: +# - options (see option parameter), +# - netlist filename: \e name.vst, +# - pattern filename: \e name.pat, +# - results filename: \e name_res.pat . +# +# @param name netlist name, +# @param options asimut command line options (optional, default empty), +# @param stdout asimut stout (optional, default False), +# @param stderr asimut stderr (optional, default True). +# @return returns asimut exit value. +# @todo Add exception for simulation error. +# +# @ingroup patterns_utils +def runpat(name_vst, name_pat, options='', stdout=False, stderr=True): + cmd_str = ('asimut %s %s %s %s') % (options, name_vst, name_pat, name_pat+'_res') + + if not stdout: + cmd_str += ' > /dev/null' + if not stderr: + cmd_str += ' 2> /dev/null' + + result = system(cmd_str) + if not result : print "Simulation OK" + + return result + +## Return interface connectors dictionnary where key is the conector's name +# and value the connector's format ('B' or 'X' or 'O') +# +# @param name is the tested Stratus model reference name +# @return connectors dictionnary +def get_interface_format(name): + file = open(name+'.pat', 'r') + dict = {} + for line in file : + # stop at end of the declaration + if re.compile(r"^begin$", re.I).search(line): + break; + # skip blank line + if re.compile(r"^ *$", re.I).search(line): + continue + # get name and format + res = re.search("[in|out]+ *(\w*).*([X|B|O]) *;*",line).group(1,2) + dict[res[0]] = res[1] + file.close() + return dict + +## Return interface connectors list +# +# @param cell tested Stratus model reference +# @return connectors list +# +# @ingroup patterns_utils +def get_interface(cell): + l = [] + + dict = get_interface_format(cell._name) + + if (cell==None): + raise Exception("get_interface() " + "cell reference no given thus the cell parameter is mandatory.") + + # 1. Clocks + for port in cell._st_cks: + if isinstance(port, CkIn): + port._format = dict[port._name] + l.append(port) + + # 2. Inputs + for port in cell._st_ports: + if isinstance(port, SignalIn): + port._format = dict[port._name] + l.append(port) + + # 3. Outputs + for port in cell._st_ports: + if isinstance(port, SignalOut): + port._format = dict[port._name] + l.append(port) + + # 4. VDDs + for port in cell._st_vdds: + if isinstance(port, VddIn): + port._format = dict[port._name] + l.append(port) + + # 5. VSSs + for port in cell._st_vsss: + if isinstance(port, VssIn): + port._format = dict[port._name] + l.append(port) + + return l + +# ------------------------------------------------------ +## Pattern simulation with synopsys +# +# @param cell tested Stratus model reference +# @param vasy if vhdl is obtained from Alliance vst netlist (optional, default False) +# @param time_interval between pattern (optional, default 20) +# @param time_unit for simulation, valid values are ps, ns, us and ms (optional, default 'ns') +# @param debug informations during compilation and simulation (optional, default False) +# @param downto to have vector in MSB to LSB format (optional, default True) +# @param logic to have a time_interval delay between inputs and outputs affectations for logical simulation (optional, default False) +# +# @ingroup patterns_utils +def runsynop(cell, vasy = False, time_interval = 20, time_unit = 'ns', debug = False, downto = True, logic = False): + from synopsys import Synopsys + # Convert to VHDL + syn = Synopsys(cell) + if vasy : + syn.convert_to_vhdl() + + # Create testbench + syn.create_testbench(get_interface(cell), time_interval, time_unit, debug, downto, logic) + + # Create testbench and block instance + syn.create_run(get_interface(cell), debug, downto) + + # Compile + syn.compile(debug=True) + + # Run simulation + syn.run() + + del syn + +# ------------------------------------------------------ +## Create a samples iterator from an input file +# +# Return a iterator from the specified input signal. The iterator +# output format can be : +# - LoadSig.FIX the corresponding fixed point number converted back +# to float, +# - LoadSig.STRING the binary representation of the fixed point number +# into a string, +# - LoadSig.FLOAT the original floating point number without any +# conversion. +# - LoadSig.INT the rounded int number +# +# @remark the input file has one floating point number per line, +# comments begin with # +# +# @remark Python don't support multiple constructors without hack, so +# we prefer not to use them. +# (see: http://mail.python.org/pipermail/python-list/2005-May/280116.html) +# +# @ingroup patterns_utils +class LoadSig: + # Class attributes ------------------------------------- + ## Used a constructor parameter, select fixed point output + FIX = 0 + ## Used a constructor parameter, select binary string output + STRING = 1 + ## Used a constructor parameter, select unconverted float output + FLOAT = 2 + ## Used a constructor parameter, select rounded int output + INT = 3 + + # Private attributes ----------------------------------- + # @var _f file object + # @var _it input file object iterator + # @var _wl word length + # @var _iwl input word length + # @var _mode output format (FIX|STRING|FLOAT|INT) + + # ------------------------------------------------------ + ## Constructor + # + # @param filename input filename, + # @param connector stratus connector, + # @param iwl integer word length, + # @param mode set iterator output format (LoadSig.FIX | + # LoadSig.STRING | LoadSig.FLOAT | LoadSig.INT). + def __init__(self, filename, connector, iwl, mode): + self._f = open(filename, 'r') + self._it = iter(self._f) + self._wl = connector._arity + self._iwl = iwl + self._mode = mode + + # ------------------------------------------------------ + # Activate Iterator + def __iter__(self): + return self + + # ------------------------------------------------------ + # Subfonction used by next(), convert a line to the selected output + # format. + def _make_output(self,line): + r = float2strfix(float(line), self._wl, self._iwl) + + if self._mode == self.STRING: + return r + elif self._mode == self.FIX: + return strfix2float(r , self._iwl) + elif self._mode == self.FLOAT: + return float(line) + elif self._mode == self.INT: + return int(round(float(line))) + + # ------------------------------------------------------ + ## Return next sample + def next(self): + line = self._it.next() + while re.compile("^#").search(line): + line = self._it.next() + return self._make_output(line) + +# ------------------------------------------------------------------------- +## Create an iterator for a pattern input signal values. +# +# The iterator will return at each call the next input signal value in +# the form of the corresponding unsigned int. The output value +# sequence depends on the input signal word length (wl): +# - wl=MAX_IT: use Pattern Mask Generator (PMG) to reduce the number +# of values. +# +# The PMG splits the number into 3 parts: +# - a middle fixed part where all bits have the same value (0 or 1), +# - 2 varying parts (called masks, one for msb and one for lsb) with +# the same fixed width. +# +# At each call, the iterator : +# -# increments the masks to obtain all the possible values, +# -# add these 2 masks around the middle part to obtain the final +# value, +# -# returns the final value. +# +# @todo Add constructor parameters check (raise exception if +# width<=mask_width). +# @todo Check if there is no errors during << witch could be corrected +# by using long int. +# +# @ingroup patterns_utils +class MaskNumber: + # Class attributes ----------------------------------------------- + ## Maximal signal width for exhaustive generation + MAX_IT = 9 + + # Private instance attributes ------------------------------------ + ## @var _mask_value + # Varying part value. + + ## @var _middle + # Central part value. + + ## @var _currrent + # Current value of the number. + + ## @var _mask_width + # Mask width. + + ## @var _width + # Width of the signal to affect. + + ## @var _exhaustiv + # If False force using PMG even if wl= width: + raise Exception('MaskNumber.__init__: ' + 'mask_width(%d)*2 >= width(%d)' % (mask_width, width)) + self._mask_max_value = 2**(2*mask_width) - 1 + + self._mask_lsb = 2**mask_width-1 + self._mask_msb = (2**mask_width-1) << mask_width + self._dec_val = self._width - 2 * self._mask_width + + # ---------------------------------------------------------------- + # Activate Iterator + def __iter__(self): + return self + + # ---------------------------------------------------------------- + def _next_exhaustive(self): + if self._mask_value == self._mask_max_value: + # stop generation at last value + raise StopIteration + else: + # increment each value by 1 + self._mask_value += 1 + self._current = self._mask_value + return self._mask_value + + # ---------------------------------------------------------------- + def _next_pmg(self): + if self._mask_value == self._mask_max_value: + if self._middle != 0: + # Stop generation when all the mask value are obtained + # for both value (0 and 1) of the central part. + raise StopIteration + else: + # When all the mask value are obtained for the 0 central value + # we pass to the 1 central value. + self._mask_value = -1 + self._middle = 2**self._width - 1 + self._middle = (self._middle ^ + ((self._mask_msb * 2**self._dec_val) + self._mask_lsb)) + value = 0 + # 2.a Adds 1 to the mask value + self._mask_value = self._mask_value + 1 + # 2.b Constructs msb and lsb parts of the mask value + lsb = self._mask_value & self._mask_lsb + msb = (self._mask_value & self._mask_msb) * 2**self._dec_val + # 2.c Place msb and lsb around central part + value = msb + self._middle + lsb + # 2.d Return the obtained value + self._current = value + return value + + # ---------------------------------------------------------------- + ## Return next sample + # + # @param self The object pointer. + # @return next sample. + def next(self): + # Signal width inferior to MAX_IT => exhaustive pattern generation. + # else we use PMG. + if (self._width < self.MAX_IT) and (self._exhaustiv): + return self._next_exhaustive() + else: + return self._next_pmg() + + # ---------------------------------------------------------------- + ## Reset the generator to the first value + # + # @param self The object pointer. + def reset(self): + self._mask_value = -1 + self._middle = 0 + self._current = -1 + + # ---------------------------------------------------------------- + ## Return current sample + # + # @param self The object pointer. + # @return current sample. + def current(self): + return self._current + +# ------------------------------------------------------ +## Extend a given signed number +# @param val is the number to extend +# @param width is the width in bits of the number +# @return the extended value +def extend(val,width): + # if the number is negative extend the sign ('1') + if val >= 2**(width-1): + mask = ~(2**width-1) + return (val | mask) + # else return the number + else: + return val + +# ------------------------------------------------------ +## Calculation of the cout's value in case of addition +# @param width is the width in bits of the number +# @param vali0 is the value of the first operand +# @param vali1 is the value of the second operand +# @param valCin is the value of the input carry +# @return the corresponding value of cout +def cout_cal(width,valA,valB,valCin): + mask = 2**width - 1 + val = (valA & mask) + (valB & mask) + valCin + if val >= 2**width: + return 1 + else: + return 0 diff --git a/stratus1/src/stratus/CMakeLists.txt b/stratus1/src/stratus/CMakeLists.txt new file mode 100644 index 00000000..ebc64ce0 --- /dev/null +++ b/stratus1/src/stratus/CMakeLists.txt @@ -0,0 +1,36 @@ + + set ( pysources ${CMAKE_CURRENT_SOURCE_DIR}/st_bool.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_cat.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_comp.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_const.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_extend.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_func_gen_wallace.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_generate.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_getrealmodel.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_instance.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_model.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_mult_blocs.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_mult_matrix.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_mult.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_mux.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_net.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_param.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_parser.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_placeAndRoute.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_placement.py + ${CMAKE_CURRENT_SOURCE_DIR}/stratus.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_ref.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_shifter.py + ${CMAKE_CURRENT_SOURCE_DIR}/st_slansky.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Const.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Defs.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Gen.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Misc.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Place.py + ${CMAKE_CURRENT_SOURCE_DIR}/util.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Route.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_Shift.py + ${CMAKE_CURRENT_SOURCE_DIR}/util_uRom.py + ) + + install ( FILES ${pysources} DESTINATION ${PYTHON_SITE_PACKAGES}/stratus ) diff --git a/stratus1/src/stratus/st_bool.py b/stratus1/src/stratus/st_bool.py new file mode 100644 index 00000000..277a704f --- /dev/null +++ b/stratus1/src/stratus/st_bool.py @@ -0,0 +1,159 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_bool.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +from st_parser import I, I0, I2, I3, A, CK, CMD, CMD0, CIN, Q, NQ, S + +class Bool ( Model ) : + + def __init__ ( self, name, param, inout ) : + Model.__init__ ( self, name, param ) + + self.m = self._param['model'] + self.realM = self._param['realModel'] + + self.dictInOut = inout + + if 'nbit' not in param : self.nbit = 1 + else : self.nbit = self._param['nbit'] + + if self.nbit < 1 : + err = "\n[Stratus ERROR] " + self.m + " : the number of bits must be greater than 0.\n" + raise err + + def Interface ( self ) : + if self.m in I : + self._i = SignalIn ( "i", self.nbit ) + elif self.m in I0 : + self._i0 = SignalIn ("i0", self.nbit ) + self._i1 = SignalIn ("i1", self.nbit ) + elif self.m in A : + self._a = SignalIn ( "a", self.nbit ) + self._b = SignalIn ( "b", self.nbit ) + + if self.m in I2 : + self._i2 = SignalIn ("i2", self.nbit ) + if self.m in I3 : + self._i3 = SignalIn ("i3", self.nbit ) + + if self.m in CMD : + self._cmd = SignalIn ( "cmd", 1 ) + elif self.m in CMD0 : + self._cmd0 = SignalIn ( "cmd0", 1 ) + self._cmd1 = SignalIn ( "cmd1", 1 ) + + if self.m in CK : + self._ck = CkIn ( "ck" ) + + if self.m in CIN : + self._cin = SignalIn ( "cin", self.nbit ) + + if self.m in Q : + self._q = SignalOut ( "q", self.nbit ) + elif self.m in NQ : + self._nq = SignalOut ( "nq", self.nbit ) + elif self.m in S : + self._sout = SignalOut ( "sout", self.nbit ) + self._cout = SignalOut ( "cout", self.nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + for i in range ( self.nbit ) : + boolMap = { self.dictInOut['vdd'] : self._vdd + , self.dictInOut['vss'] : self._vss + } + + if self.m in I : + boolMap[self.dictInOut['i']] = self._i[i] + elif self.m in I0 : + boolMap[self.dictInOut['i0']] = self._i0[i] + boolMap[self.dictInOut['i1']] = self._i1[i] + elif self.m in A : + boolMap[self.dictInOut['a']] = self._a[i] + boolMap[self.dictInOut['b']] = self._b[i] + + if self.m in I2 : + boolMap[self.dictInOut['i2']] = self._i2[i] + if self.m in I3 : + boolMap[self.dictInOut['i3']] = self._i3[i] + + if self.m in CIN : + boolMap[self.dictInOut['cin']] = self._cin[i] + if self.m in CMD : + boolMap[self.dictInOut['cmd']] = self._cmd + elif self.m in CMD0 : + boolMap[self.dictInOut['cmd0']] = self._cmd0 + boolMap[self.dictInOut['cmd1']] = self._cmd1 + if self.m in CK : + boolMap[self.dictInOut['ck']] = self._ck + + if self.m in Q : + boolMap[self.dictInOut['q']] = self._q[i] + elif self.m in NQ : + boolMap[self.dictInOut['nq']] = self._nq[i] + elif self.m in S : + boolMap[self.dictInOut['sout']] = self._sout[i] + boolMap[self.dictInOut['cout']] = self._cout[i] + + Inst ( "%s" % self.realM + , map = boolMap + ) + + def GetParam ( cls ): + global BV + from st_parser import BV + if BV == [] : InitBV() + + return {'nbit' : 'integer', 'model' : BV} + + GetParam = classmethod ( GetParam ) diff --git a/stratus1/src/stratus/st_cat.py b/stratus1/src/stratus/st_cat.py new file mode 100644 index 00000000..5ba7962c --- /dev/null +++ b/stratus1/src/stratus/st_cat.py @@ -0,0 +1,104 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_cat.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * + +from st_net import * + +import types + +def Cat ( *nets ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + nb = len ( cell._TAB_NETS_CAT ) + + cell._TAB_NETS_CAT += [Signal ( "net_cat_%d" % nb )] + + netToCat = cell._TAB_NETS_CAT[nb] + + if type ( nets[0] ) == types.ListType : nets = nets[0] + + # Creation of the inversed tab + netstries = [] + for net in nets : netstries.insert ( 0, net ) + + if ( "_arity" not in net.__dict__ ) or ( "_real_net" not in net.__dict__ ) or ( "_ind" not in net.__dict__ ) : + err = "\n[Stratus ERROR] Cat : Problem of parameter.\n" + raise err + + # Construction of the tab _to_cat if needed + if not ( len ( netToCat._to_cat ) ) : + for net in netstries : + for l in range ( net._arity ) : netToCat._to_cat.append ( 0 ) + + # Initialisation of _to_cat + for net in netstries : + if net._real_net : realNet = net._real_net + else : realNet = net + + nbit1 = net._ind + if ( '_reverse' in net.__dict__ ) and ( net._reverse ) : + nbit2 = net._ind - net._arity + pas = -1 + else : + nbit2 = net._ind + net._arity + pas = 1 + + for l in range ( nbit1, nbit2, pas ) : + netToCat._to_cat[netToCat._arity] = [realNet, l] + netToCat._arity += 1 + + # Initialisation of _hur_net if in hurricane mode + if netToCat._st_cell._hur_cell : netToCat._hur_net += [realNet._hur_net[l]] + + return netToCat diff --git a/stratus1/src/stratus/st_comp.py b/stratus1/src/stratus/st_comp.py new file mode 100644 index 00000000..1466fc25 --- /dev/null +++ b/stratus1/src/stratus/st_comp.py @@ -0,0 +1,198 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_comp.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +import re, types + +class Comp ( Model ) : + + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + + self.nbit = param['nbit'] + self.nb = param['nb'] + self.egal = param['egal'] + + if self.egal : self.func = "Eq" + else : self.func = "Ne" + + # Error : if net is not a string + if type ( self.nb ) != types.StringType : + err = "\n[Stratus ERROR] " + self.func + " : the argument must be a string.\n" + raise err + + def Interface ( self ) : + self.netIn = SignalIn ( "netin", self.nbit ) + self.netOut = SignalOut ( "netout", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + netConst = Signal ( "netconst" ) + + extendConst = Signal ( "extendconst", self.nbit ) + tempXor = Signal ( "tempxor", self.nbit ) + + netConst <= self.nb + + # Error : if the number is too big for the arity of the net + if netConst._arity > self.nbit : + err = "\n[Stratus ERROR] " + self.func + " : the number does not match with the net's lenght.\n" + raise err + # Otherwise, completion of the net + elif netConst._arity < self.nbit : extendConst <= netConst.Extend ( self.nbit, 'zero' ) + else : netConst.Alias ( extendConst ) + + # Xor bit per bit + tempXor <= self.netIn ^ extendConst + + if self.nbit > 1 : + if self.egal : + Generate ( "st_comp.BoolToOne", "bool_to_one_%s_%dbits" % ( "nor", tempXor._arity ), param = { 'nbit' : tempXor._arity, 'func' : "Nor" } ) + Inst ( "bool_to_one_%s_%dbits" % ( "nor", tempXor._arity ) + , map = { 'i' : tempXor + , 'q' : self.netOut + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + else : + Generate ( "st_comp.BoolToOne", "bool_to_one_%s_%dbits" % ( "or", tempXor._arity ), param = { 'nbit' : tempXor._arity, 'func' : "Or" } ) + Inst ( "bool_to_one_%s_%dbits" % ( "or", tempXor._arity ) + , map = { 'i' : tempXor + , 'q' : self.netOut + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + else : + if self.egal : self.netOut <= ~tempXor + else : self.netOut <= tempXor + + def GetModelName ( cls, param ) : + modelName = "comparator" + + modelName += "_" + + if param['egal'] : modelName += "eq" + else : modelName += "ne" + + modelName += "_" + modelName += param['nb'] + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'nb' : 'StringInteger' , 'egal' : 'boolean'} + + GetParam = classmethod ( GetParam ) + +class BoolToOne ( Model ) : + + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + + self.nbit = param['nbit'] + + if self.nbit < 2 : raise "\n[Stratus ERROR] booltoone : the number of bits of the inputs must be greater than 1.\n" + + self.func = param['func'] + + if self.func not in ( "And", "Nand", "Or", "Nor", "Xor", "Nxor" ) : + err = "\n[Stratus ERROR] " + self.func + " : the argument must be a string.\n" + raise err + + def Interface ( self ) : + self._in = SignalIn ( "i", self.nbit ) + self._q = SignalOut ( "q", 1 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + nbStages = log2(self.nbit) + + def bool_function ( net1, net2 ) : + if self.func == 'And' : return ( net1 & net2 ) + elif self.func == 'Nand' : return ~( net1 & net2 ) + elif self.func == 'Or' : return ( net1 | net2 ) + elif self.func == 'Nor' : return ~( net1 | net2 ) + elif self.func == 'Xor' : return ( net1 ^ net2 ) + elif self.func == 'Nxor' : return ~( net1 ^ net2 ) + + out = {} + out[0] = self._in[0] + for i in range ( 1, self.nbit ) : + out[i] = Signal("out%d" % i , 1 ) + out[i] <= bool_function ( out[i-1], self._in[i] ) + self._q <= out[self.nbit-1] + + def GetModelName ( cls, param ) : + modelName = str(param['func']) + + modelName += "_" + modelName += str(param['nbit']) + modelName += "bits_to one" + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'func' : ["And", "Nand", "Or", "Nor", "Xor", "Nxor"]} + + GetParam = classmethod ( GetParam ) + diff --git a/stratus1/src/stratus/st_const.py b/stratus1/src/stratus/st_const.py new file mode 100644 index 00000000..dd8da513 --- /dev/null +++ b/stratus1/src/stratus/st_const.py @@ -0,0 +1,199 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_const.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from Hurricane import * + +from st_net import * +from st_instance import Inst +from st_generate import Generate + +import types + +################## +def One ( nbit ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "one_%d" % num_net, nbit )] + + # "1 bit constant" => directly instanciate the virtual cell "One" cell + # "> 1 bit constant" => generate a model +# if nbit == 1: +# inst_name = "one" +# else: + inst_name = "one_%dbits" % nbit + Generate ( "One", inst_name, param = { 'nbit' : nbit } ) + Inst ( inst_name + , map = { 'q' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + +################### +def Zero ( nbit ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "zero_%d" % num_net, nbit )] + + # "1 bit constant" => directly instanciate the virtual cell "Zero" cell + # "> 1 bit constant" => generate a model +# if nbit == 1: +# inst_name = "zero" +# else: + inst_name = "zero_%dbits" % nbit + Generate ( "Zero", inst_name, param = { 'nbit' : nbit } ) + Inst ( inst_name + , map = { 'nq' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + +###################### +class Constant ( Model ) : + + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + + self.string = Constant.getString ( param ) + self.nbit = len ( self.string ) + + def Interface ( self ) : + self.outPut = SignalOut ( "output0", self.nbit ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + i = 0 + for letter in self.string : + if letter == "1" : self.outPut[i] <= One ( 1 ) + else : self.outPut[i] <= Zero ( 1 ) + i += 1 + + def GetModelName ( cls, param ) : + modelName = "constant" + + modelName += "_" + modelName += param['nb'] + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetString ( param ) : + nb = param['nb'] + + # Error : if nb is not a string + if type ( nb ) != types.StringType : raise "\n[Stratus ERROR] Constant : the argument must be a string.\n" + + ### String representing a binary number ( from the LSB to the MSB ) ### + bin = re.search ( "0[bB]([0-1]+)", nb ) + hexa = re.search ( "0[xX]([0-9,A-F]+)", nb ) + oct = re.search ( "0[oO]([0-7]+)", nb ) + dec = re.search ( "([0-9]+)", nb ) + + # The parameter is a binary number + if bin : + result = bin.group(1) + string = "" + for i in range ( len (result)-1, -1, -1 ) : string += result[i] + # The parameter is an hexadecimal number + elif hexa : + result = hexa.group(1) + string = "" + raise "Hexa not ready yet." + # The parameter is an octal number + elif oct : + result = oct.group(1) + string = "" + raise "Octal not ready yet." + # The parameter is a decimal number + elif dec : + num = int ( nb ) + string = "" + + if not num : + string = "0" + else : + while num : + num2 = num + num /= 2 + if ( num * 2 ) != num2 : string += "1" + else : string += "0" + + # Error if the string does not belong to the previous categories + else : + raise "\n[Stratus ERROR] Const : the argument must be a string representing a number in decimal, binary (0b) or hexa (0x).\n" + + return string + + GetString = staticmethod ( GetString ) + + def GetParam ( cls ): + + return {'nb' : 'StringInteger'} + + GetParam = classmethod ( GetParam ) diff --git a/stratus1/src/stratus/st_extend.py b/stratus1/src/stratus/st_extend.py new file mode 100644 index 00000000..1fbd5a13 --- /dev/null +++ b/stratus1/src/stratus/st_extend.py @@ -0,0 +1,88 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_extend.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from stratus import * + +class Extend ( Model ) : + + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + self.nbit0 = param['nbit0'] + self.nbit1 = param['nbit1'] + + self.type = param['type'] + + def Interface ( self ) : + self.i = SignalIn ( "i", self.nbit0 ) + self.o = SignalOut ( "o", self.nbit1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + if self.nbit0 > 1 : self.o[self.nbit0-1:0] <= self.i.Buffer() + else : self.o[0] <= self.i.Buffer() + + if self.type == 'zero' : + if (self.nbit1-1) == self.nbit0 : self.o[self.nbit0] <= Zero ( 1 ) + else : self.o[self.nbit1-1:self.nbit0] <= Zero ( self.nbit1 - self.nbit0 ) + elif self.type == 'one' : + if (self.nbit1-1) == self.nbit0 : self.o[self.nbit0] <= One ( 1 ) + else : self.o[self.nbit1-1:self.nbit0] <= One ( self.nbit1 - self.nbit0 ) + elif self.type == 'signed' : + for i in range ( self.nbit0, self.nbit1 ) : self.o[i] <= self.i[self.nbit0-1].Buffer() + else : + raise "\n[Stratus ERROR] Extend : type must be \'zero\', \'one\' or \'signed\'.\n" + + def GetParam ( cls ): + + return {'nbit0' : 'integer', 'nbit1' : 'integer', 'type' : ["zero", "one", "signed"]} + + GetParam = classmethod ( GetParam ) + diff --git a/stratus1/src/stratus/st_func_gen_wallace.py b/stratus1/src/stratus/st_func_gen_wallace.py new file mode 100644 index 00000000..bc3a670d --- /dev/null +++ b/stratus1/src/stratus/st_func_gen_wallace.py @@ -0,0 +1,340 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_func_gen_wallace.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +from math import * + +import string + +################################################################ +def genWallace ( cell, _tabIn, matrixIn ) : + FA = 0 + HA = 1 + tabIn = transpose ( _tabIn ) + mylistTransposed = transpose ( matrixIn[:] ) + nbNumbers = len ( _tabIn ) + + tabtmp = wallace ( mylistTransposed ) + tabFAHA = tabtmp[0] + + count = 0 + choix = 0 + + tabInput = [] + for i in range ( len ( tabIn ) ) : + tabInput.append ( [] ) + + for j in range ( len ( tabIn[i] ) ) : + if tabIn[i][j] : + choix = 1 + count = count + 1 + tabInput[i].append ( Signal ( "tabinput_%d_%d" % ( i, j ) , 1 ) ) + + tabInput[i][len(tabInput[i])-1] = tabIn[i][j] + + if choix == 0 : tabInput = tabIn + + if nbNumbers > 2 and len ( tabFAHA ) > 0 : + for i in range ( len ( tabInput ) ) : + for k in range ( tabInput[i].count ( 0 ) ) : tabInput[i].pop ( tabInput[i].index ( 0 ) ) + + for i in range ( len ( tabFAHA[0] ) - len( tabInput ) ) : tabInput = [[]] + tabInput + + colOut = [] + reportedCarries = [] + + for i in range ( len ( tabFAHA ) ) : + for jinv in range ( len ( tabFAHA[i] ) ) : + j = len(tabFAHA[i]) - 1 - jinv + jj = j + + t = tabFAHA[i][j] + reportCarries = [] + col = [] + col = tabInput[jj] + reportedCarries + colOut = [] + + for ii in range ( t[FA] ) : + listFA = getInputs ( col, 3 ) + + colOut.append ( Signal ( "colout_%d_%d_%d" % ( i, jinv, ii ), 1 ) ) + reportCarries.append ( Signal ( "report_%d_%d_%d" % ( i, jinv, ii ), 1 ) ) + + Generate ( 'Fulladder', "full_adder", param = {'nbit' : 1} ) + Inst ( 'full_adder' + , map = { 'a' : col[listFA[0]] + , 'b' : col[listFA[1]] + , 'cin' : col[listFA[2]] + , 'sout' : colOut[ii] #[0] + , 'cout' : reportCarries[ii][0] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + col.pop ( listFA[2] ) + col.pop ( listFA[1] ) + col.pop ( listFA[0] ) + + sizeReportCarries = len ( reportCarries ) + sizeColOut = len ( colOut ) + + for ii in range ( t[HA] ) : + listHA = getInputs ( col, 2 ) + + colOut.append ( Signal ( "colout_%d_%d_%d" % ( i, jinv, ii+t[FA]), 1 ) ) + reportCarries.append ( Signal ( "report_%d_%d_%d" % ( i, jinv, ii+t[FA]), 1 ) ) + + Generate ( 'Halfadder', 'half_adder', param = {'nbit ': 1} ) + Inst ( 'half_adder' + , map = { 'a' : col[listHA[0]] + , 'b' : col[listHA[1]] + , 'sout' : colOut[sizeColOut + ii] #[0] + , 'cout' : reportCarries[sizeReportCarries + ii][0] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + col.pop(listHA[1]) + col.pop(listHA[0]) + + for ii in range ( len ( colOut ) ) : col = col + [colOut[ii][0]] + + for ii in range ( len ( reportCarries ) ) : + tmp = reportCarries[ii][0] + reportCarries[ii] = tmp + + tabInput[jj] = col[:] + + reportedCarries = reportCarries[:] + + for i in range ( len ( tabInput ) ) : + for k in range ( tabInput[i].count ( 0 ) ): tabInput[i].pop ( tabInput[i].index ( 0 ) ) + + sizeTabInput = len ( tabInput ) + + output0 = Signal ( "output0", sizeTabInput ) + output1 = Signal ( "output1", sizeTabInput ) + + for j in range ( sizeTabInput ) : + jj = sizeTabInput -1 -j + + if len ( tabInput[j] ) == 0 : + output0[jj] <= Zero(1) + output1[jj] <= Zero(1) + + elif len ( tabInput[j] ) == 1 : + output0[jj] <= tabInput[j][0].Buffer() + output1[jj] <= Zero(1) + + elif len ( tabInput[j] ) > 1 : + output0[jj] <= tabInput[j][0].Buffer() + output1[jj] <= tabInput[j][1].Buffer() + + return [sizeTabInput,output0,output1] + +################################################################ +def getInputs ( lst, nb ) : + lResult = [] + sizeList = len(lst) + i = 0 + + while nb > 0 and i < sizeList: + if lst[i] : + lResult = lResult + [i] + nb = nb -1 + i = i+1 + + return lResult + +################################################################ +def suite_dadda ( iValue ) : + Un = 2 + Un_1 = 2 + + while Un < iValue : + aux = (3 * Un_1) / 2 + Un_1 = Un + Un = aux + + return Un_1 + +################################################################ +def transpose ( lValue ) : + ltmp = [] + + nbCol = len(lValue[0]) + nbLine = len(lValue) + + for j in range(nbCol): + ltmp2 = [] + for i in range ( nbLine ) : ltmp2.append ( lValue[i][j] ) + + ltmp.append ( 0 ) + ltmp[j] = ltmp2 + + return ltmp + +################################################################ +def find_first_zero ( lValue ) : + i_ = 0 + + for i_ in range (len ( lValue ) ) : + if lValue[i_] == 0 : return i_ + + return -1 + +################################################################ +def wallace_1level ( lMat, lAdders ) : + + lMatrice = lMat[:] + + for j in range(len(lMatrice)): + lAdders.append([0]) + + hmax = max_list(lMatrice) + umax = suite_dadda(hmax) + + carries = [] + + for j in range(len(lMatrice)): + i=len(lMatrice)-1-j + + nb_FA = 0 + nb_HA = 0 + report_carries = [] + + delta = size_list(lMatrice[i]) - umax + nbToDel = delta + len(carries) + + if(nbToDel > 0): + nb_FA = nbToDel/2 + nb_HA = nbToDel%2 + else: + nb_FA = 0 + nb_HA = 0 + + for k in range(nb_FA + nb_HA) : report_carries = report_carries + [1] + + lAdders[i] = [nb_FA, nb_HA] + + nb = size_list(lMatrice[i]) + + for k in range(len(carries)): + ii = find_first_zero(lMatrice[i]) + + if(ii == -1): + (lMatrice[i]).append(1) + else: + lMatrice[i].remove(0) + lMatrice[i].insert(ii,1) + + for k in range(nbToDel ): + (lMatrice[i]).remove(1) + (lMatrice[i]).append(0) + + carries = report_carries + + if(len(carries) > 0 ): + for i in range( len(lMatrice[0]) - len(carries) ) : carries = carries + [0] + + lMatrice = [carries] + lMatrice + + return lMatrice + +#------------------------------------------------------------------------ +def wallace ( lValue ) : + ltmp=lValue[:] + + nbNumbers = len(lValue[0]) + + listAdders = [] + + counter = 0 + + while max_list(ltmp)>2: + listAdders.append([0]) + listAdders[counter] = [] + + ltmp = wallace_1level(ltmp,listAdders[counter]) + counter = counter +1 + + if(nbNumbers>2): + mmax = 0; + for i in range(len(listAdders)): + if len(listAdders[i]) > mmax : mmax = len(listAdders[i]) + + for i in range(len(listAdders)) : + while (mmax - len(listAdders[i])) > 0 : listAdders[i] = [[0,0]] + listAdders[i] + + if(nbNumbers>2 and len(listAdders) > 0) : return [listAdders,ltmp] + else : return [[],lValue] + +#------------------------------------------------------------------------ +def size_list ( lValue ) : + count = 0 + + for i in range ( len ( lValue ) ) : + if ( lValue[i] == 1 ) : count = count + 1 + + return count + +#------------------------------------------------------------------------ +def max_list ( lValue ) : + nbmax = 0 + + for j in range ( len ( lValue ) ) : + nb = size_list ( lValue[j] ) + + if nb > nbmax : nbmax = nb + + return nbmax diff --git a/stratus1/src/stratus/st_generate.py b/stratus1/src/stratus/st_generate.py new file mode 100644 index 00000000..87ec99fc --- /dev/null +++ b/stratus1/src/stratus/st_generate.py @@ -0,0 +1,115 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_generate.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * +from CRL import * + +from st_model import Model, MODELMAP +from st_getrealmodel import GetRealModel, InitBV + +import sys, re, types, os + +def Generate ( model_name, inst_name, param = {} ) : + global CELLS, FRAMEWORK, MODEL_MAP + from st_model import CELLS, FRAMEWORK + cell = CELLS[-1] + + if '_vbe' in cell.__dict__ : param['behavioral'] = cell._vbe + + # Error : if the model is not a string + if type ( model_name ) != types.StringType : + err = "\n[Stratus ERROR] Generate : the model must be described in a string.\n" + raise err + if type ( inst_name ) != types.StringType : + err = "\n[Stratus ERROR] Generate : the model must be described in a string.\n" + raise err + + # Error : spaces are forbidden + if re.search ( " ", inst_name ) : + err = "\n[Stratus ERROR] Generate : " + inst_name + " the name of the model \"" + model_name + "\" can not contain a space.\n" + raise err + # Warning : the name can not contain capitalized letters + if re.search ( "[A-Z]", inst_name ) : + print "[Stratus Warning] Generate : Upper case letters are not supported, the name", inst_name, "is lowered." + inst_name = inst_name.lower() + + # Check if the model does already exist + hur_masterCell = FRAMEWORK.getCell ( inst_name, Catalog.State.Views ) + + st_masterCell = None + for c in cell._underCells : + if inst_name == c._name : st_masterCell = c + + # Creation of model not found neither in the database nor in the files + if not ( hur_masterCell or st_masterCell ) : + cell._model_map[inst_name] = [model_name, param] + + realModele = None + inout = None + + global BVg + from st_parser import BVg + if BVg == [] : InitBV() + + if model_name in BVg : realModele, inout = GetRealModel ( model_name.lower() ) + + st_masterCell = cell.ModelCreation ( model_name, inst_name, param, cell._hierarchy+1, realModele, inout ) + + if "Properties" in dir ( st_masterCell ) : return st_masterCell.Properties() + else : return st_masterCell + + else : + if st_masterCell : + # MAJ of the hierarchy in _underCells + CELLS[0]._underCells[st_masterCell] = cell._hierarchy+1 + return st_masterCell + + else: + return hur_masterCell diff --git a/stratus1/src/stratus/st_getrealmodel.py b/stratus1/src/stratus/st_getrealmodel.py new file mode 100644 index 00000000..0f995fc3 --- /dev/null +++ b/stratus1/src/stratus/st_getrealmodel.py @@ -0,0 +1,93 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_getrealmodel.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +from st_parser import Parser, InitParser, WeightParser + +import os + +def InitBV () : + myP = InitParser() + + if 'STRATUS_MAPPING_NAME' in os.environ : + myP.Parse ( os.environ['STRATUS_MAPPING_NAME'] ) + else : + err = "\n[Stratus ERROR] Virtual library : No file found in order to parse.\nCheck STRATUS_MAPPING_NAME.\n" + raise err + +def GetRealModel ( model ) : + myP = Parser() + + if 'STRATUS_MAPPING_NAME' in os.environ : + myP.Parse ( os.environ['STRATUS_MAPPING_NAME'] ) + else : + err = "\n[Stratus ERROR] Virtual library : No file found in order to parse.\nCheck STRATUS_MAPPING_NAME.\n" + raise err + + return myP._realCell[model], myP._inOut[model] + +def GetWeightTime ( model ) : + myP = WeightParser() + + if 'STRATUS_MAPPING_NAME' in os.environ : + myP.Parse ( os.environ['STRATUS_MAPPING_NAME'] ) + else : + err = "\n[Stratus ERROR] Virtual library : No file found in order to parse.\nCheck STRATUS_MAPPING_NAME.\n" + raise err + + return myP._weightTime[model] + +def GetWeightArea ( model ) : + myP = WeightParser() + + if 'STRATUS_MAPPING_NAME' in os.environ : + myP.Parse ( os.environ['STRATUS_MAPPING_NAME'] ) + else : + err = "\n[Stratus ERROR] Virtual library : No file found in order to parse.\nCheck STRATUS_MAPPING_NAME.\n" + raise err + + return myP._weightArea[model] diff --git a/stratus1/src/stratus/st_instance.py b/stratus1/src/stratus/st_instance.py new file mode 100644 index 00000000..a9601dcf --- /dev/null +++ b/stratus1/src/stratus/st_instance.py @@ -0,0 +1,375 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_instance.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * +import CRL + +from st_model import Model, MODELMAP +from st_getrealmodel import GetRealModel, InitBV + +import sys, re, types, os + +## Alliance's libraries ## +SXLIB = "_x[0-8]" +PXLIB = "_px" +RAMLIB = "ram_" +RFLIB = "rf_" +RF2LIB = "rf2_" +ROMLIB = "rom_" +DPSXLIB = "dp_.*_x[1-8]" + +## Puts MBK_CATA_LIB at the begining of PYTHONPATH ## +cata_lib = os.environ['MBK_CATA_LIB'] +chaine = re.search ( "([^:]*):(.*)", cata_lib ) +while chaine : + rep = chaine.group ( 1 ) + cata_lib = chaine.group ( 2 ) + + sys.path.insert ( 0, rep ) + + chaine = re.search ( "([^:]*):(.*)", cata_lib ) + +## Class of nets ## +NET = ( "st_net.SignalIn", "st_net.SignalOut", "st_net.SignalInOut" \ + , "st_net.SignalUnknown", "st_net.TriState" \ + , "st_net.CkIn" \ + , "st_net.Signal", "st_net.Sig" \ + , "st_net.VddIn", "st_net.VssIn" \ + , "st_net.VddInFromHur", "st_net.VssInFromHur" + ) +ALIM_NET = ( "st_net.VddIn", "st_net.VssIn" \ + , "st_net.VddInFromHur", "st_net.VssInFromHur" + ) + +################ +##### Inst ##### +################ +class Inst : + + ################ + ##### Init ##### + ################ + def __init__ ( self, model, name = None, map = {}, cell = None ) : + global MODELMAP, CELLS, FRAMEWORK + + from st_model import MODELMAP, CELLS, FRAMEWORK + from util_Place import UNPLACED, NOSYM + + if not cell : cell = CELLS[-1] + + ##### Virtual library ##### + global BV + from st_parser import BV + if BV == [] : InitBV() + + if model in BV : model, self._inout = GetRealModel ( model ) + + ##### Attributes of the instance ##### + self._model = model.lower() + self._st_cell = cell + self._hur_instance = None + self._plac = UNPLACED + self._map = map + + ##### Name of the instance ###### + if not name : + name = "instance%d_%s" % ( cell._NB_INST, self._model ) + cell._NB_INST += 1 + self._name = name + + ##### The instance is put in the instances' list of the cell ##### + cell._st_insts.append ( self ) + + ##### Errors ##### + # Error : if the model is not a string + if type ( model ) != types.StringType : raise "\n[Stratus ERROR] Inst : the model must be described in a string.\n" + # Warning : the model can not contain capitalized letters + if re.search ( "[A-Z]", model ) : + print "[Stratus Warning] Inst : Upper case letters are not supported, the name", model, "is lowered." +# model = model.lower() + # Error : spaces are forbidden + if re.search ( " ", model ) : + err = "\n[Stratus ERROR] Inst : " + name + " the name of the model \"" + model + "\" can not contain a space.\n" + raise err + if name : + if re.search ( " ", name ) : + err = "\n[Stratus ERROR] Inst : \"" + name + "\" the name of the instance can not contain a space.\n" + raise err + # Warning : the name can not contain capitalized letters + if re.search ( "[A-Z]", name ) : + print "[Stratus Warning] : Upper case letters are not supported, the name", name, "is lowered." + name = name.lower () + + # Error : if map[pin] is not a net + if map : + for pin in map : + if str ( map[pin].__class__ ) not in NET : + err = "\n[Stratus ERROR] Inst : \"" + name + "\" one argument is not a net : " + err += "pin is : " + pin + " and is associated to : " + if map[pin] : err += str(map[pin]) + else : err += "None" + err += "\n" + raise err + + ##### MasterCell ##### + self._hur_masterCell = FRAMEWORK.getCell ( self._model, CRL.Catalog.State.Views ) + + self._st_masterCell = None + for c in CELLS[0]._underCells : + if self._model == c._name : + self._st_masterCell = c + break + if not( self._hur_masterCell or self._st_masterCell ) : print "\n[Stratus Warning] Inst : no master cell found for instance" + self._name + + # Creation of the hurricane instance + if CELLS[0]._hur_plug : self.create_hur_inst ( model ) + + ############## + ### Delete ### + ############## + def Delete ( self ) : + # Erasement of the references to the instance + for i in range ( len ( self._st_cell._st_insts ) ) : + if self._st_cell._st_insts[i] == self : + del self._st_cell._st_insts[i] + break + # Erasement of the hurricane instance associated + if self._hur_instance : self._hur_instance.Delete() + + ############################################## + ##### Creation of the hurricane instance ##### + ############################################## + def create_hur_inst ( self, model ) : + if not self._hur_masterCell : + #self._hur_masterCell = FRAMEWORK.getCell ( self._model, CRL.Catalog.State.Views ) + self._hur_masterCell = FRAMEWORK.getCell ( model, CRL.Catalog.State.Views ) + + if not self._hur_masterCell : + err = "\n[Stratus ERROR] HurricanePlug : Problem of master cell " + model + ".\nCheck model name and/or CRL_IN_LO/CRL_IN_PH variables .\n" + raise err + + if not self._st_masterCell : + if MODELMAP.has_key ( str ( self._hur_masterCell ) ) : + self._st_masterCell = MODELMAP[str ( self._hur_masterCell )] + else : + self._st_masterCell = Model ( str ( self._hur_masterCell.getName() ), hurCell = self._hur_masterCell ) + + if not self._st_cell._hur_cell : + err = "\n[Stratus ERROR] HurricanePlug : Problem of hurricane cell.\nTry to contact Coriolis team.\n" + raise err + + inst = Instance ( self._st_cell._hur_cell + , self._name + , self._hur_masterCell + ) + # The hurricane instance is connected to the stratus instance + self._hur_instance = inst + + ##### Connection ##### + for pin in self._map : + mapNet = self._map[pin] + + ### Virtual library ### + if "_inout" in self.__dict__ : pin = self._inout[pin] + + # Error : if there is a space in the name of the pin (usually done at the end of the pin ...) + if re.search ( " ", pin ) : + err = "\n[Stratus ERROR] Inst : " + self._name + " the keys of the connection map can not contain a space : \"" + pin + "\".\n" + raise err + + # Error : if the net to connect does not have it's arity defined + if not ( mapNet._arity ) : + err = "\n[Stratus ERROR] Inst : " + self._name + " : the size of " + mapNet._name + " has not been defined properly.\n" + raise err + + wrong_pin = 1 + for net in self._hur_masterCell.getExternalNets(): + if ( pin == str(net.getName()) ) or re.search ( "%s\(" % pin, str(net.getName()) ) : + wrong_pin = 0 + break + + # Error : if the pin doesn't exist in the model's ports + if wrong_pin : + err = "\n[Stratus ERROR] Inst : " + str(self._name) + " : port " + pin \ + + " does not exist in model " + str(self._hur_masterCell.getName()) + ". Pins are :" + for pin in self._hur_masterCell.getExternalNets(): + err += str ( pin.getName() ) + err += "," + sea = re.search ( "(.*),$", err ) + if not sea : err += "No pins found ..." + else : err = sea.group(1) + raise err + + # Error : if the arities of the nets don't correspond + tabPins = self._st_masterCell._st_ports + self._st_masterCell._st_cks + self._st_cell._st_vdds + self._st_cell._st_vsss + for net in tabPins : + if net._name == pin : + if net._arity != mapNet._arity : + err = "\n[Stratus ERROR] Inst : " + str(self._name) + " : The arity of the net " + mapNet._name + " " + str(mapNet._arity) \ + + " does not correspond to the arity of the port of the cell : "+ net._name + " " + str(net._arity) + ".\n" + raise err + + # If the port of the masterCell doesn't have a LSB which is 0 + lsb = 0 + if mapNet._arity > 1 : + netBus = None + while not ( netBus ) : + netBus = self._hur_masterCell.getNet ( pin.lower() + "(" + str ( lsb ) + ")" ) + lsb += 1 + if lsb > 20 : # value chosen in order to avoid infinite loop in case of a problem (may be higher) + err = "\n[Stratus ERROR] Inst : " + str(self._name) + " : Probem of map, check the arities of your nets.\n" + raise err + if lsb : lsb -= 1 + + ### Connection ### + if mapNet._real_net : realNet = mapNet._real_net + else : realNet = mapNet + + # range 1: given the indice's net + nbit1 = mapNet._ind - realNet._ind + # range 2: deal with reverse nets + if ( '_reverse' in mapNet.__dict__ ) and ( mapNet._reverse ) : + nbit2 = nbit1 - mapNet._arity + pas = -1 + else : + nbit2 = nbit1 + mapNet._arity + pas = 1 + + j = 0 + for i in range ( nbit1, nbit2, pas ) : + # If the net has to be concatened + if ( realNet._to_cat ) and ( realNet._to_cat[i] ) : + net = realNet._to_cat[i][0] + bit = realNet._to_cat[i][1] + if net._real_net : net = net._real_net + + # If the net which is concatened is an alias + if ( net._alias ) and ( net._alias[bit] ) : + netA = net._alias[bit].keys()[0] + bitA = net._alias[bit][netA] + if net._real_net : netA = netA._real_net + + hurNet = netA._hur_net[bitA-net._ind] + else : + hurNet = net._hur_net[bit-net._ind] + + # If the net is an alias + elif ( realNet._alias ) and ( realNet._alias[i] ) : + net = realNet._alias[i].keys()[0] + bit = realNet._alias[i][net] + if net._real_net : net = net._real_net + + hurNet = net._hur_net[bit+net._ind] + + else : + hurNet = realNet._hur_net[i] + + #if mapNet._arity == 1 : tempNet = self._hur_masterCell.getNet ( pin.lower() ) + if mapNet._arity == 1 : tempNet = self._hur_masterCell.getNet ( pin ) + else : tempNet = self._hur_masterCell.getNet ( pin.lower() + "(" + str(j+lsb) + ")" ) + j += 1 + + if not ( tempNet ) : + err = "\n[Stratus ERROR] Inst : Problem in map. Check that the arities of your nets are correct.\n" + raise err + + plug = self._hur_instance.getPlug ( tempNet ) + plug.setNet ( hurNet ) + + # In order to see the ring + if str ( realNet.__class__ ) not in ALIM_NET : CRL.createPartRing ( self._st_cell._hur_cell, hurNet.getName() ) + + # Error message if the connection is not correct (detection before vst driver) + # Not for vdd/vss in case of utilisation of SetGlobal + # The detection is done with vst driver in this case ... + for plug in self._hur_instance.getUnconnectedPlugs(): + if plug.getMasterNet().getType() not in ( TypePOWER, TypeGROUND ) : + name = str(plus.getMasterNet().getName()) + chaine = re.search ( "(.*)\(", name ) + if chaine : name = chaine.group(1) + + err = "\n[Stratus ERROR] Inst : plug " + name + " of instance " + self._name + " must be connected.\n" + raise err + + ############## + ### Prints ### + ############## + def printInstance ( self ) : + print " => model", self._model + print " => map" + for pin in self._map : + n = self._map[pin] + if n._to_merge : n = n._to_merge[0][0] + print " ", pin, "->", n._name + + def printMap ( self ) : + print "Map:", self._name + for pin in self._map : + print " ", pin, self._map[pin]._name + +######################### +#### SetCurrentModel #### +######################### +def SetCurrentModel ( instance ) : + global CELLS + from st_model import CELLS + + if not instance : + err = "\n[Stratus ERROR] SetCurrentModel : argument given does not exist.\n" + raise err + cell = instance._st_masterCell + + if not cell : + err = "\n[Stratus ERROR] SetCurrentModel : cannot find model for instance " + str ( getName ( instance ) ) + ".\n" + raise err + + CELLS.append ( cell ) + + return cell diff --git a/stratus1/src/stratus/st_model.py b/stratus1/src/stratus/st_model.py new file mode 100644 index 00000000..5d74fdd5 --- /dev/null +++ b/stratus1/src/stratus/st_model.py @@ -0,0 +1,1123 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_model.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * +import CRL + +import re, types, string + +FRAMEWORK = None +EDITOR = None + +MODELMAP = {} +CELLS = [] + +STRATUS = 100 +LOGICAL = CRL.Catalog.State.Logical +PHYSICAL = CRL.Catalog.State.Physical +VIEWS = CRL.Catalog.State.Views + +def setEditor ( editor ): + global EDITOR + + EDITOR = editor + return + +####################### +##### Class Model ##### +####################### +class Model : + + ########################## + ##### Initialisation ##### + ########################## + def __init__ ( self, nom, param = {}, hurCell = None, hurricane_plug = True ) : + global FRAMEWORK, CELLS + + self._name = nom + self._param = param + + self._hur_cell = hurCell + + self._st_insts = [] # Tab : list of the instances + self._st_ports = [] # Tab : list of the nets + self._st_sigs = [] # Tab : list of the nets + + self._st_partsigs = [] # Tab : list of the partial nets + self._st_merge = [] # Tab : list of the nets to merge, in order to have them in the right order + + self._hierarchy = 0 # Modified in ModelCreation + + self._TAB_NETS_OUT = [] + self._TAB_NETS_CAT = [] + self._NB_INST = 0 + + # List of the generators used for overload + self._and = 'A2' + self._or = 'O2' + self._xor = 'Xr2' + self._not = 'Inv' + self._buff = 'Buf' + self._reg = 'Sff1' + # Stratus generators + self._mux = 'Smux' + self._shift = 'Shifter' + self._comp = 'Comp' + # Arithmetic generators + self._add = 'Slansky' + self._sub = 'Sub' + self._mult = 'Multiplier' + self._div = None + + self._signed = True + self._extended = False + + self._model_map = {} + + # List of the under-cells of a cell + self._underCells = {} +# self._tabPlacement = [] + # Instance reference for placement + self._insref = None + + # Place and Route + self._nb_alims_verticales = 0 + self._nb_pins = 0 # to number the pins of the core + self._nb_vdd_pins = 0 # to number the pins vdd of the core + self._nb_vss_pins = 0 # to number the pins vss of the core + self.standard_instances_list = [] + self.pad_north = [] # list to save the pads names + self.pad_south = [] + self.pad_east = [] + self.pad_west = [] + + # Creation of the database + if not FRAMEWORK : + #Initialize() + FRAMEWORK = CRL.getAllianceFramework() + + self._st_vdds = [] + self._st_vsss = [] + + if hurCell : + from st_net import VddInFromHur + from st_net import VssInFromHur + + netVdd = iter(hurCell.getPowerNets()).next() + netVss = iter(hurCell.getGroundNets()).next() + if netVdd != None : self._st_vdds.append ( VddInFromHur ( netVdd ) ) + else : print "[Stratus Warning] : Cell", self._name, "does not have a vdd port." + if netVss != None : self._st_vsss.append ( VssInFromHur ( netVss ) ) + else : print "[Stratus Warning] : Cell", self._name, "does not have a vss port." + + self._st_cks = [] + + if not hurCell : + # List of the cells + CELLS.append ( self ) + # List of the undercells + if CELLS[0] != self : + CELLS[0]._underCells[self] = 0 +# CELLS[0]._tabPlacement.append ( self ) + + self._hur_plug = hurricane_plug + + # HurricanePLug if : no hurCell, in mode hurricane plug (i.e. hurricane_plug and hurricane_plug of the masterCell) + if ( not hurCell ) and ( hurricane_plug ) : + if CELLS[0] == self : + self.HurricanePlug() + else : + if CELLS[0]._hur_plug : + self.HurricanePlug() + + ##### Delete ##### + def Delete ( self ) : + UpdateSession.open() + + under_cells = self._underCells + self._hur_cell.Delete() + for cell in under_cells : cell._hur_cell.Delete() + + UpdateSession.close() + + ##################################################### + ##### Initialisation of attributes for the cell ##### + ##################################################### + def InitGraph ( self ) : + self._graph = True + + # External nets + for net in self._st_ports : + net._st_inst_in = None + net._st_insts_out = [] + net._covered = False + + # Internal nets + for net in self._st_sigs : + net._st_inst_in = None + net._st_insts_out = [] + net._covered = False + + # Part nets + for pnet in self._st_partsigs : + pnet._st_inst_in = None + pnet._st_insts_out = [] + pnet._covered = False + + # Instances + for inst in self._st_insts : + inst._st_nets_in = [] + inst._st_nets_out = [] + + # Initialisation of instances and nets + self.initNet ( inst ) + self.initInst ( inst ) + + ######################################################## + ##### Initialisation of the attributes of the nets ##### + ######################################################## + def initNet ( self, instance ) : + # For each pin + for pin in instance._map : + # Check if the pin is an output or an input + direct = "" + direct = self.getDirect ( instance._model, pin ) + + # Get the net connected to this pin + if instance._map[pin]._to_merge : mapNet = instance._map[pin]._to_merge[0][0] + else : mapNet = instance._map[pin] + + if len ( instance._map[pin]._to_merge ) > mapNet._arity : + mapNet._real_arity = len ( instance._map[pin]._to_merge ) + mapNet._inverse_merge = instance._map[pin] + + # Initialisation + if direct == 'input' : + if mapNet._real_net : + mapNet = mapNet._real_net + + if '_st_insts_out' not in mapNet.__dict__ : mapNet._st_insts_out = [] + + if instance not in mapNet._st_insts_out : mapNet._st_insts_out += [instance] + + elif direct == 'output' : # FIXME _real_net not taken care of + mapNet._st_inst_in = instance + + ############################################################# + ##### Initialisation of the attributes of the instances ##### + ############################################################# + def initInst ( self, instance ) : + # For each pin + for pin in instance._map : + # Check if the pin is an output or an input + direct = "" + direct = self.getDirect ( instance._model, pin ) + + # Get the net connected to this pin + if instance._map[pin]._to_merge : mapNet = instance._map[pin]._to_merge[0][0] + else : mapNet = instance._map[pin] + + # Initialisation + if direct == 'input' : instance._st_nets_in += [mapNet] + elif direct == 'output' : instance._st_nets_out += [mapNet] + + ########################################### + ##### Returns the direction of a port ##### + ########################################### + def getDirect ( self, model, pin ) : + global FRAMEWORK + + hurCell = FRAMEWORK.getCell ( model, CRL.Catalog.State.Views ) + + stCell = None + if not hurCell : + for c in self._underCells : + if c._name == model : + stCell = c + break + + if not hurCell and not stCell : + raise "\nError : no cell found with model %s.\n" % model + + # Hurricane cell found: + if hurCell : + found = False + for netLoc in hurCell.getExternalNets(): + net = netLoc.getElement() + direction = net.getDirection() + name = str(net.getName()) + + if net.getType() in ( TypePOWER, TypeGROUND, TypeCLOCK ) : + found = True + continue + + chaine = re.search ( "(.*)\([0-9]+\)", name ) + if chaine : name = chaine.group(1) + + if name == pin : + found = True + if direction == DirectionOUT : return "output" + elif direction == DirectionIN : return "input" + else : raise "\nError : unable to find direction of port %s in model %s. Direction is %d\n" % ( pin, model, direction ) + + if not found : raise "\nError : unable to find port %s in model %s.\n" % ( pin, model ) + + # Stratus cell found: + elif stCell : + found = False + + for net in stCell._st_vdds : + if net._name == pin : + found = True + break + + for net in stCell._st_vsss : + if net._name == pin : + found = True + break + + for net in stCell._st_cks : + if net._name == pin : + found = True + break + + # _st_ports i.e. not alimentations and not clock + for net in stCell._st_ports : + if net._name == pin : + found = True + if net._direct == "OUT" : return "output" + elif net._direct == "IN" : return "input" + else : raise "\nError : unable to find direction of port %s in model %s.\n" % ( pin, model ) + + if not found : + ports = "" + for net in stCell._st_ports : ports += net._name + "," + raise "\nError : unable to find port %s in model %s.\nPorts are : %s\n" % ( pin, model, ports ) + + else : + err = "\n[ERROR] InitGraph : no model named " + model + " in the database.\n" + raise err + + ############################# + ##### Print of the cell ##### + ############################# + def Print ( self ) : + print "################## The Cell ##################" + for inst in self._st_insts : + print " * inst name :", inst._name + print " inst model :", inst._model + for pin in inst._map : + if pin != 'vdd' and pin != 'vss' : + net = inst._map[pin] + print " pin :", pin, "net :", net._name, "with arity :", net._arity + if net._to_merge : + net = inst._map[pin]._to_merge[0][0] + print " net merged with :", net._name, "with arity :", net._arity + + ######################### + def PrintGraph ( self ) : + if "_graph" not in self.__dict__ : + err = "\n[Stratus ERROR] PrintGraph : The graph does not exist. Use initGraph before.\n" + raise err + else : + if self._graph == False : + err = "\n[Stratus ERROR] PrintGraph : The graph does not exist. Use initGraph before.\n" + raise err + + print "################## Cell's Graph features ##################" + for inst in self._st_insts : + print " => inst name :", inst._name, "( model :", inst._model, ")" + print " inst st_nets_in :" + for net in inst._st_nets_in : print " ", net._name + print " inst st_nets_out :" + for net in inst._st_nets_out : print " ", net._name + for port in self._st_ports : + print " => port name :", port._name + if port._st_inst_in : print " port _st_inst_in :", port._st_inst_in._name + print " port _st_insts_out :" + for p in port._st_insts_out : print " ", p._name + for sig in self._st_sigs : + print " => sig name :", sig._name + if sig._st_inst_in : print " sig _st_inst_in :", sig._st_inst_in._name + print " sig _st_insts_out :" + for s in sig._st_insts_out : print " ", s._name + for psig in self._st_partsigs : + print " => part sig name :", psig._name + if '_st_inst_in' in psig.__dict__ and psig._st_inst_in: print " part sig _st_inst_in :", psig._st_inst_in._name + if '_st_insts_out' in psig.__dict__ : + print " part sig _st_insts_out :" + for s in psig._st_insts_out : print " ", s._name + + ##################### + ##### overloard ##### + ##################### + ##### __getattr ##### +# def __getattr__ ( self, attr ) : + + ##### __str ##### + def __str__ ( self ) : + s = "Model" + str ( self._hur_cell ) + return s + + ######################## + ##### VLSI Methods ##### + ######################## + ##### Interface ##### + def Interface ( self ) : + print "[Stratus Warning] : Execution of empty Interface method for", self._name, "." + + ##### Netlist ##### + def Netlist ( self ) : + print "[Stratus Warning] : Execution of empty Netlist method for", self._name, "." + pass + + ##### Layout ##### + def Layout ( self ) : + print "[Stratus Warning] : Execution of empty Layout method for", self._name, "." + pass + + ##### Vbe ##### + def Vbe ( self ) : + self._vbe = True + + ##### View : in order to see the in the editor ##### + def View ( self, stopLevel=1, message="Status stop point" ) : + global EDITOR + + if not self._hur_cell : + err = "\n[Stratus ERROR] View : Hurricane Cell does not exist.\nCheck CRL_IN_LO/CRL_IN_PH variables.\n" + raise err + + if EDITOR: + EDITOR.setCell ( self._hur_cell ) + EDITOR.fit () + Breakpoint.stop ( stopLevel, message ) + + ##### Save : in order to create the output files ##### + def Save ( self, views = 0, fileName = None ) : + global FRAMEWORK + global CELLS + + if views == STRATUS : + self.exportStratus ( fileName ) + + else : + UpdateSession.open() + + hurCell = self._hur_cell + + if str ( hurCell.getName() ) != "__Scratch__" : + FRAMEWORK.saveCell ( hurCell, views|CRL.Catalog.State.Logical ) + + if len ( CELLS ) == 0 : + err = "\n[Stratus ERROR] Save : CELLS stack is empty.\n" + raise err + + CELLS.pop() + + UpdateSession.close() + + ##### Simul : in order to use simulation tool ##### + def Simul ( self, name = None, tool = 'asimut' ) : + from utils import runpat + + if not name : name = self._name + + if tool == 'asimut' : runpat ( self._name, name, '-l 1 -p 100 -zerodelay -nocheckdriver -nostrict -bdd -nowarning' ) + else : raise 'not implemented yet' + + ##### Create a stratus file given the database ##### + def exportStratus ( self, fileName ) : + + ## Cat formating ## + def catName ( net, tableau ) : + + name = "Cat ( " + paire = tableau[-1] + if paire : + net1 = paire[0] + bit1 = str(paire[1]) + else : + net1 = net + bit1 = str(len(tableau)-1) + + for i in range ( len(tableau)-2, -1, -1 ) : + change = False + if tableau[i] and not tableau[i+1] : + change = True + elif not tableau[i] and tableau[i+1] : + change = True + elif tableau[i] and tableau[i+1] : + if tableau[i][0] != tableau[i+1][0] : + change = True + + if change : + if tableau[i+1] : bit2 = str(tableau[i+1][1]) + else : bit2 = str(i+1) + + name += "self." + if int(bit2) == int(net1._ind) and int(bit1) == (net1._arity-1) : + name += net1._name + else : + name += net1._name + name += "[" + name += bit1 + name += ":" + name += bit2 + name += "]" + + name += ", " + + if tableau[i] : net1 = tableau[i][0] + else : net1 = net + + if tableau[i] : bit1 = str(tableau[i][1]) + else : bit1 = str(i) + + if tableau[0] : + bit2 = str(tableau[0][1]) + else : + bit2 = "0" + + name += "self." + if int(bit2) == int(net1._ind) and int(bit1) == (net1._arity-1) : + name += net1._name + else : + name += net1._name + name += "[" + name += bit1 + name += ":" + name += bit2 + name += "]" + + name += " )" + + return name + + ######################### + nom = str(self.__class__) + chaine = re.search ( "[^\.]*\.(.*)", nom ) + nom = chaine.group(1) + + if not fileName : fileName = nom + "_created" + fileName += ".py" + + file = open ( fileName, "w+" ) + + file.write ( "#!/usr/bin/python\n\n" ) + file.write ( "from stratus import *\n\n" ) + + file.write ( "class %s ( Model ) :\n\n" % nom ) + + ##### Interface ##### + file.write ( " def Interface ( self ) :\n\n" ) + + for net in self._st_ports : + if net._direct == "IN" : classe = "SignalIn" + elif net._direct == "OUT" : classe = "SignalOut" + elif net._direct == "INOUT" : classe = "SignalInOut" + + file.write ( " self.%s = %s ( \"%s\", %d )\n" % ( net._name, classe, net._name, net._arity ) ) + file.write ( "\n" ) + + for ck in self._st_cks : + if ck._ext: + file.write ( " self.%s = CkIn ( \"%s\" )\n" % (ck._name, ck._name) ) + + file.write ( " self.vdd = VddIn ( \"vdd\" )\n" ) + file.write ( " self.vss = VssIn ( \"vss\" )\n" ) + file.write ( "\n" ) + + ##### Netlist ##### + file.write ( " def Netlist ( self ) :\n\n" ) + + # Signals + for net in self._st_sigs : + if net._to_merge : + towrite = False + for paire in net._to_merge : + if paire == 0 : towrite = True + if not towrite : continue + file.write ( " self.%s = Signal ( \"%s\", %d )\n" % ( net._name, net._name, net._arity ) ) + file.write ( "\n" ) + + # Generate + for cell in CELLS[0]._underCells : + if CELLS[0]._underCells[cell] == 1 : + classe = str(cell.__class__) + nom = cell._name + param = cell._param + + # Gestion of libraries with specific treatment + chaine = re.search ( "(.*)\.([^\.]*)", classe ) + if chaine : + fichier = chaine.group(1) + if re.search ( "dpgen_", fichier ) or re.search ( "st_", fichier ) : + classe = chaine.group(2) + # Special treatment for virtual library + if classe == "Bool" : + nom = cell._name + classe = cell._param['model'] + param = cell._param + del param['model'] + del param['realModel'] + + classe = string.upper(classe[0]) + classe[1:] #FIXME !!! + if re.search ( "(.*)\.([^\.]*)", classe ) : # ArithLib generator + classe = string.lower(classe[0]) + classe[1:] + + file.write ( " Generate ( \"%s\", \"%s\", param = %s )\n" % ( classe, nom, param ) ) + file.write ( "\n" ) + + # Instances + for inst in self._st_insts : + #chaine = re.search ( "([^_]*)_(.*)", inst._name ) #XTOF FIXME !!! + #instName = chaine.group(1) #XTOF FIXME !! + file.write ( " self.%s = Inst ( \"%s\"\n" % ( inst._name, inst._model ) ) + file.write ( " , \"%s\"\n" % inst._name ) + file.write ( " , map = { " ) + + # Map + for pin in inst._map : + toto = False + tata = False + + netInMap = inst._map[pin] + nom = "self." + netInMap._name + + # <= + if netInMap._to_merge : + oneperone = True + for i in range ( len ( netInMap._to_merge ) ) : + paire = netInMap._to_merge[i] + + if paire : + net = paire[0] + if i > 0 : + if netInMap._to_merge[i-1] != 0 : + netbefore = netInMap._to_merge[i-1][0] + else : + oneperone = False + break + if net != netbefore : + oneperone = False + break + if paire[1] != i : + oneperone = False + break + + else : + toto = True + oneperone = False + break + + # "easy" case : 1 per 1 corresponding + if oneperone : + netInMap = netInMap._to_merge[0][0] + nom = "self." + netInMap._name + + # else : Cat of the different signals + else : + nom = catName ( netInMap, netInMap._to_merge ) + + # Cat + if netInMap._to_cat : + tata = True + nom = catName ( netInMap, netInMap._to_cat ) + + if toto and tata : print "Attention est ce un cas bien gere ???" + + if pin == inst._map.keys()[0] : file.write ( "\"%s\" : %s\n" % ( pin, nom ) ) + else : file.write ( " , \"%s\" : %s\n" % ( pin, nom ) ) + + file.write ( " }\n" ) + file.write ( " )\n\n" ) + + ##### End ##### + file.close () + + #### Quit : to quit the current cell without saving ##### + def Quit ( self ) : + global CELLS + + CELLS.pop () + + ######################################### + ##### GetModelName : Class's method ##### + ######################################### + def GetModelName ( param ) : + return None + GetModelName = staticmethod ( GetModelName ) + + ######################################### + ##### GetParam : Class's method ##### + ######################################### + def GetParam () : + return None + GetParam = staticmethod ( GetParam ) + + ############### + ##### Set ##### + ############### + def SetAnd ( self, model ) : self._and = model + def SetOr ( self, model ) : self._or = model + def SetXor ( self, model ) : self._xor = model + def SetNot ( self, model ) : self._not = model + + def SetBuff ( self, model ) : self._buff = model + def SetReg ( self, model ) : self._reg = model + def SetMux ( self, model ) : self._mux = model + def SetShift ( self, model ) : self._shift = model + def SetComp ( self, model ) : self._comp = model + + def SetAdd ( self, model ) : self._add = model + def SetMult ( self, model ) : self._mult = model + def SetDiv ( self, model ) : self._div = model + + def SetSigned ( self, model ) : self._signed = model + def SetExtended ( self, model ) : self._extended = model + + ############################# + ##### Creation of model ##### + ############################# + def ModelCreation ( self, modele, modele2, dict, hierarchy, realModele = None, inOut = None ) : + global CELLS + + from st_parser import BVg + + ## Virtual library ## + from st_bool import Bool + + ## Stratus generators ## + from st_mux import Smux + from st_shifter import Shifter + from st_comp import Comp + from st_const import Constant + from st_extend import Extend + + from st_slansky import Slansky + from st_slansky import Sub + from st_mult import Multiplier + + ## Genlib ## + from dpgen_Shifter import DpgenShifter + from dpgen_Shrot import DpgenShrot + from dpgen_Nul import DpgenNul + from dpgen_RAM import DpgenRam + from dpgen_ROM2 import DpgenRom2 + from dpgen_ROM4 import DpgenRom4 + from dpgen_ADSB2F import DpgenAdsb2f + from dpgen_RF1 import DpgenRf1, DpgenRf1d, DpgenRf1r0, DpgenRf1dr0, DpgenFifo + from dpgen_RF2 import DpgenRf2, DpgenRf2d, DpgenRf2r0, DpgenRf2dr0 + from dpgen_Regular import DpgenAnd2, DpgenAnd3, DpgenAnd4, DpgenBuff, DpgenBuse, DpgenConst, DpgenDff, DpgenDfft, DpgenInv, DpgenMux2, DpgenNand2, DpgenNand2mask, DpgenNand3, DpgenNand4, DpgenNbuse, DpgenNmux2, DpgenNor2, DpgenNor2mask, DpgenNor3, DpgenNor4, DpgenOr2, DpgenOr3, DpgenOr4, DpgenSff, DpgenSfft, DpgenXnor2, DpgenXnor2mask, DpgenXor2 + + from util_Gen import F_MSB_FIRST + + if type ( dict ) != types.DictType : + raise "\n[Stratus ERROR] Inst : instanciation of a user's defined generator. The methods' arguments must be dictionnaries.\n" + + ##### Creation of the instance ##### +# dict['flags'] = F_MSB_FIRST # When vst driver permits to do F_LSB_FIRST or F_LSB_FIRST TODO + + ## Virtual library ## + if modele in BVg : + dict['model'] = modele.lower() + dict['realModel'] = realModele + + instCell = Bool ( modele2, dict, inOut ) + + ## Generator ## + elif re.search ( "\.", modele ) : + chaine = re.search ( "(.*)\.([^\.]*)$", modele ) + + ficName = chaine.group(1) + className = chaine.group(2) + + # Roselyne : pour prendre en compte les modeles recursifs + import sys + #moduleClass = __import__ ( ficName, globals(), locals(), [className] ) + #modeleClass = getattr ( moduleClass, className ) + try : + modeleClass = getattr ( sys.modules['__main__'], className ) + except AttributeError : + moduleClass = __import__ ( ficName, globals(), locals(), [className] ) + modeleClass = getattr ( moduleClass, className ) + # fin Roselyne + + instCell = modeleClass ( modele2, dict ) + + else : + instCell = eval ( "%s ( \"%s\", %s )" % ( modele, modele2, str(dict) ) ) + + ## MAJ of the hierarchy ## + instCell._hierarchy = hierarchy + + ##### Methods ##### + if ( self._hur_cell ) and ( not instCell._hur_cell ) : instCell.HurricanePlug() + + instCell.Interface() + instCell.Netlist() + + if ( 'clean' in dict ) and ( dict['clean'] != False ) : + if 'interactive' not in dict : dict['interactive'] = False + instCell.Clean ( dict['interactive'], dict['clean'] ) + + if ( 'behavioral' in dict ) and ( dict['behavioral'] == True ) : + instCell.Vbe() + + if instCell._hur_cell : + v = 0 + if ( 'physical' in dict ) and ( dict['physical'] == True ) : + instCell.Layout() + v = CRL.Catalog.State.Physical + instCell.Save( v|CRL.Catalog.State.Logical ) + + else : + instCell.Quit() + + if CELLS[0] != instCell : CELLS[0]._underCells[instCell] = hierarchy + + return instCell + + ################################################################# + ##### HurricanePlug : in order to create the hurricane cell ##### + ################################################################# + def HurricanePlug ( self ) : + global FRAMEWORK, CELLS + + if self._hur_cell : + print "[Stratus Warning] : The stratus cell already exists." + return + + self._hur_plug = True + + ##### Creation of all the under cells ##### + # Initialisation of the max depth + max_depth = 0 + for keyCell in self._underCells : + if self._underCells[keyCell] > max_depth : max_depth = self._underCells[keyCell] + # Creation from the leaf to the top cell + while max_depth : + for keyCell in self._underCells : + if self._underCells[keyCell] == max_depth : + if not FRAMEWORK.getCell ( keyCell._name, CRL.Catalog.State.Views ) : + CELLS.append ( keyCell ) + keyCell.CellHurCreation() + max_depth -= 1 + + # Creation of the top cell + CELLS.append ( self ) + self.CellHurCreation() + + ##### CellHurCreation ##### + def CellHurCreation ( self ) : + global FRAMEWORK, CELLS + + # The cell + hurCell = FRAMEWORK.createCell ( self._name ) + hurCell.setTerminal ( 0 ) + + self._hur_cell = hurCell + + MODELMAP [ str ( self._hur_cell ) ] = self + + # The nets + for net in self._st_ports : net.create_hur_net() + for net in self._st_sigs : net.create_hur_net() + + + for net in self._st_cks : net.create_hur_net() + + for net in self._st_vdds : net.create_hur_net() + for net in self._st_vsss : net.create_hur_net() + + # The instances and the connection + for inst in self._st_insts : inst.create_hur_inst ( inst._model ) + + # Merge + for net in self._st_merge : net.hur_merge() + + if ( self != CELLS[0] ) and ( self._st_insts ) : # Layout done if HurricanePlug after Netlist method + #self.Layout() # FIXME trouver une raison de le faire ou pas : instances placees ou pas ... HurricanePlug ne doit plus marcher avec placement A VERIFIER 14/01/08 + if self._st_insts[0]._hur_instance.getPlacementStatus() : self.Save ( CRL.Catalog.State.Physical ) + else : self.Save ( CRL.Catalog.State.Logical ) + else : + self.Quit() + + #################### + ##### Clean Up ##### + #################### + def Clean ( self, interactive = False, tab_name_net = [] ) : + + # Hurricane cell + hurricane_cell = self._hur_cell + + # Useful for print + TAB_NETS = [] + TAB_INSTS = [] + cpt_inst_del = 0 + cpt_net_del = 0 + + ##### Tabs initialisation ##### + net_entree = [] + net_sortie = [] + net_interne = [] + + for net in hurricane_cell.getNets(): + if net.getDirection() == DirectionUNDEFINED : net_interne.append ( net ) + elif net.getDirection() == DirectionIN : net_entree.append ( net ) + elif net.getDirection() == DirectionOUT : net_sortie.append ( net ) + + ##### File initialisation ##### + file = [] + + # Output nets put in the file if there are given as arguments + if tab_name_net != True : + for net_name in tab_name_net : + for net in net_sortie : + if net_name == str ( net.getName() ) : + file.insert ( 0, net ) + if interactive : print "Output Net", net, "has to be erased, it is put in the fifo." + + ## Internal nets ## + # Number of plugs of each net : + # if equal to 0 : del net + # if equal to 1 : put net in the file + for net in net_interne : + nb_plugs = self.count_plugs ( net ) + + if nb_plugs == 0 : + if interactive : print "* One net suppressed (a) :", net + TAB_NETS.append ( net.getName () ) + cpt_net_del += 1 + + net.Delete() + + elif nb_plugs == 1 : + if net.getPlugs().next().getMasterNet().getDirection() == DirectionOUT: # output of an instance + if interactive : print "* One net put in the fifo :", net + file.insert ( 0, net ) + + ## Ouput nets ## + # Number of plugs of each net : + # if equal to 0 : del net + for net in net_sortie + net_entree : + cpt_plugs_sor = self.count_plugs ( net ) + if cpt_plugs_sor == 0 : + print "[Stratus Warning] Clean : Interface of", self._name, "changed, net :", net, "is suppressed" + TAB_NETS.append ( net.getName() ) + cpt_net_del += 1 + + net.Delete() + + ##### Algorithm ##### + while len ( file ) > 0 : + net_file = file.pop() + plug = net_file.getPlugs().next() + inst = plug.getInstance() + + # input nets of the instance + plugs_inst = inst.getPlugs() + net_entree_inst = [] + net_sortie_inst = [] + cpt_sortie = 0 + + for plug_de_inst in plugs_inst: + # compute the number of outputs of the instance + if plug_de_inst.getMasterNet().getDirection() == DirectionOUT : + cpt_sortie += 1 + # output nets of the instance put in tab, except for the net being worked on + if net_file != plug_de_inst.getNet() : net_sortie_inst.append ( plug_de_inst.getNet() ) + + if plug_de_inst.getMasterNet().getDirection() == DirectionIN : + # ignore vdd and vss + type = plug_de_inst.getNet().getType() + if type not in ( TypePOWER, TypeGROUND ) : net_entree_inst.append ( plug_de_inst.getNet() ) + + ### Deletion of te instance ### + # If the instance has only one output + if cpt_sortie == 1 : + if interactive : print "* One net suppressed (b) :", net_file + TAB_NETS.append ( net_file.getName() ) + cpt_net_del += 1 + + net_file.Delete() + + if interactive : print "* One instance suppressed (a) :", inst, inst + TAB_INSTS.append(inst.getName()) + cpt_inst_del += 1 + + UpdateSession.open() + inst.Delete() + UpdateSession.close() + + for net_ent in net_entree_inst : + cpt_plugs_in = self.count_plugs ( net_ent ) + if cpt_plugs_in == 0 : + if net_ent in net_entree : + print "[Stratus Warning] Clean : Interface of", self._name, "changed, net :", net_ent, "is suppressed" + + TAB_NETS.append ( net_ent.getName() ) + cpt_net_del += 1 + + net_ent.Delete() + else : + if interactive : print "* One net suppressed (c) : ", net_ent + + TAB_NETS.append ( net_ent.getName() ) + cpt_net_del += 1 + + net_ent.Delete() + + elif cpt_plugs_in == 1 : + if net_ent.getPlugs().next().getMasterNet().getDirection() == DirectionOUT : # is an output net of another instance + if interactive : print "* One net put in the fifo :", net_ent + file.insert ( 0, net_ent ) + + # If the instance has more than one output + elif cpt_sortie >= 2 : + connect = False + for net_sor in net_sortie_inst: + cpt_sor = self.count_plugs ( net_sor ) + if cpt_sor >= 2 : + connect = True # at least one output connected + break + elif cpt_sor == 1 : + if net_sor in net_sortie : + connect = True # at least one output connected + break + + if not ( connect ) : + if interactive : print "* One net suppressed (d) :", net_file + + TAB_NETS.append ( net_file.getName() ) + cpt_net_del += 1 + + net_file.Delete() + + for net_sor in net_sortie_inst : + if net_sor in file : file.remove ( net_sor ) + + if interactive : print "* One net suppressed (e) :", net_sor + TAB_NETS.append ( net_sor.getName() ) + cpt_net_del += 1 + + net_sor.Delete() + + if interactive : print "* One instance suppressed (b) :", inst + TAB_INSTS.append ( inst.getName() ) + cpt_inst_del += 1 + + UpdateSession.open() + inst.Delete() + UpdateSession.close() + + for net_ent in net_entree_inst : + cpt_plugs_in = self.count_plugs ( net_ent ) + + if cpt_plugs_in == 0 : + if net_ent in net_entree : + print "[Stratus Warning] Clean : Interface of", self._name, "changed, net :", net_ent, "is suppressed" + + TAB_NETS.append ( net_ent.getName() ) + cpt_net_del += 1 + + net_ent.Delete() + + else : + if interactive : print "* One net suppressed (f) :", net_ent + + TAB_NETS.append ( net_ent.getName() ) + cpt_net_del += 1 + + net_ent.Delete() + + elif cpt_plugs_in == 1 : + if net_ent.getPlugs().next().getMasterNet().getDirection() == DirectionOUT: # in an output net of another instance + if interactive : print "* One net net put in the fifo :", net_ent + file.insert ( 0, net_ent ) + + else : + if interactive : print "The net", net_file, "can not be delayed, it may be delayed later" + + else : + print "[Warning] Pb in Clean." + + if interactive : + print "" + print "* Number of net suppressed :", cpt_net_del + print "* List of these nets :", TAB_NETS + print "" + print "* Number of instances suppressed :", cpt_inst_del + print "* List of these instance :", TAB_INSTS + print "" + + ############################### + def count_plugs ( self, net ) : + return len(net.getPlugs()) + + + ############################################################################# + ############################## Place and route ############################## + ############################################################################# + def getCore ( self ) : + '''This function returns the instance "core" : the only one which is not a pad''' + + from placeandroute import isPad + + cores = [] + for instance in self._hur_cell.getInstances(): + if not isPad ( instance ): + cores.append ( instance ) + + if len(cores) == 0 : raise "\n[Stratus ERROR] getCore : No core found.\n" + elif len(cores) > 1 : raise "\n[Stratus ERROR] getCore : More than one core found.\n" + + return cores[0] diff --git a/stratus1/src/stratus/st_mult.py b/stratus1/src/stratus/st_mult.py new file mode 100644 index 00000000..98225c88 --- /dev/null +++ b/stratus1/src/stratus/st_mult.py @@ -0,0 +1,212 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_mult.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +from st_mult_matrix import Matrix, Matrix_Inv +from st_func_gen_wallace import genWallace + +class Multiplier ( Model ) : + + def __init__ ( self, name, param ) : + Model.__init__ ( self, name, param ) + + if 'nbit' in param : + self.nbit0 = param['nbit'] + self.nbit1 = param['nbit'] + else : + self.nbit0 = param['nbit0'] + self.nbit1 = param['nbit1'] + + if 'signed' in param : + self._signed = param['signed'] + else : + self._signed = True + + if self.nbit0 < 3 or self.nbit1 < 3 : raise SizeError, 'input arities must be greater than 2' + + self.type = "nr" + self.nType = 1 + + def Interface ( self ) : + self._i0 = SignalIn ( "i0", self.nbit0 ) + self._i1 = SignalIn ( "i1", self.nbit1 ) + + if self._signed : + self._o = SignalOut ( "o", self.nbit0+self.nbit1 ) + else : + self._o = SignalOut ( "o", self.nbit0+self.nbit1-2 ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + size_A = self.nbit0 + 2 + + if self.nbit1 % 2 == 0 : size_B = self.nbit1 / 2 + else : size_B = ( self.nbit1+1 ) / 2 + + if self.nbit1 % 2 == 0 : parite = 1 + else : parite = 0 + + # Signaux internes + sig_nul = Signal ( "sig_nul", 1 ) + opB = Signal ( "opb", 2*size_B-1 ) + NUL = Signal ( "nul", size_B ) + DECA = Signal ( "deca", size_B ) + COMP = Signal ( "comp", size_B ) + + # Matrice de Produits Partiels + matrice_v = [] + for i in range ( size_B ) : + matrice_v_bis = [] + for j in range ( size_A ) : matrice_v_bis += [Signal ( "matrice_%d_%d" % ( i, j ), 1 )] + matrice_v += [matrice_v_bis] + + matrice = [] + position = [] + NEW_matrice = [] + NEW_position = [] + PPmatrix = [] + + sig_nul <= Zero ( 1 ) + + for i in range ( size_B ) : + matrice.append ( [] ) + position.append ( [] ) + + # Premiere ligne + myMap = { 'nul' : NUL[i] + , 'deca' : DECA[i] + , 'comp' : COMP[i] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if i == 0 : + myMap['bminus'] = sig_nul + myMap['b'] = self._i1[i] + myMap['bplus'] = self._i1[i+1] + elif i == ( size_B - 1 ) : + myMap['bminus'] = self._i1[(2*i)-1] + myMap['b'] = self._i1[2*i] + if parite : myMap['bplus'] = self._i1[(2*i)+1] + else : myMap['bplus'] = self._i1[2*i] + else : + myMap['bminus'] = self._i1[(2*i)-1] + myMap['b'] = self._i1[2*i] + myMap['bplus'] = self._i1[(2*i)+1] + + Generate ( 'st_mult_blocs.booth_decoder', 'booth_decoder' ) + Inst ( 'booth_decoder' , map = myMap ) + + for j in range ( size_A ) : + myMap = { 'nul' : NUL[i] + , 'deca' : DECA[i] + , 'comp' : COMP[i] + , 'pp' : matrice_v[i][j] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + + if j == 0 : + myMap['a'] = sig_nul + myMap['b'] = self._i0[j] + elif j > ( self._i0._arity - 1 ) : + myMap['a'] = self._i0[self.nbit0-1] + myMap['b'] = self._i0[self.nbit0-1] + else : + myMap['a'] = self._i0[j-1] + myMap['b'] = self._i0[j] + + Generate ( 'st_mult_blocs.booth_mux', 'booth_mux' ) + Inst ( 'booth_mux', map = myMap ) + + matrice[i] = matrice[i] + [matrice_v[i][j]] + position[i] = position[i] + [1] + + # Adaptation de la matrice de produits partiels pour + MX = Matrix ( matrice, position, COMP, size_A, size_B ) + NEW_matrice = Matrix_Inv ( MX[0],( size_B + 1 ) ) + NEW_position = Matrix_Inv ( MX[1],( size_B + 1 ) ) + + # WALLACE + PPmatrix = genWallace ( self, NEW_matrice, NEW_position ) + + # Conversion pour que la sortie soit en non redondant + #temp_out = Signal ( "tempout", PPmatrix[0] ) + #temp_out <= PPmatrix[1] + PPmatrix[2] + #self._o <= temp_out[self._o._arity-1:0] + self._o <= PPmatrix[1][self._o._arity-1:0] + PPmatrix[2][self._o._arity-1:0] + + def GetModelName ( cls, param ) : + modelName = "multca2_" + + if 'nbit' in param : + modelName += str(param['nbit']) + elif 'nbit1' in param : + if param['nbit0'] != param['nbit1'] : + modelName += str(param['nbit0']) + modelName += "x" + modelName += str(param['nbit1']) + else : + modelName += str(param['nbit0']) + modelName += "bits" + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'nbit0' : 'integer', 'nbit1' : 'integer'} + + GetParam = classmethod ( GetParam ) + diff --git a/stratus1/src/stratus/st_mult_blocs.py b/stratus1/src/stratus/st_mult_blocs.py new file mode 100644 index 00000000..c548b2fd --- /dev/null +++ b/stratus1/src/stratus/st_mult_blocs.py @@ -0,0 +1,99 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_mult_blocs.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class booth_decoder ( Model ) : + def Interface ( self ) : + self.Bminus = SignalIn ( "bminus", 1 ) + self.B = SignalIn ( "b", 1 ) + self.Bplus = SignalIn ( "bplus", 1 ) + self.NUL = SignalOut ( "nul", 1 ) + self.DECA = SignalOut ( "deca", 1 ) + self.COMP = SignalOut ( "comp", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + inv_B = Signal ( "inv_b" ) + inv_Bplus = Signal ( "inv_bplus" ) + inv_Bminus = Signal ( "inv_bminus" ) + + inv_B <= ~self.B + inv_Bplus <= ~self.Bplus + inv_Bminus <= ~self.Bminus + + self.NUL <= ( self.Bplus & self.B & self.Bminus ) | ( inv_B & inv_Bplus & inv_Bminus ) + self.COMP <= self.Bplus & ( inv_B | inv_Bminus ) + self.DECA <= ( inv_B & inv_Bminus & self.Bplus ) | ( inv_Bplus & self.B & self.Bminus ) + + def GetModelName ( cls, param ) : + return "booth_decoder" + GetModelName = classmethod ( GetModelName ) + +class booth_mux ( Model ) : + def Interface ( self ) : + self.A = SignalIn ( "a", 1 ) + self.B = SignalIn ( "b", 1 ) + self.NUL = SignalIn ( "nul", 1 ) + self.COMP = SignalIn ( "comp", 1 ) + self.DECA = SignalIn ( "deca", 1 ) + self.PP = SignalOut ( "pp", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + self.PP <= ( ( ( self.A & self.DECA ) | ( ~self.DECA & self.B ) ) ^ ( self.COMP ) ) & ( ~self.NUL ) + + def GetModelName ( cls, param ) : + return "booth_mux" + GetModelName = classmethod ( GetModelName ) diff --git a/stratus1/src/stratus/st_mult_matrix.py b/stratus1/src/stratus/st_mult_matrix.py new file mode 100644 index 00000000..8482c06e --- /dev/null +++ b/stratus1/src/stratus/st_mult_matrix.py @@ -0,0 +1,106 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./mult_matrix.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +########################################################################################################################### +def Matrix ( matrice, position, sig_comp, size_A, size_B ) : + size_row = size_B + 1 + + for k in range ( size_B ) : + size_line = (2*(size_B - 1)) - 2*k + + if k == 0 : + for kk in range ( size_line ) : + matrice[k] = matrice[k] + [matrice[k][size_A-1]] + position[k] = position[k] + [1] + + elif k == size_B-1 : + position[k] = [0] + position[k] + position[k] = [1] + position[k] + matrice[k] = [0] + matrice[k][:] + matrice[k] = [sig_comp[k-1]] + matrice[k][:] + + else : + position[k] = [0] + position[k] + matrice[k] = [0] + matrice[k] + matrice[k] = [sig_comp[k-1]]+ matrice[k][:] + position[k] = [1] + position[k] + + for kk in range ( size_line ) : + matrice[k]= matrice[k] + [matrice[k][len(matrice[k])-1]] + position[k] = position[k] + [1] + + position.append([]) + matrice.append([]) + + for ii in range ( 2, size_row ) : + for jj in range ( ii - 1 ) : + position[ii] = [0] + [0]+ position[ii] + matrice[ii] = [0] + [0]+ matrice[ii][:] + + position[size_B] = position[size_B] + [1] + matrice[size_B] = matrice[size_B][:] + [sig_comp[k]] + + for jj in range ( size_A-1 ) : + position[ii] = position[ii] + [0] + matrice[ii] = matrice[ii][:] + [0] + + return [matrice,position] + +def Matrix_Inv ( matrice, size_row ) : + matrice_inv = [] + + for i in range ( size_row ) : + matrice_inv.append ([]) + for j in range ( len ( matrice[0] ) ) : + matrice_inv[i] = matrice_inv[i] + [matrice[i][len(matrice[i])-j-1]] + + return(matrice_inv) diff --git a/stratus1/src/stratus/st_mux.py b/stratus1/src/stratus/st_mux.py new file mode 100644 index 00000000..9b746aad --- /dev/null +++ b/stratus1/src/stratus/st_mux.py @@ -0,0 +1,145 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_mux.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class Smux ( Model ) : + + def Interface ( self ) : + + nbit_cmd = self._param['nbit_cmd'] + nbit = self._param['nbit'] + + if nbit_cmd < 1 : raise "\n[Stratus ERROR] mux : the number of bits of the command must be greater than 0.\n" + if nbit < 1 : raise "\n[Stratus ERROR] mux : the number of bits of the inputs must be greater than 0.\n" + + self._cmd = SignalIn ( "cmd", nbit_cmd ) + + self._in_tab = [] + for i in range ( int(pow ( 2, nbit_cmd )) ) : self._in_tab += [SignalIn ( "i%d" % i, nbit )] + + self._q = SignalOut ( "q", nbit ) + + self._vdd = VddIn ( "vdd" ) + self._vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + nbit_cmd = self._param['nbit_cmd'] + nbit = self._param['nbit'] + + # If the command is a bus + ######################### + if nbit_cmd > 1 : + temp = {} + # Input nets are renamed + for i in range ( int(pow ( 2, nbit_cmd )) ) : temp[i] = self._in_tab[i] + # Temporary nets + for i in range ( int(pow ( 2, nbit_cmd )), int(pow ( 2, nbit_cmd + 1 ) - 1) ) : temp[i] = Signal ( "temp_%d" % i, nbit ) + + bit_cmd = 0 + bit_entree = 0 + bit_sortie = pow ( 2, nbit_cmd ) + + for i in range ( nbit_cmd - 1, -1, -1 ) : + for j in range ( int(pow ( 2, i )) ) : + Generate ( "Mx2", "mux_%dbits" % nbit, param = { 'nbit' : nbit } ) + Inst ( "mux_%dbits" % nbit + , map = { 'i0' : temp[2*j+bit_entree] + , 'i1' : temp[2*j+1+bit_entree] + , 'cmd' : self._cmd[bit_cmd] + , 'q' : temp[j+bit_sortie] + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + bit_cmd += 1 + bit_entree += pow ( 2, i ) * 2 + bit_sortie += pow ( 2, i ) + + self._q <= temp[pow ( 2, nbit_cmd + 1 ) - 2] + + # If the command is a 1 bit net + ############################### + else : + Generate ( "Mx2", "mux_%dbits" % nbit, param = { 'nbit' : nbit } ) + Inst ( "mux_%dbits" % nbit + , map = { 'i0' : self._in_tab[0] + , 'i1' : self._in_tab[1] + , 'cmd' : self._cmd + , 'q' : self._q + , 'vdd' : self._vdd + , 'vss' : self._vss + } + ) + + def GetModelName ( cls, param ) : + + modelName = "smux" + + modelName += "_" + modelName += str(param['nbit']) + modelName += "bits" + + modelName += "_" + modelName += str(param['nbit_cmd']) + modelName += "cmdbits" + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'nbit_cmd' : 'integer'} + + GetParam = classmethod ( GetParam ) + diff --git a/stratus1/src/stratus/st_net.py b/stratus1/src/stratus/st_net.py new file mode 100644 index 00000000..73efbc72 --- /dev/null +++ b/stratus1/src/stratus/st_net.py @@ -0,0 +1,1166 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_net.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from Hurricane import * +import CRL + +from st_model import Model +from st_instance import Inst +from st_generate import Generate + +import re, types, inspect + +## Class of nets ## +PORT = ( "st_net.SignalIn", "st_net.SignalOut", "st_net.SignalInOut" \ + , "st_net.SignalUnknown", "st_net.TriState" \ + ) + +##################### +##### Class net ##### +##################### +class net : + + # Creation of the instance : coded for each herited class + def __init__ ( self, nbit ) : pass + + # Deletion of the instance : the same for each net + def Delete ( self ) : + # Erasement of the references to the net + if str ( self.__class__ ) in PORT : + for i in range ( len ( self._st_cell._st_ports ) ) : + if self._st_cell._st_ports[i] == self : + del self._st_cell._st_ports[i] + break + else : + for i in range ( len ( self._st_cell._st_sigs ) ) : + if self._st_cell._st_sigs[i] == self : + del self._st_cell._st_sigs[i] + break + + for net in self._st_cell._st_sigs : + if "_to_merge" in net.__dict__ : + if len ( net._to_merge ) : + for i in range ( len ( net._to_merge ) ): + if net._to_merge[i] != 0 : + if net._to_merge[i][0] == self : net._to_merge[i] = 0 # Erasement of a reference of the net + non = False + # Erasement of the net which wes going to be merged to the net being deleted + for i in range ( len ( net._to_merge ) ) : + if net._to_merge[i] != 0 : + non = True + break + if not non : net.Delete() + + # Erasement in the connections + for inst in self._st_cell._st_insts : + for pin in inst._map : + if self == inst._map[pin] : + del inst._map[pin] + break + + # Erasement of the huricane nets associated + for hurNet in self._hur_net : + if hurNet : hurNet.Delete() + + + ##### For buses ##### + def __getitem__ ( self, indice ) : + if ( indice < self._ind ) or ( indice >= ( self._ind + self._arity ) ) : + err = "\n[Stratus ERROR] [] : bad index " + str(indice) + " for net : " \ + + self._name + " of arity " + str(self._arity) + if self._ind != 0 : err += " and LSB " + str(self._ind) + err += ".\n" + raise err + + return Sig ( self, indice ) + + def __getslice__ ( self, ind1, ind2 ) : + if ind1 < ind2 : + indmin = ind1 + indmax = ind2 + else : + indmin = ind2 + indmax = ind1 + + # Errors + if ( (indmax-indmin) < 1 ) or ( (indmax-indmin) > self._arity ) : + err = "\n[Stratus ERROR] [:] : bad indexes " + str(indmax) + ", and " + str(indmin) \ + + " for net : " + self._name + " of arity " + str(self._arity) + if self._ind != 0 : err += " and LSB " + str(self._ind) + err += ".\n" + raise err + if ( indmax >= ( self._ind + self._arity ) ) or ( indmin < self._ind ) : + err = "\n[Stratus ERROR] [:] : bad indexes " + str(indmax) + ", and " + str(indmin) \ + + " for net : " + self._name + " of arity " + str(self._arity) + if self._ind != 0 : err += " and LSB " + str(self._ind) + err += ".\n" + raise err + + return Sig ( self, ind1, ind2 ) + + ##### To affect a signal : <= ##### + def __le__ ( self, net ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + ### Initialisation of net representing a constant ### + if type ( net ) == types.StringType : + from st_const import Constant + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : + raise "\n[Stratus ERROR] : there is no alim.\n" + + constParam = { 'nb' : net } + string = Constant.getString ( constParam ) + + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "constant_%d" % num_net, len ( string ) )] + + # 3 possible constant operator output name (nq,q,output) => 3 differents map + if string == "0" : + inst_name = "zero" + map_cst = { 'nq' : cell._TAB_NETS_OUT[num_net] + , 'vdd': cell._st_vdds[0] + , 'vss': cell._st_vsss[0] + } + elif string == "1" : + inst_name = "one" + map_cst = { 'q' : cell._TAB_NETS_OUT[num_net] + , 'vdd': cell._st_vdds[0] + , 'vss': cell._st_vsss[0] + } + else : + inst_name = Constant.getModelName ( constParam ) + map_cst = { 'output0': cell._TAB_NETS_OUT[num_net] + , 'vdd': cell._st_vdds[0] + , 'vss': cell._st_vsss[0] + } + Generate ( "Constant", inst_name, param = constParam ) + + Inst ( inst_name + , map = map_cst + ) + + net = cell._TAB_NETS_OUT[num_net] + + ### Merging of two nets ### + # Resizement of the output net if needed thanks to the input net's lenght + if not ( self._arity ) : self.create_net ( self._name, net._arity ) + + # Error if the nets don t have the same size + if self._arity - net._arity : + err = "\n[Stratus ERROR] <= : the nets " + self._name + " " + str(self._arity) + " and " + net._name + " " + str(net._arity) \ + + " must have the same lenght\n" + raise err + + # If the nets are virtual, Let s work with the corresponding real nets + if self._real_net : netInCell = self._real_net + else : netInCell = self + + if net._real_net : netToMerge = net._real_net + else : netToMerge = net + + # Error if self is an input net + if ( netInCell._ext ) and ( netInCell._direct == "IN" ) : + err = "\n[Stratus ERROR] <= : " + self._name + " One can not give a value to an input net.\n" + raise err + + if netToMerge._ext : + err = "\n[Stratus ERROR] <= : " + self._name + # Error if net is an output net + if netToMerge._direct == "OUT" : err += " One can not initialise a net with an output net.\n" + # Error if net is an input net + elif netToMerge._direct == "IN" : err += " One can not initialise a net with an input net. The method Buffer() should be used.\n" + raise err + + # Construction of the tab if needed + if not ( len ( netToMerge._to_merge ) ) : + for i in range ( netToMerge._arity ) : netToMerge._to_merge.append ( 0 ) + + # Initialisation of _to_merge + for i in range ( net._arity ) : netToMerge._to_merge[i+net._ind] = [netInCell, i+self._ind] + + # Puts the net in the list of nets to merge in order to have them in the right order + self._st_cell._st_merge.append ( net ) + + if self._st_cell._hur_cell : + net.hur_merge() + for i in range ( net._arity ) : + CRL.createPartRing ( self._st_cell._hur_cell, netInCell._hur_net[i+self._ind].getName() ) # FIXME plante avec le adder mixed dans un cas particulier indetermine .... + + ##### Instanciation of a buffer ##### + def Buffer ( self ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_outbuf_%d" % num_net, self._arity )] + + buffMap = { 'q' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + + if self._st_cell._buff == 'DpgenBuff' : buffMap['i0'] = self + else : buffMap['i'] = self + +# if ( self._st_cell._buff == "Buf" ) and ( self._arity == 1 ) : +# inst_name = self._st_cell._buff.lower() +# else : + inst_name = self._st_cell._buff.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(self._arity) + inst_name += "bits" + + Generate ( self._st_cell._buff, inst_name, param = { 'nbit' : self._arity } ) + + Inst ( inst_name, map = buffMap ) + + return cell._TAB_NETS_OUT[num_net] + + ##### Boolean operators ##### + def __and__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._and ) + def __or__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._or ) + def __xor__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._xor ) + + def bool ( self, other_net, model ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if model == self._st_cell._and : f = "&" + elif model == self._st_cell._or : f = "|" + elif model == self._st_cell._xor : f = "^" + if self._arity - other_net._arity : + err = "\n[Stratus ERROR] " + f + " : the nets " + self._name + " and " + other_net._name + " must have the same lenght.\n" + raise err + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, self._arity )] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + +# if ( model in ( "A2", "O2", "Xr2" ) ) and ( self._arity == 1 ) and ( other_net._arity == 1 ) : +# inst_name = model.lower() +# +# else : + inst_name = model.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(self._arity) + inst_name += "bits" + + Generate ( model, inst_name, param = { 'nbit' : self._arity } ) + + Inst ( inst_name + , map = { 'i0' : self + , 'i1' : other_net + , 'q' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + + def __invert__ ( self ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, self._arity )] + + invMap = { 'nq' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + if self._st_cell._not == 'DpgenInv' : invMap['i0'] = self + else : invMap['i'] = self + +# if ( self._st_cell._not == "Inv" ) and ( self._arity == 1 ) : +# inst_name = self._st_cell._not.lower() +# else : + inst_name = self._st_cell._not.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(self._arity) + inst_name += "bits" + + Generate ( self._st_cell._not, inst_name, param = { 'nbit' : self._arity } ) + + Inst ( inst_name, map = invMap ) + + return cell._TAB_NETS_OUT[num_net] + + ##### Arithmetic operators ##### + def __add__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._add, {'signed' : self._st_cell._signed, 'extended' : self._st_cell._extended} ) + def __sub__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._sub, {'signed' : self._st_cell._signed, 'extended' : self._st_cell._extended} ) + def __mul__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._mult, {'signed' : self._st_cell._signed} ) + def __div__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._div ) + + def arithgen ( self, other_net, function, parameter = {} ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not function : raise "\n[Stratus ERROR] / : to be done.\n" + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] there is no alim in cell %s.\n" % str(cell._name) + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + + if function == self._st_cell._add : + if self._st_cell._extended : + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, max ( self._arity, other_net._arity )+1 )] + else: + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, max ( self._arity, other_net._arity ) )] + elif function == self._st_cell._sub : + if self._st_cell._extended : + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, max ( self._arity, other_net._arity )+1 )] + else: + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, max ( self._arity, other_net._arity ) )] + elif function == self._st_cell._mult : cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, self._arity+other_net._arity )] + + arithParam = parameter + if not self._st_cell._signed and function == self._st_cell._mult : + name1 = re.sub(r"\[([0-9]+):([0-9]+)\]",r"\1\2", self._name) + "ext" + name2 = re.sub(r"\[([0-9]+):([0-9]+)\]",r"\1\2", other_net._name) + "ext" + i0ext = Signal(name1, self._arity+1) + i1ext = Signal(name2, other_net._arity+1) + i0ext <= self.Extend(self._arity+1, 'zero') + i1ext <= other_net.Extend(other_net._arity+1, 'zero') + + arithParam['nbit0'] = self._arity+1 + arithParam['nbit1'] = other_net._arity+1 + + arithMap = { 'i0' : i0ext + , 'i1' : i1ext + , 'o' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + + else: + + arithParam['nbit0'] = self._arity + arithParam['nbit1'] = other_net._arity + + arithMap = { 'i0' : self + , 'i1' : other_net + , 'o' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + + inst_name = function.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + for p in arithParam : inst_name += "_%s_%s" % ( str(p).lower(), str(arithParam[p]).lower() ) + + Generate ( function, inst_name, param = arithParam ) + Inst ( inst_name, map = arithMap ) + + return cell._TAB_NETS_OUT[num_net] + + ##### Shifter ##### + def Shift ( self, inputNet, direction, type ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not inputNet._arity : raise "\n[Stratus ERROR] Shift : The input net does not have a positive arity.\n" + if not self._arity : raise "\n[Stratus ERROR] Shift : The command net does not have a positive arity.\n" + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] there is no alim.\n" + # Wrong parameters : + if direction not in ( "left", "right" ) : raise "\n[Stratus ERROR] Shift : The direction parameter must be \"left\" or \"right\".\n" + if type not in ( "logical", "arith", "circular" ) : raise "\n[Stratus ERROR] Shift : The type parameter must be \"logical\" or \"arith\" or \"circular\".\n" + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, inputNet._arity )] + + # Initialisation of shiftType + if direction is "left" : + if type is "logical" : shiftType = 0x12 + elif type is "arith" : shiftType = 0xa + else : shiftType = 0x6 + else : + if type is "logical" : shiftType = 0x11 + elif type is "arith" : shiftType = 0x9 + else : shiftType = 0x5 + + inst_name = self._st_cell._shift.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += type + inst_name += "_" + inst_name += str(inputNet._arity) + inst_name += "bits" + + Generate ( self._st_cell._shift, inst_name, param = { 'nbit' : inputNet._arity, 'type' : shiftType } ) + Inst ( inst_name + , map = { 'cmd' : self + , 'i' : inputNet + , 's' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + + ##### Register ##### + def Reg ( self, inputNet ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not inputNet._arity : raise "\n[Stratus ERROR] Reg : The input net does not have a positive arity.\n" + if not self._arity : raise "\n[Stratus ERROR] Reg : The clock does not have a positive arity.\n" + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] there is no alim.\n" + + # Creation of the output net with the right size + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, inputNet._arity )] + +# if ( self._st_cell._reg == "Sff1" ) and ( inputNet._arity == 1 ) : +# inst_name = "sff1" +# else : +# inst_name = self._st_cell._reg.lower() +# inst_name = re.sub ( "\.", "_", inst_name ) +# inst_name += "_" +# inst_name += str(inputNet._arity) +# inst_name += "bits" +# +# Generate ( self._st_cell._reg, inst_name, param = { 'nbit' : inputNet._arity } ) + + inst_name = self._st_cell._reg.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(inputNet._arity) + inst_name += "bits" + + Generate ( self._st_cell._reg, inst_name, param = { 'nbit' : inputNet._arity } ) + + Inst ( inst_name + , map = { 'i' : inputNet + , 'ck' : self + , 'q' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + + ##### Multiplexor ##### + def Mux ( self, nets ) : + + maxPossibility = pow ( 2, self._arity ) - 1 + + ### List ### + if type ( nets ) == types.ListType : + if len ( nets ) != ( maxPossibility + 1 ) : + raise "\n[Stratus ERROR] Mux : when using a list, all the nets must be precised. Maybe one should use a dictionnary.\n" + + return self.muxList ( nets ) + + ### Dictionnary : Creation of the corresponding list ### + elif type ( nets ) == types.DictType : + + # Initialisation of the by default to 0 net if no default net given + if "default" not in nets : nets["default"] = 0 + + # Traitement of lists, intervals and numbers + for net in nets.keys () : + if re.search ( "-", net ) or re.search ( ",", net ) or re.search ( "#", net ) : + chaine = net + while chaine : + interval = re.search ( "^([0-9]+)-([0-9]+)", chaine ) + chiffre = re.search ( "^([0-9]+)", chaine ) + diese = re.search ( "^#([0-9\?]+)", chaine ) + + ############# + if interval : + nb1 = int ( interval.group(1) ) + nb2 = int ( interval.group(2) ) + + # Error : wrong interval + if nb1 >= nb2 : + raise "\n[Stratus ERROR] Mux : when an interval is specified, the second number of the interval must be the greater one.\n" + # Error : if the interval does not correspond to the lenght of the command + if ( nb1 > maxPossibility ) or ( nb2 > maxPossibility ) : + raise "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n" + + for i in range ( nb1, nb2+1 ) : nets[i] = nets[net] + + # Next element + temp = re.search ( "^[0-9]+-[0-9]+,(.+)$", chaine ) + if temp : chaine = str ( temp.group(1) ) + else : chaine = None + + ############## + elif chiffre : + if int ( chiffre.group(0) ) > maxPossibility : + raise "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n" + + nets[int(chiffre.group(0))] = nets[net] + + # Next element + temp = re.search ( "^[0-9]+,(.+)$", chaine ) + if temp : chaine = str ( temp.group(1) ) + else : chaine = None + + ############ + elif diese : + binaire = diese.group ( 1 ) + + # Error : if the binary number does not correspond to the lenght of the command + if len ( binaire ) != self._arity : + err = "\n[Stratus ERROR] Mux : the binary number " + str(binaire) \ + + " does not match with the lenght of the command. It has to be a " + str(self._arity) + "bits number.\n" + raise err + + # Error : if the number is not binary + for n in binaire : + if n not in ( "0", "1", "?", "#" ) : + err = "\n[Stratus ERROR] Mux : after #, the number has to be binary.\n" + raise err + + nombrebit = self._arity + + nb = 0 + for i in range ( -1, -nombrebit - 1, -1 ) : + if binaire[i] == "1" : nb += pow ( 2, -i - 1 ) + + nombres = [] + premierpassage = 1 + for i in range ( -1, -nombrebit - 1, -1 ) : + if binaire[i] == "?" : + if premierpassage : + nombres += [nb] + nombres += [nb + pow ( 2, -i - 1 )] + premierpassage = 0 + else : + enplus = [] + for chaquenombre in nombres : enplus += [chaquenombre + pow ( 2, -i - 1 )] + nombres += enplus + + for chaquenombre in nombres : nets[chaquenombre] = nets[net] + + # Next element + temp = re.search ( "^#.*,(.+)$", chaine ) + if temp : chaine = str ( temp.group (1) ) + else : chaine = None + + else : + err = "\n[Stratus ERROR] Mux : wrong key.\n" + raise err + + del nets[net] + + # Otherwise it must be a number : + elif re.search ( "^[0-9]+$", net ) : + chaine = re.search ( "^([0-9]+)$", net ) + chiffre = str ( chaine.group ( 1 ) ) + + if int ( chiffre ) > maxPossibility : + err = "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n" + raise err + + nets[int(chiffre)] = nets[chiffre] + del nets[chiffre] + + else : + if net != "default" : + err = "\n[Stratus ERROR] Mux : wrong key.\n" + raise err + + clefs = nets.keys () + clefs.sort () + + # Covering of the keys wich are not default + lenClefs = 0 + for c in clefs : + if c != "default" : lenClefs += 1 + + liste = [] + decalage = 0 + for i in range ( lenClefs ) : + nb = clefs[i] + nb2 = i + decalage + if nb2 < nb : + while nb2 < nb : + liste.append ( nets["default"] ) + nb2 += 1 + decalage += 1 + liste.append ( nets[clefs[i]] ) # it is the right one + else : + liste.append ( nets[clefs[i]] ) + + # Number of wanted nets : + lenList = pow ( 2, self._arity ) + + # If nets are missing theu are default nets + while len ( liste ) < lenList : liste.append ( nets["default"] ) + + # Creation of the list corresponding to the dictionnary + return self.muxList ( liste ) + + # Error : wrong argument + else : + err = "\n[Stratus ERROR] Mux : wrong argument type.\n" + raise err + + + ### List ### + def muxList ( self, nets ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : there is no alim.\n" + + long = 0 + for i in range ( len ( nets ) ) : + if nets[i] : long = nets[i]._arity + + # Error : if no input net + if not ( long ) : raise "\n[Stratus ERROR] Mux : there are no input nets.\n" + + # Instanciation of a zero cell if needed + for net in nets : + if net == 0 : + from st_const import Zero + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "sig0_%d" % num_net, long )] + cell._TAB_NETS_OUT[num_net] <= Zero ( long ) + break + + # Creation of the map + map_mux = { 'cmd' : self + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + + i = 0 + for net in nets : + if net : map_mux['i%d' % i] = net + else : map_mux['i%d' % i] = cell._TAB_NETS_OUT[num_net] + + i += 1 + + # Initialisation of the output net + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, long )] + + map_mux ['q'] = cell._TAB_NETS_OUT[num_net] + + inst_name = self._st_cell._mux.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(long) + inst_name += "bits" + inst_name += "_" + inst_name += str(self._arity) + inst_name += "cmd" + + Generate ( self._st_cell._mux, inst_name, param = { 'nbit' : long, 'nbit_cmd' : self._arity } ) + Inst ( inst_name, map = map_mux ) + + return cell._TAB_NETS_OUT[num_net] + + + ##### Comparison functions ##### + def Eq ( self, nb ) : return self.comparaison ( nb, True ) + def Ne ( self, nb ) : return self.comparaison ( nb, False ) + + # TODO : it could work with un string representing binary, decimal, or hexadecimal + def comparaison ( self, nb, egal ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise "\n[Stratus ERROR] : threre is no alim.\n" + + # Initialisation of the output net + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, 1 )] + + inst_name = self._st_cell._comp.lower() + inst_name = re.sub ( "\.", "_", inst_name ) + inst_name += "_" + inst_name += str(self._arity) + inst_name += "bits" + inst_name += "_" + inst_name += str(nb) + if egal : inst_name += "egal" + + Generate ( self._st_cell._comp, inst_name, param = { 'nbit' : self._arity, 'nb' : nb, 'egal' : egal } ) + Inst ( inst_name + , map = { "netin" : self + , "netout" : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + + + ##### Method Alias ##### + def Alias ( self, net ) : + + # Error : if the net already has an alias + if net._alias : + err = "\n[Stratus ERROR] Alias : the net " + net._name + " is already an alias.\n" + raise err + + # Resizement of the net if needed + if not ( net._arity ) : net.create_net ( net._name, self._arity ) + + # Error : if the nets don't have the same lenght + if self._arity != net._arity : + err = "\n[Stratus ERROR] Alias : the nets " + self._name + " and " + net._name + " must have the same lenght\n" + raise err + + # If nets are virtual, let's work with the corresponding real nets + if net._real_net : realNet = net._real_net + else : realNet = net + + if self._real_net : realSelf = self._real_net + else : realSelf = self + + # Construction of the tab if needed + if not ( len ( realNet._alias ) ) : + for i in range ( realNet._arity ) : realNet._alias.append ( 0 ) + + # Initialisation of _alias + for i in range ( net._ind, net._ind + net._arity ) : + + if not realSelf._alias : + realNet._alias[i] = {realSelf : i + self._ind - net._ind} + # Alias of an alias + else : + err = "\n[Stratus ERROR] Alias : 2 Alias in a row are not supported.\n" + raise err + # FIXME bug : for now, Alias of Alias are not permitted +# if realSelf._alias[i + self._ind - net._ind] : +# netAlias = realSelf._alias[i + self._ind - net._ind].keys()[0] +# bitAlias = realSelf._alias[i + self._ind - net._ind][netAlias] +# if netAlias._real_net : netAlias = netAlias._real_net +# realNet._alias[i] = {netAlias : bitAlias} +# # Error : more than 2 Alias in a row not supported +# if netAlias._alias : +# err = "\n[Stratus ERROR] Alias : more than 2 Alias in a row are not supported.\n" +# raise err +# else : +# realNet._alias[i] = {realSelf : i + self._ind - net._ind} + + ##### Method Extend ##### + def Extend ( self, width, type ) : + global CELLS + + from st_model import CELLS + from st_const import Zero, One + + cell = CELLS[-1] + + if self._arity >= width : + err = "\n[Stratus ERROR] Extend : the net " + self._name + \ + " can not be extended to " + str(width) + " bits, it's arity is already " + str(self._arity) + ".\n" + raise err + + num_net = len ( cell._TAB_NETS_OUT ) + cell._TAB_NETS_OUT += [Signal ( "%s_ext_%d_%d" % ( self._name, width, num_net ), width )] + + name = "extend_%d_%d_%s" % ( self._arity, width, type ) + + Generate ( "Extend", name, param = { 'nbit0' : self._arity, 'nbit1' : width, 'type' : type } ) + + Inst ( name + , map = { 'i' : self + , 'o' : cell._TAB_NETS_OUT[num_net] + , 'vdd' : cell._st_vdds[0] + , 'vss' : cell._st_vsss[0] + } + ) + + return cell._TAB_NETS_OUT[num_net] + + ################################################################################################################################## + ##### Initialisation of nets ##### + def create_net ( self, nom, nbit, indice = 0, extern = False, direction = None, hType = None ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + # Error : + if re.search ( "[A-Z]", nom ) : + print "[Stratus Warning] : Upper case letters are not supported, the name", nom, "is lowered." + nom.lower () + if re.search ( " ", nom ) : + chaine = re.search ( "st_net\.(.*)", str ( self.__class__ ) ) + classe = chaine.group(1) + err = "\n[Stratus ERROR] " + classe + " : \"" + nom + "\" the name of the net can not contain a space.\n" + raise err + + self._st_cell = cell + self._name = nom + self._arity = nbit + self._ind = indice + self._hur_net = [] + self._alias = [] + self._to_merge = [] + self._to_cat = [] + self._real_net = None + self._ext = extern + if extern : self._direct = direction + + # Error : + if ( nbit == 1 ) and indice : + err = "\n[Stratus ERROR] " + str ( self.__class__ ) + " : " + self._name + " : one can not put an indice for a 1 bit net.\n" + raise err + + if hType : + self._h_type = hType + if hType == "POWER" : self._st_cell._st_vdds.append ( self ) + elif hType == "GROUND" : self._st_cell._st_vsss.append ( self ) + elif hType == "CLOCK" : self._st_cell._st_cks.append ( self ) + + # The net is put in the nets list of the cell + else : + if nbit : + if extern : self._st_cell._st_ports.append ( self ) + else : self._st_cell._st_sigs.append ( self ) + + # Creation of the hurricane net if in hurricane mode + if self._st_cell._hur_cell : self.create_hur_net() + + ##### Initialisation of the hurricane nets for part nets ##### + def create_part_hur_net ( self ) : + if self._ind2 < self._ind : pas = -1 + else : pas = 1 + + if self._real_net._hur_net : # FIXME a priori pb du a l outil d optimisation + for i in range ( self._ind, self._ind2 + pas, pas ) : self._hur_net.append ( self._real_net._hur_net[i] ) + + ##### Initialisation of the hurricane nets ##### + def create_hur_net ( self ) : + if self._arity == 1 : + self.hur_net ( self._name, 0 ) + else : + for i in range ( self._ind, self._arity+self._ind ) : self.hur_net ( self._name + "(" + str(i) + ")", i ) + + ##### hur_net one by one ##### + def hur_net ( self, name, ind ) : + if ( self._alias ) and ( self._alias[ind] ) : + self._hur_net += [self._alias[ind].keys()[0]] # put the right hur_net + return + elif ( self._to_cat ) and ( self._to_cat[ind] ) : + cat = self._to_cat[ind] + self._hur_net += [cat[0]._hur_net[cat[1]]] + return + + net = Net ( self._st_cell._hur_cell, name ) + + net.setType ( TypeLOGICAL ) + + if self._ext : net.setExternal ( True ) + else : net.setExternal ( False ) + + if self._ext : + if self._direct == "IN" : net.setDirection ( DirectionIN ) + elif self._direct == "OUT" : net.setDirection ( DirectionOUT ) + elif self._direct == "INOUT" : net.setDirection ( DirectionINOUT ) + elif self._direct == "TRISTATE" : net.setDirection ( DirectionTRISTATE ) + elif self._direct == "UNKNOWN" : net.setDirection ( DirectionUNDEFINED ) + + if '_h_type' in self.__dict__ : + if self._h_type == "POWER" : net.setType ( TypePOWER ) + elif self._h_type == "GROUND" : net.setType ( TypeGROUND ) + elif self._h_type == "CLOCK" : net.setType ( TypeCLOCK ) + + self._hur_net += [net] + + ##### Hurricane merge ##### + def hur_merge ( self ) : + if self._real_net : realNet = self._real_net + else : realNet = self + + if self._to_cat : + err = "\n[Stratus ERROR] HurricanePlug <= : net " + self._name + " is a Cat net. Forbidden utilisation of <= and Cat.\n" + raise err + + for i in range ( self._ind, self._arity + self._ind ) : + if realNet._to_merge[i] : + + selfToMerge = realNet._to_merge[i][0] + bitToMerge = realNet._to_merge[i][1] + + if selfToMerge._hur_net == [] : + print "[Stratus Warning] HurricanePlug <= : net", selfToMerge._name, "has no hurricane net." + return + + if realNet._hur_net == [] : + err = "\n[Stratus ERROR] HurricanePlug <= : net " + realNet._name + " has no hurricane net.\n" + raise err + + if bitToMerge > ( len ( selfToMerge._hur_net ) - 1 ) : + err = "\n[Stratus ERROR] HurricanePlug <= : net " + selfToMerge._name + " with hur_net : " + str(selfToMerge._hur_net) \ + + " with asked bit : " + str(bitToMerge) + ".\n" + raise err + if i > ( len ( realNet._hur_net ) - 1 ) : + err = "\n[Stratus ERROR] HurricanePlug <= : net " + realNet._name + " with hur_net : " + str(realNet._hur_net) \ + + " with asked bit : " + str(i) + ".\n" + raise err + + selfToMerge._hur_net[bitToMerge].merge ( realNet._hur_net[i] ) +# realNet._hur_net[i] = 0 + +# realNet.Delete() +# del realNet + + ##### Initialisation from a net hurricane ##### + def create_from_hur ( self, hur_net ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + self._st_cell = cell + self._alias = [] + self._to_merge = [] + self._to_cat = [] + self._real_net = None + + self._arity = 1 + self._ind = 0 + + self._name = str ( hur_net.getName() ) + + if hur_net.isExternal() : self._ext = True + else : self._ext = False + + if hur_net.isExternal() : + if hur_net.getDirection() == DirectionIN : self._direct = "IN" + elif hur_net.getDirection() == DirectionOUT : self._direct = "OUT" + elif hur_net.getDirection() == DirectionINOUT : self._direct = "INOUT" + elif hur_net.getDirection() == DirectionTRISTATE : self._direct = "TRISTATE" + elif hur_net.getDirection() == DirectionUNDEFINED : self._direct = "UNDEFINED" + + if hur_net.getType() == TypePOWER : self._h_type = "POWER" + elif hur_net.getType() == TypeGROUND : self._h_type = "GROUND" + elif hur_net.getType() == TypeCLOCK : self._h_type = "CLOCK" + + self._hur_net = [hur_net] + + if ( self._ext ) and ( '_h_type' in self.__dict__ ) : + if self._h_type == "CLOCK" : cell._st_ports.append ( self ) # not alimentations + else : + cell._st_sigs.append ( self ) + +########### +# SignalIn # +########### +class SignalIn ( net ) : + def __init__ ( self, nom, nbit, indice = 0 ) : + + if nbit < 1 : raise "\n[Stratus ERROR] SignalIn : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice, True, "IN" ) + +class SignalInFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +############ +# SignalOut # +############ +class SignalOut ( net ) : + def __init__ ( self, nom, nbit, indice = 0 ) : + + if nbit < 1 : raise "\n[Stratus ERROR] SignalOut : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice, True, "OUT" ) + +class SignalOutFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +############## +# SignalInOut # +############## +class SignalInOut ( net ) : + def __init__ ( self, nom, nbit, indice = 0 ) : + + if nbit < 1 : raise "\n[Stratus ERROR] SignalInOut : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice, True, "INOUT" ) + +class SignalInOutFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +################ +# SignalUnknown # +################ +class SignalUnknown ( net ) : + def __init__ ( self, nom, nbit, indice = 0 ) : + + if nbit < 1 : raise "\n[Stratus ERROR] SignalUnknown : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice, True, "UNKNOWN" ) + +class SignalUnknownFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +############ +# TriState # +############ +class TriState ( net ) : + def __init__ ( self, nom, nbit, indice = 0 ) : + + if nbit < 1 : raise "\n[Stratus ERROR] TriState : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice, True, "TRISTATE" ) + +class SignalTriStateFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +######### +# Clock # +######### +class CkIn ( net ) : + def __init__ ( self, nom ) : + self.create_net ( nom, 1, extern = True, direction = "IN", hType = "CLOCK" ) + +class CkInFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +################### +# Internal Signal # +################### +class Signal ( net ) : + def __init__ ( self, nom, nbit = 0, indice = 0 ) : + + if nbit < 0 : raise "\n[Stratus ERROR] Signal : the lenght of the net must be a positive value\n" + + self.create_net ( nom, nbit, indice ) + +class SignalFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +################ +# Alimentation # +################ +class VddIn ( net ) : + def __init__ ( self, nom ) : self.create_net ( nom, 1, extern = True, direction = "IN", hType = "POWER" ) +class VssIn ( net ) : + def __init__ ( self, nom ) : self.create_net ( nom, 1, extern = True, direction = "IN", hType = "GROUND" ) + +class VddInFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) +class VssInFromHur ( net ) : + def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net ) + +################## +# Virtual signal # +################## +class Sig ( net ) : + def __init__ ( self, net, indiceFort, indiceFaible = -1 ) : + global CELLS + from st_model import CELLS + + if indiceFaible == -1 : indiceFaible = indiceFort + + self._st_cell = CELLS[-1] + self._ind = indiceFaible + self._ind2 = indiceFort + self._alias = [] + self._to_merge = [] + self._to_cat = [] + self._real_net = net + self._ext = net._ext + self._arity = abs ( indiceFort - indiceFaible ) + 1 + + if indiceFort < indiceFaible : self._reverse = True + else : self._reverse = False + + self._hur_net = [] + + self._st_cell._st_partsigs.append ( self ) + + # Initialisation of _hur_net if in hurricanePlug mode +# if CELLS[0]._hur_plug : self.create_part_hur_net() + + if self._ext : self._direct = net._direct + + if '_h_type' in net.__dict__ : self._h_type = net._h_type + + if indiceFort == indiceFaible : self._name = net._name + "[" + str(indiceFaible) + "]" + else : self._name = net._name + "[" + str(indiceFort) + ":" + str(indiceFaible) + "]" diff --git a/stratus1/src/stratus/st_param.py b/stratus1/src/stratus/st_param.py new file mode 100644 index 00000000..aee523ef --- /dev/null +++ b/stratus1/src/stratus/st_param.py @@ -0,0 +1,76 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_param.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +import getopt, sys, re, types + +####################### +def Param ( *tokens ) : + + try : + argum = "" + for i in range ( len ( tokens ) ) : argum += "%s:" + opts = getopt.getopt ( sys.argv[1:], argum % tokens )[0] + + except getopt.GetoptError : + raise "\n[Stratus ERROR] Param.\n" + + if opts == [] : + raise "\n[Stratus ERROR] Param : there is no parameter.\n" + + n = [] + for option, argument in opts : + for i in range ( len ( tokens ) ) : + if option in ( "-%s" % tokens[i] ) : + if re.search ( "^[0-9]+$", argument ) : n.insert ( i, int ( argument ) ) + elif re.search ( "^[0-9]+\.?[0-9]*e?-?[0-9]+$", argument ) : n.insert ( i, float ( argument ) ) + else : n.insert ( i, argument ) # By default, type is str + + if len ( n ) == 1 : return n[0] + + return n diff --git a/stratus1/src/stratus/st_parser.py b/stratus1/src/stratus/st_parser.py new file mode 100644 index 00000000..4297710c --- /dev/null +++ b/stratus1/src/stratus/st_parser.py @@ -0,0 +1,215 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_parser.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + +import xml.parsers.expat +import re, types + +BV = [] +BVg = [] + +I = [] +I0 = [] +I2 = [] +I3 = [] +A = [] + +CK = [] +CMD = [] +CMD0 = [] +CIN = [] + +Q = [] +NQ = [] +S = [] + +############## +class Parser : + + def __init__ ( self ) : + self._p = xml.parsers.expat.ParserCreate () + + self._p.StartElementHandler = self.start_element + self._p.EndElementHandler = self.end_element + self._p.CharacterDataHandler = self.char_data + + self._realCell = {} + self._inOut = {} + + # Handler functions + + ######################################### + def start_element ( self, name, attrs ) : + # Print which the technology is +# if name == 'technology' : +# print "Technology is :", attrs['name'] + + # Modification of attributes + if name == 'model' : + virtName = str(attrs['name']) + + self._realCell[virtName] = str(attrs['realcell']) + + inOutTemp = {} + for key in attrs : + if key not in ( 'name', 'realcell' ) : + inOutTemp[str(key)] = str(attrs[str(key)]) + + self._inOut[str(attrs['name'])] = inOutTemp + + ################################ + def end_element ( self, name ) : pass + + ############################## + def char_data ( self, data ) : pass # print repr(data) + + # Parsing a file + ################ + def Parse ( self, nameFile ) : + self._p.ParseFile ( open ( nameFile, "r" ) ) + +################## +class InitParser : + + def __init__ ( self ) : + self._p = xml.parsers.expat.ParserCreate () + + self._p.StartElementHandler = self.start_element + self._p.EndElementHandler = self.end_element + self._p.CharacterDataHandler = self.char_data + + self._realCell = {} + self._inOut = {} + + # Handler functions + + ######################################### + def start_element ( self, name, attrs ) : + global BV, I, I0, I2, I3, A, CK, CMD, CMD0, CIN, Q, NQ, S + + # Modification of attributes + if name == 'model' : + virtName = str(attrs['name']) + BV.append ( virtName ) + + for key in attrs : + if key == 'i' : I.append ( virtName ) + elif key == 'i0' : I0.append ( virtName ) + elif key == 'i2' : I2.append ( virtName ) + elif key == 'i3' : I3.append ( virtName ) + elif key == 'a' : A.append ( virtName ) + elif key == 'ck' : CK.append ( virtName ) + elif key == 'cmd' : CMD.append ( virtName ) + elif key == 'cmd0' : CMD0.append ( virtName ) + elif key == 'cin' : CIN.append ( virtName ) + elif key == 'q' : Q.append ( virtName ) + elif key == 'nq' : NQ.append ( virtName ) + elif key == 'sout' : S.append ( virtName ) + + ################################ + def end_element ( self, name ) : pass + + ############################## + def char_data ( self, data ) : pass # print repr(data) + + # Parsing a file + ################ + def Parse ( self, nameFile ) : + self._p.ParseFile ( open ( nameFile, "r" ) ) + + # Givien the tab of the name of the cells, contruction of a tab giving the name of the generators (first letter uppered) + for name in BV : + chaine = re.search ( "([a-z])(.+)", name ) + name_g = chaine.group(1).upper() + chaine.group(2) + BVg.append ( name_g ) + +############## +class WeightParser : + + def __init__ ( self ) : + self._p = xml.parsers.expat.ParserCreate () + + self._p.StartElementHandler = self.start_element + self._p.EndElementHandler = self.end_element + self._p.CharacterDataHandler = self.char_data + + self._weightTime = {} + self._weightArea = {} + + # Handler functions + + ######################################### + def start_element ( self, name, attrs ) : + if name == 'model' : + virtName = str(attrs['name']) + + if 'time' in attrs : + temp = float(attrs['time']) + else : +# print 'Warning: no weight done in the file, weight put to 1.' + temp = 1 + + self._weightTime[virtName] = temp + + if 'area' in attrs : + temp = float(attrs['area']) + else : +# print 'Warning: no weight done in the file, weight put to 1.' + temp = 1 + + self._weightArea[virtName] = temp + + ################################ + def end_element ( self, name ) : pass + + ############################## + def char_data ( self, data ) : pass # print repr(data) + + # Parsing a file + ################ + def Parse ( self, nameFile ) : + self._p.ParseFile ( open ( nameFile, "r" ) ) diff --git a/stratus1/src/stratus/st_placeAndRoute.py b/stratus1/src/stratus/st_placeAndRoute.py new file mode 100644 index 00000000..3ec23931 --- /dev/null +++ b/stratus1/src/stratus/st_placeAndRoute.py @@ -0,0 +1,344 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@lip6.fr | +# | =============================================================== | +# | Py Module : "./st_placeAndRoute.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +import CRL +from placeandroute import * +from st_net import * + +import re, string + +global nbCkBuf +nbCkBuf = 0 + + +############### +## PlaceGlue ## +############### +def PlaceGlue ( cell = None, tool = "mistral", greedy = True, nparts = 0 ) : + + if not cell : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if isinstance ( cell, Model ) : # FIXME : a changer, mettre toujours un model et faire utiliser aux etudiants de l'annee prochaine getModel + pyPlaceGlue ( cell._hur_cell ) + + if isinstance ( cell, Inst ) : + pyPlaceGlue ( cell._st_masterCell._hur_cell ) + + +################## +## PlaceCentric ## +################## +def PlaceCentric ( instance ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + pyPlaceCentric ( cell._hur_cell, instance._hur_instance ) + +###################### +## AlimVerticalRail ## +###################### +def AlimVerticalRail ( coordonnee ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + pyAlimVerticalRail ( cell._hur_cell, coordonnee ) + +######################## +## AlimHorizontalRail ## +######################## +def AlimHorizontalRail ( coordonnee ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + pyAlimHorizontalRail ( cell._hur_cell, coordonnee ) + +#################### +## AlimConnectors ## +#################### +def AlimConnectors () : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + pyAlimConnectors ( cell._hur_cell ) + +############# +## RouteCk ## +############# +def RouteCk ( net ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + pyRouteCk ( cell._hur_cell, net._hur_net[0] ) + +################# +## GlobalRoute ## +################# +def GlobalRoute ( cell = None ): + if not cell: + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if isinstance ( cell, Model ): # FIXME : a changer, mettre toujours un model et faire utiliser aux etudiants de l'annee prochaine getModel + pyGlobalRoute ( cell._hur_cell ) + if isinstance ( cell, Inst ): + pyGlobalRoute ( cell._st_masterCell._hur_cell ) + return + +################### +## DetailRoute ## +################### +def DetailRoute ( cell = None ): + if not cell: + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if isinstance ( cell, Model ) : # FIXME : a changer, mettre toujours un model et faire utiliser aux etudiants de l'annee prochaine getModel + pyDetailRoute ( cell._hur_cell ) + if isinstance ( cell, Inst ) : + pyDetailRoute ( cell._st_masterCell._hur_cell ) + return + +########################## +## TimingStaticAnalysis ## +########################## +#def TimingStaticAnalysis ( cell = None ): +# if not cell: +# global CELLS +# from st_model import CELLS +# +# cell = CELLS[-1] +# +# if isinstance ( cell, Model ): # FIXME : a changer, mettre toujours un model et faire utiliser aux etudiants de l'annee prochaine getModel +# pyTimingStaticAnalysis ( cell._hur_cell ) +# if isinstance ( cell, Inst ): +# pyTimingStaticAnalysis ( cell._st_masterCell._hur_cell ) +# return + + +############## +## PadNorth ## +############## +def PadNorth ( *args ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + hur_core = cell.getCore() + + hur_args = [] + for arg in args : + if not arg : + raise "\n[Stratus ERROR] PadNorth : one instance doesn't exist.\n" + if str ( arg.__class__ ) != "st_instance.Inst" : + raise "\n[Stratus ERROR] PadNorth : one argument is not an instance.\n" + + hur_args.append ( arg._hur_instance ) + + pyPadNorth ( cell._hur_cell, hur_core, hur_args ) + +############## +## PadSouth ## +############## +def PadSouth ( *args ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + hur_core = cell.getCore() + + hur_args = [] + for arg in args : + if not arg : + raise "\n[Stratus ERROR] PadSouth : one instance doesn't exist.\n" + if str ( arg.__class__ ) != "st_instance.Inst" : + raise "\n[Stratus ERROR] PadSouth : one argument is not an instance.\n" + + hur_args.append ( arg._hur_instance ) + + pyPadSouth ( cell._hur_cell, hur_core, hur_args ) + +############# +## PasEast ## +############# +def PadEast ( *args ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + hur_core = cell.getCore() + + hur_args = [] + for arg in args : + if not arg : + raise "\n[Stratus ERROR] PadEast : one instance doesn't exist.\n" + if str ( arg.__class__ ) != "st_instance.Inst" : + raise "\n[Stratus ERROR] PadEast : one argument is not an instance.\n" + + hur_args.append ( arg._hur_instance ) + + pyPadEast ( cell._hur_cell, hur_core, hur_args ) + +############# +## PadWest ## +############# +def PadWest ( *args ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + hur_core = cell.getCore() + + hur_args = [] + for arg in args : + if not arg : + raise "\n[Stratus ERROR] PadWest : one instance doesn't exist.\n" + if str ( arg.__class__ ) != "st_instance.Inst" : + raise "\n[Stratus ERROR] PadWest : one argument is not an instance.\n" + + hur_args.append ( arg._hur_instance ) + + pyPadWest ( cell._hur_cell, hur_core, hur_args ) + +############### +## PowerRing ## +############### +def PowerRing ( n ) : + global CELLS + from st_model import CELLS + + cell = CELLS[-1] + + if n < 3 : raise "\n[Stratus ERROR] : PowerRing : must have at least 3 pairs of vdd/vss rings\n" + + hur_core = cell.getCore() + + pyPowerRing ( cell._hur_cell, hur_core, n ) + + +################# +## ClockBuffer ## +################# +class ClockBuffer : + def __init__ ( self, netname ) : + global CELLS + from st_model import CELLS + global nbCkBuf + self.cell = CELLS[-1] + + self.net = self.cell._hur_cell.getNet ( netname ) + self.ck_b = Signal ( "ck_b%d"%nbCkBuf, 1 ) + + modelMasterCell = CRL.getAllianceFramework().getCell ( "buf_x2", CRL.Catalog.State.Views ) + if not modelMasterCell : + err = "Stratus Error : ClockBuffer : Cannot find model cell : buf_x2 in database !\n" + raise err + + inst = Instance ( self.cell._hur_cell, "ck_buffer%d"%nbCkBuf, modelMasterCell ) + nbCkBuf += 1 + + ##### Connection ##### + plugI = inst.getPlug ( modelMasterCell.getNet ( "i" ) ) + plugI.setNet ( self.net ) + + plugQ = inst.getPlug ( modelMasterCell.getNet ( "q" ) ) + plugQ.setNet ( self.ck_b._hur_net[0] ) + + plugGround = inst.getPlug ( iter(modelMasterCell.getGroundNets()).next() ) + plugGround.setNet ( iter(self.cell._hur_cell.getGroundNets()).next() ) + + plugPower = inst.getPlug ( iter(modelMasterCell.getPowerNets()).next() ) + plugPower.setNet ( iter(self.cell._hur_cell.getPowerNets()).next() ) + + def AddFF ( self, netname ) : + net = self.cell._hur_cell.getNet ( netname ) + if not net : + err = "AddFF Error net : " + netname + " not found" + raise err + + instDrive = None + for plug in net.getPlugs(): + if plug.getMasterNet().getDirection() == DirectionOUT : + instDrive = plug.getInstance() + break + + if instDrive == None : + err = "AddFF Error no drive instance found for net " + netname + ".\n" + raise err + + masterCell = instDrive.getMasterCell() + ## ici il vaudrait mieux faire une recherche sur l'ensemble des plugs de l'instDrive et trouver celle accrochee au self.net ## + netCk = masterCell.getNet ( "ck" ) + if instDrive.getPlug ( netCk ).getNet() != self.net : + err = "Stratus Error : AddFF : driver Instance of net " + netname + " is not connected to signal " + str ( self.net.getName() ) + ".\n" + raise err + + instDrive.getPlug ( netCk ).setNet ( self.ck_b._hur_net[0] ) diff --git a/stratus1/src/stratus/st_placement.py b/stratus1/src/stratus/st_placement.py new file mode 100644 index 00000000..94fcc788 --- /dev/null +++ b/stratus1/src/stratus/st_placement.py @@ -0,0 +1,537 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_placement.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * + +from util_Place import * + +########### +def Place ( ins, sym, ref, plac = FIXED, cell = None ) : + global MYPITCH, MYSLICE + + # Error if x and y found not permitted : + if ref._x % MYPITCH : + err = "\n[Stratus ERROR] Place : " + ins._name + " : coordinate x is not a mutiple of PITCH.\n" + raise err + + if ref._y % MYSLICE : + err = "\n[Stratus ERROR] Place : " + ins._name + " : coordinate y is not a mutiple of SLICE.\n" + raise err + + # Error message : if ref is not a reference + if str ( ref.__class__ ) != "st_ref.XY" : + raise "\n[Stratus ERROR] Place : wrong argument for placement, the coordinates must be put in a XY object.\n" + + # Error message if plac is not one of the permitted values + if ( plac != PLACED ) and ( plac != FIXED ) : raise "\n[Stratus ERROR] Place : wrong argument for placement type.\n" + + #placement ( ins, sym, getUnit(ref._x), getUnit(ref._y), plac, cell = cell ) + placement ( ins, sym, DbU_lambda(ref._x), DbU_lambda(ref._y), plac, cell = cell ) + +############### +def PlaceTop ( ins, symetry, offsetX = 0, offsetY = 0, plac = FIXED ) : + global CELLS + from st_model import CELLS + + global MYPITCH, MYSLICE + + cell = CELLS[-1] + + if offsetX % MYPITCH : + err = "\n[Stratus ERROR] PlaceTop : " + ins._name + " : offsetX is not a mutiple of PITCH.\n" + raise err + + if offsetY % MYSLICE : + err = "\n[Stratus ERROR] PlaceTop : " + ins._name + " : offsetY is not a mutiple of SLICE.\n" + raise err + + if ( plac != PLACED ) and ( plac != FIXED ) : + err = "\n[Stratus ERROR] PlaceTop : " + ins._name + " : wrong argument for placement type.\n" + raise err + + if cell._insref == None : + err = "\n[Stratus ERROR] PlaceTop : " + ins._name + " : no previous instance.\n" + raise err + + x = cell._insref._x + y = cell._insref._y + + if droite ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : x -= width ( cell._insref ) + else : x -= height ( cell._insref ) + + if bas ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : y += height ( cell._insref ) + else : y += width ( cell._insref ) + + placement ( ins, symetry, x + DbU_lambda ( offsetX ), y + DbU_lambda ( offsetY ), plac ) + +################# +def PlaceRight ( ins, symetry, offsetX = 0, offsetY = 0, plac = FIXED ) : + global CELLS + from st_model import CELLS + + global MYPITCH, MYSLICE + + cell = CELLS[-1] + + if offsetX % MYPITCH : + err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : offsetX is not a mutiple of PITCH.\n" + raise err + + if offsetY % MYSLICE : + err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : offsetY is not a mutiple of SLICE.\n" + raise err + + if ( plac != PLACED ) and ( plac != FIXED ) : + err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : wrong argument for placement type.\n" + raise err + + if cell._insref == None : + err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : no previous instance.\n" + raise err + + x = cell._insref._x + y = cell._insref._y + + if gauche ( cell._insref._sym ): + if vertical ( cell._insref._sym ) : x += width ( cell._insref ) + else : x += height ( cell._insref ) + + if haut ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : y -= height ( cell._insref ) + else : y -= width ( cell._insref ) + + placement ( ins, symetry, x + DbU_lambda ( offsetX ), y + DbU_lambda ( offsetY ), plac ) + +################ +def PlaceLeft ( ins, symetry, offsetX = 0, offsetY = 0, plac = FIXED ) : + global CELLS + from st_model import CELLS + + global MYPITCH, MYSLICE + + cell = CELLS[-1] + + if offsetX % MYPITCH : + err = "\n[Stratus ERROR] PlaceLeft : " + ins._name + " : offsetX is not a mutiple of PITCH.\n" + raise err + + if offsetY % MYSLICE : + err = "\n[Stratus ERROR] PlaceLeft : " + ins._name + " : offsetY is not a mutiple of SLICE.\n" + raise err + + if ( plac != PLACED ) and ( plac != FIXED ) : + err = "\n[Stratus ERROR] PlaceLeft : " + ins._name + " : wrong argument for placement type.\n" + raise err + + if cell._insref == None : + err = "\n[Stratus ERROR] PlaceLeft : " + ins._name + " : no previous instance.\n" + raise err + + x = cell._insref._x + y = cell._insref._y + + sym = transformation ( symetry ) + + if droite ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : x -= width ( cell._insref ) + else : x -= height ( cell._insref ) + + if haut ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : y -= height ( cell._insref ) + else : y -= width ( cell._insref ) + + placement ( ins, symetry, x - DbU_lambda ( offsetX ), y + DbU_lambda ( offsetY ), plac, fonction = "Left" ) + +################## +def PlaceBottom ( ins, symetry, offsetX = 0, offsetY = 0, plac = FIXED ) : + global CELLS + from st_model import CELLS + + global MYPITCH, MYSLICE + + cell = CELLS[-1] + + if offsetX % MYPITCH : + err = "\n[Stratus ERROR] PlaceBottom : " + ins._name + " : offsetX is not a mutiple of PITCH.\n" + raise err + + if offsetY % MYSLICE : + err = "\n[Stratus ERROR] PlaceBottom : " + ins._name + " : offsetY is not a mutiple of SLICE.\n" + raise err + + if ( plac != PLACED ) and ( plac != FIXED ) : + err = "\n[Stratus ERROR] PlaceBottom : " + ins._name + " : wrong argument for placement type.\n" + raise err + + if cell._insref == None : + err = "\n[Stratus ERROR] PlaceBottom : " + ins._name + " : no previous instance.\n" + raise err + + x = cell._insref._x + y = cell._insref._y + + sym = transformation ( symetry ) + + if droite ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : x -= width ( cell._insref ) + else : x -= height ( cell._insref ) + + if haut ( cell._insref._sym ) : + if vertical ( cell._insref._sym ) : y -= height ( cell._insref ) + else : y -= width ( cell._insref ) + + placement ( ins, symetry, x + DbU_lambda ( offsetX ), y - DbU_lambda ( offsetY ), plac, fonction = "Bottom" ) + +################# +def SetRefIns ( ins ) : + global CELLS + from st_model import CELLS + + from util_Place import UNPLACED + + cell = CELLS[-1] + + # Error : SetRefIns on a non existing instance + if not ins : raise "\n[Stratus ERROR] SetRefIns : the instance doesn't exist.\n" + + # Error : SetRefIns on a non placed instance + if ins._plac == UNPLACED : + err = "\n[Stratus ERROR] SetRefIns : the instance " + ins._name + " is not placed.\n" + raise err + + cell._insref = ins + +############ +def DefAb ( ref1, ref2 ) : + global CELLS + from st_model import CELLS + + global MYSLICE, MYPITCH + + cell = CELLS[-1] + + UpdateSession.open () + + # Error message : if ref are not references + if ( str ( ref1.__class__ ) != "st_ref.XY" ) or ( str ( ref2.__class__ ) != "st_ref.XY" ) : + err = "\n[Stratus ERROR] DefAb : wrong argument, the coordinates must be put in a XY object.\n" + raise err + + x1 = ref1._x + y1 = ref1._y + x2 = ref2._x + y2 = ref2._y + + if not cell._hur_cell : + err = "\n[Stratus ERROR] Layout : The hurricane cell has not been created.\n" \ + + "One has to use HurricanePlug before creating the layout.\n" + raise err + + if x1 % MYPITCH or y1 % MYSLICE or x2 % MYPITCH or y2 % MYSLICE : + err = "\nError in DefAb : Coordinates of an abutment Box in y must be multiple of the slice.\n" \ + + " : Coordinates of an abutment Box in x must be multiple of the pitch.\n" + raise err + + boite = cell._hur_cell.getAbutmentBox () + + if not ( boite.isEmpty() ) : + err = "\n[Stratus ERROR] DefAb : an abutment box already exists for cell : " \ + + str ( cell._name ) \ + + ". Maybe you should use ResizeAb function.\n" + raise err + + cell._hur_cell.setAbutmentBox ( Box ( DbU_lambda ( x1 ) + , DbU_lambda ( y1 ) + , DbU_lambda ( x2 ) + , DbU_lambda ( y2 ) + ) + ) + + UpdateSession.close () + +############ +def ResizeAb ( dx1, dy1, dx2, dy2 ) : + global CELLS + from st_model import CELLS + + global MYSLICE, MYPITCH + + cell = CELLS[-1] + + hurCell = cell._hur_cell + ab = hurCell.getAbutmentBox() + + UpdateSession.open () + + if dx1 % MYPITCH or dy1 % MYSLICE or dx2 % MYPITCH or dy2 % MYSLICE : + err = "\n[Stratus ERROR] ResizeAb : Coordinates of an abutment Box in y must be multiple of the slice.\n" \ + + " : Coordinates of an abutment Box in x must be multiple of the pitch.\n" + raise err + + old_xmin = ab.getXMin() + old_xmax = ab.getXMax() + old_ymin = ab.getYMin() + old_ymax = ab.getYMax() + + new_xmin = old_xmin - DbU_lambda ( dx1 ) + new_ymin = old_ymin - DbU_lambda ( dy1 ) + new_xmax = old_xmax + DbU_lambda ( dx2 ) + new_ymax = old_ymax + DbU_lambda ( dy2 ) + + if new_xmin >= new_xmax : + err = "\n[Stratus ERROR] ResizeAb : one of the values of dx1 or dx2 is incompatible with the size of the abutment box.\n" + raise err + + if new_ymin >= new_ymax : + err = "\n[Stratus ERROR] ResizeAb : one of the values of dy1 or dy2 is incompatible with the size of the abutment box.\n" + raise err + + hurCell.setAbutmentBox ( Box ( new_xmin, new_ymin, new_xmax, new_ymax ) ) + + UpdateSession.close () + +############ +def DefInstanceAb ( instance, x1, y1, x2, y2 ) : + + cell = instance._hur_instance.getMasterCell() + + boite = cell.getAbutmentBox() + + if not ( boite.isEmpty() ) : + err = "\n[Stratus ERROR] DefInstanceAb : an abutment box already exists. Maybe you should use ResizeAb function.\n" + raise err + + if x1 % MYPITCH or y1 % MYSLICE or x2 % MYPITCH or y2 % MYSLICE : + err = "\nError in DefAb : Coordinates of an abutment Box in y must be multiple of the slice.\n" \ + + " : Coordinates of an abutment Box in x must be multiple of the pitch.\n" + raise err + + cell.setAbutmentBox ( Box ( DbU_lambda ( x1 ) + , DbU_lambda ( y1 ) + , DbU_lambda ( x2 ) + , DbU_lambda ( y2 ) + ) + ) + + +#################################### +## placement ## +#################################### +def placement ( st_inst, sym, x, y, plac = FIXED, cell = None, fonction = None ) : + global CELLS + from st_model import CELLS + + if not cell : cell = CELLS[-1] + + # Error : placement of a non existing instance + if not st_inst : raise "\n[Stratus ERROR] Placement : the instance doesn't exist.\n" + + # Error : st_inst is not an instance + if str ( st_inst.__class__ ) != "st_instance.Inst" : + err = "\n\n[Stratus ERROR] Placement : the first argument " + st_inst + " is not an instance.\n" + raise err + + # Hurricane instance + hur_inst = st_inst._hur_instance + + # Error : if the hurricane instance does not exist + if not hur_inst : + err = "\n[Stratus ERROR] Layout : The hurricane instance of " + st_inst._name + " has not been created.\n" \ + + "One has to use HurricanePlug before creating the layout.\n" + raise err + + # Error : if the instance is already placed + if hur_inst.getPlacementStatus() == PlacementStatusFIXED : + err = "\n[Stratus ERROR] Placement : the instance " + st_inst._name + " is already placed.\n" + raise err + + ##### Legalization of the symetry ##### + st_inst._sym = transformation ( sym ) + + ##### For PlaceBottom and PlaceLeft : need the size of the instance being placed ##### + if fonction == "Left" : + if vertical ( st_inst._sym ) : x -= width ( st_inst ) + elif horizontal ( st_inst._sym ) : x -= height ( st_inst ) + elif fonction == "Bottom" : + if vertical ( st_inst._sym ) : y -= height ( st_inst ) + elif horizontal ( st_inst._sym ) : y -= width ( st_inst ) + + ##### Initialisation for relative placement ##### + cell._insref = st_inst + + ##### Placement ##### + if st_inst._sym == OrientationID : + st_inst._x = x + st_inst._y = y + + elif st_inst._sym == OrientationMX : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + abtemp.getWidth () + st_inst._y = y + + elif st_inst._sym == OrientationMY : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + st_inst._y = y + abtemp.getHeight () + + elif st_inst._sym == OrientationR2 : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + abtemp.getWidth () + st_inst._y = y + abtemp.getHeight () + + elif st_inst._sym == OrientationR1 : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + abtemp.getHeight () + st_inst._y = y + + elif st_inst._sym == OrientationR3 : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + st_inst._y = y + abtemp.getWidth () + + elif st_inst._sym == OrientationYR : + st_inst._x = x + st_inst._y = y + + elif st_inst._sym == OrientationXR : + abtemp = ab ( st_inst, cell ) + + st_inst._x = x + abtemp.getHeight () + st_inst._y = y + abtemp.getWidth () + + else : + raise "\n[Stratus ERROR] Placement : wrong transformation.\n" + + # if the abutment box is not at 0 0 FIXME + if st_inst._sym == OrientationMY : + x = st_inst._x + hur_inst.getAbutmentBox().getXMin() + y = st_inst._y + hur_inst.getAbutmentBox().getYMin() + else : + x = st_inst._x - hur_inst.getAbutmentBox().getXMin() + y = st_inst._y - hur_inst.getAbutmentBox().getYMin() + + UpdateSession.open() + + hur_inst.setTransformation ( Transformation ( x, y, st_inst._sym ) ) + + if plac == PLACED : + cell._hur_cell.setAbutmentBox ( cell._hur_cell.getAbutmentBox ().merge ( hur_inst.getAbutmentBox () ) ) + hur_inst.setPlacementStatus ( PlacementStatusPLACED ) + elif plac == FIXED : + cell._hur_cell.setAbutmentBox ( cell._hur_cell.getAbutmentBox ().merge ( hur_inst.getAbutmentBox () ) ) + hur_inst.setPlacementStatus ( PlacementStatusFIXED ) + elif plac == UNPLACED : + hur_inst.setPlacementStatus ( PlacementStatusUNPLACED ) + else : + raise "\n[Stratus ERROR] Placement : wrong argument for type of placement.\n" + + st_inst._plac = plac + + UpdateSession.close() + + +## Two names for the symetry ## +def transformation ( symetry ) : + if symetry == NOSYM or symetry == OrientationID : transf = OrientationID + elif symetry == SYM_X or symetry == OrientationMX : transf = OrientationMX + elif symetry == SYM_Y or symetry == OrientationMY : transf = OrientationMY + elif symetry == SYMXY or symetry == OrientationR2 : transf = OrientationR2 + elif symetry == ROT_P or symetry == OrientationR1 : transf = OrientationR1 + elif symetry == ROT_M or symetry == OrientationR3 : transf = OrientationR3 + elif symetry == SY_RP or symetry == OrientationYR : transf = OrientationYR + elif symetry == SY_RM or symetry == OrientationXR : transf = OrientationXR + else : + err = "\n[Stratus ERROR] Placement :Illegal transformation.\n" + raise err + + return transf + +## How to get the abutment box ## +def ab ( ins, cell = None ) : + global CELLS + from st_model import CELLS + + if not cell : cell = CELLS[-1] + + return cell._hur_cell.getInstance ( ins._name ).getMasterCell ().getAbutmentBox () + +## the height of the abutment box ## +def height ( ins ) : + return ab ( ins ).getHeight () + +## the width of the abutment box ## +def width ( ins ) : + return ab ( ins ).getWidth () + +## Test of symetry ## +def vertical ( sym ) : + return sym == OrientationID or sym == OrientationMX or sym == OrientationMY or sym == OrientationR2 + +def horizontal ( sym ) : + return sym == OrientationR1 or sym == OrientationR3 or sym == OrientationYR or sym == OrientationXR + +def bas ( sym ) : + return sym == OrientationID or sym == OrientationMX or sym == OrientationR1 or sym == OrientationYR + +def haut ( sym ) : + return sym == OrientationR2 or sym == OrientationMY or sym == OrientationR3 or sym == OrientationXR + +def gauche ( sym ) : + return sym == OrientationID or sym == OrientationMY or sym == OrientationR3 or sym == OrientationYR + +def droite ( sym ) : + return sym == OrientationR2 or sym == OrientationMX or sym == OrientationR1 or sym == OrientationXR diff --git a/stratus1/src/stratus/st_ref.py b/stratus1/src/stratus/st_ref.py new file mode 100644 index 00000000..95ab704e --- /dev/null +++ b/stratus1/src/stratus/st_ref.py @@ -0,0 +1,242 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_ref.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from Hurricane import * + +from util_Place import * + +from ref import * + +import types + +########### +class XY : + def __init__ ( self, x, y ) : + self._x = x + self._y = y + +################################## +def GetRefXY ( pathname, refname ) : + global FRAMEWORK, CELLS + from st_model import FRAMEWORK, CELLS + + cell = CELLS[-1] + + # Check arguments type + if type ( pathname ) != types.StringType : + err = "\n[Stratus ERROR] GetRefXY : The instance's path must be put with a string.\n" + raise err + + if type ( refname ) != types.StringType : + err = "\n[Stratus ERROR] GetRefXY : The reference must be done with it's name : a string.\n" + raise err + + ( x, y ) = pyGetXY ( cell._hur_cell, pathname, refname ) + + return XY ( x, y ) + +############################ +def PlaceRef ( ref, name ) : + global FRAMEWORK, CELLS + from st_model import FRAMEWORK, CELLS + + cell = CELLS[-1] + + # Check arguments type + if ( str ( ref.__class__ ) != "st_ref.XY" ) : + err = "\n[Stratus ERROR] PlaceRef : Wrong argument, the coordinates of the reference must be put in a XY object.\n" + raise err + + if type ( name ) != types.StringType : + err = "\n[Stratus ERROR] PlaceRef : Argument layer must be a string.\n" + raise err + + pyPlaceRef ( cell._hur_cell, name, ref._x, ref._y ) + +################################################### +def PlaceContact ( net, layer, ref, width, height ) : + global FRAMEWORK + from st_model import FRAMEWORK + + # Check arguments type + if type ( layer ) != types.StringType : + err = "\n[Stratus ERROR] PlaceContact : Argument layer must be a string.\n" + raise err + myLayer = getDataBase().getTechnology().getLayer ( layer ) +# if not ( myLayer ) : +# err = "\n[Stratus ERROR] PlaceContact : Argument layer does not exist.\n" +# raise err + + if ( str ( ref.__class__ ) != "st_ref.XY" ) : + err = "\n[Stratus ERROR] PlaceContact : Wrong argument, the coordinates of the contact must be put in a XY object.\n" + raise err + + if ( net._arity > 1 ) : + err = "\n[Stratus ERROR] PlaceContact : Wrong argument, the net must be a 1 bit net.\n" + raise err + + if net._real_net : + indice = net._ind - net._real_net._ind + net = net._real_net + else : + indice = 0 + + pyPlaceContact ( net._hur_net[indice], myLayer, ref._x, ref._y, width, height ) + +################################################### +def PlacePin ( net, layer, direction, ref, width, height ) : + global FRAMEWORK + from st_model import FRAMEWORK + + # Check arguments type + if type ( layer ) != types.StringType : + err = "\n[Stratus ERROR] PlacePin : Argument layer must be a string.\n" + raise err + # No CALU permitted for Pin + calu = re.search ( "CALU", layer ) + if calu : + err = "\n[Stratus ERROR] PlacePin : Illegal layer, CALU not allowed.\n" + raise err + myLayer = getDataBase().getTechnology().getLayer ( layer ) +# if not ( myLayer ) : +# err = "\n[Stratus ERROR] PlacePin : Argument layer does not exist.\n" +# raise err + + if direction == UNDEFINED : direct = PinAccessDirectionUNDEFINED + elif direction == NORTH : direct = PinAccessDirectionNORTH + elif direction == SOUTH : direct = PinAccessDirectionSOUTH + elif direction == EAST : direct = PinAccessDirectionEAST + elif direction == WEST : direct = PinAccessDirectionWEST + else : + err = "\n[Stratus ERROR] PlacePin : Illegal pin access direction. The values are : UNDEFINED, NORTH, SOUTH, EAST, WEST.\n" + raise err + + if ( str ( ref.__class__ ) != "st_ref.XY" ) : + err = "\n[Stratus ERROR] PlacePin : Wrong argument, the coordinates of the pin must be put in a XY object.\n" + raise err + + if ( net._arity > 1 ) : + err = "\n[Stratus ERROR] PlacePin : Wrong argument, the net must be a 1 bit net.\n" + raise err + + if net._real_net : + indice = net._ind - net._real_net._ind + net = net._real_net + else : + indice = 0 + + if ( net._ext == False ) : + err = "\n[Stratus ERROR] PlacePin : Wrong argument, the net must be external.\n" + raise err + + pyPlacePin ( net._hur_net[indice], direct, PinPlacementStatusFIXED, myLayer, ref._x, ref._y, width, height ) + +################################################################# +def PlaceSegment ( net, layer, ref1, ref2, width ) : + global FRAMEWORK + from st_model import FRAMEWORK + + # Check arguments type + if type ( layer ) != types.StringType : + err = "\n[Stratus ERROR] PlaceSegment : Argument layer must be a string.\n" + raise err + + if ( str ( ref1.__class__ ) != "st_ref.XY" ) or ( str ( ref2.__class__ ) != "st_ref.XY" ) : + err = "\n[Stratus ERROR] PlaceSegment : Wrong argument, the coordinates of the segment must be put in XY objects.\n" + raise err + + if ( ref1._x != ref2._x ) and ( ref1._y != ref2._y ) : + err = "\n[Stratus ERROR] PlaceSegment : Segments are vertical or horizontal.\n" + raise err + + if ( net._arity > 1 ) : + err = "\n[Stratus ERROR] PlaceSegment : Wrong argument, the net must be a 1 bit net.\n" + raise err + + if net._real_net : + indice = net._ind - net._real_net._ind + net = net._real_net + else : + indice = 0 + + pyPlaceSegment ( net._hur_net[indice] + , getDataBase().getTechnology().getLayer ( layer ) + , ref1._x, ref1._y + , ref2._x, ref2._y + , width + ) + +################################################# +def CopyUpSegment ( pathname, netname, newnet ) : + global FRAMEWORK, CELLS + from st_model import FRAMEWORK, CELLS + + cell = CELLS[-1] + + # Check arguments type + if type ( pathname ) != types.StringType : + err = "\n[Stratus ERROR] CopyUpSegment : The instance's path must be put with a string.\n" + raise err + + if type ( netname ) != types.StringType : + err = "\n[Stratus ERROR] CopyUpSegment : The segment must be done with it's name : a string.\n" + raise err + + if ( newnet._arity > 1 ) : + err = "\n[Stratus ERROR] PlacePin : Wrong argument, the net must be a 1 bit net.\n" + raise err + + if newnet._real_net : + indice = newnet._ind - newnet._real_net._ind + newnet = newnet._real_net + else : + indice = 0 + + pyCopyUpSegment ( cell._hur_cell, pathname, netname, newnet._hur_net[indice] ) diff --git a/stratus1/src/stratus/st_shifter.py b/stratus1/src/stratus/st_shifter.py new file mode 100644 index 00000000..f5b3f384 --- /dev/null +++ b/stratus1/src/stratus/st_shifter.py @@ -0,0 +1,219 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Roselyne AVOT-CHOTIN - Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_shifter.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + + +def getConfig ( type ) : + def getValue ( pos ) : + if (type & 2**pos) != 0 : return True + else : return False + + config = { 'sticky' : None + , 'type' : {'log' : None, 'arith' : None, 'rot' : None, 'con' : None} + , 'dir' : {'left' : None, 'right' : None, 'con' : None} + } + + config['sticky'] = getValue(5) + config['type']['log'] = getValue(4) + config['type']['arith'] = getValue(3) + config['type']['rot'] = getValue(2) + config['dir']['left'] = getValue(1) + config['dir']['right'] = getValue(0) + + config['dir']['con'] = config['dir']['left'] and config['dir']['right'] + config['type']['con'] = ((config['type']['log'] and config['type']['arith']) + or (config['type']['log'] and config['type']['rot']) + or (config['type']['arith'] and config['type']['rot'])) + + if not (config['dir']['left'] or config['dir']['right']): + raise 'any of left or right directions are set' + if not (config['type']['log'] or config['type']['arith'] or config['type']['rot']) : + raise 'any of log or arith or rot types are set' + + return config + + +class Shifter ( Model ) : + + def __init__ ( self, name, param ) : + + Model.__init__ ( self, name, param ) + + self.nbit = param['nbit'] + + if self.nbit < 2: raise "\n[Stratus ERROR] Shift : input arity should be greater than 1.\n" + + self.config = getConfig(param['type']) + + self.cmd_width = log2 ( self.nbit ) + + def Interface ( self ) : + + self.cmd = SignalIn ( "cmd", self.cmd_width ) + self.i = SignalIn ( "i", self.nbit ) + self.s = SignalOut ( "s", self.nbit ) + + if self.config['sticky'] : self.sticky = SignalOut ( "sticky", 1 ) + if self.config['type']['con'] : self.type = SignalIn ( "typ", 3 ) + if self.config['dir']['con'] : self.dir = SignalIn ( "dir", 1 ) + + self.vdd = VddIn ( "vdd" ) + self.vss = VssIn ( "vss" ) + + def Netlist ( self ) : + + nbStages = self.cmd_width + + MuxOutput = {} + inj_lsb = {} + inj_msb = {} + mux_cmd = {} + + one = Signal ( "one", 1 ) + one <= One ( 1 ) + + zero = Signal ( "zero", 1 ) + zero <= Zero ( 1 ) + + # Normalizing the input signals names + MuxOutput[0] = self.i + + # signal giving the shift direction + if not self.config['dir']['con'] : + if self.config['dir']['left'] : dir = zero.Buffer() + else : dir = one.Buffer() + else : + dir = self.dir + + # signals giving the type of shift + if self.config['type']['con'] : + log = self.type[2].Buffer() + arith = self.type[1].Buffer() + rot = self.type[0].Buffer() + else : + if self.config['type']['log'] : log = one.Buffer() + else : log = zero.Buffer() + + if self.config['type']['arith'] : arith = one.Buffer() + else : arith = zero.Buffer() + + if self.config['type']['rot'] : rot = one.Buffer() + else : rot = zero.Buffer() + + # Building the control signals + c0 = Signal ( "c0", nbStages ) + c1 = Signal ( "c1", nbStages ) + + for stage in range ( nbStages ) : + c1[stage] <= ~self.cmd[stage] + c0[stage] <= c1[stage] | dir + + # Connecting the mux matrix + for stage in range ( nbStages ) : + valDec = 2**stage + + inj_lsb[stage] = Signal ( "inj_lsb%d" % stage, valDec ) + inj_msb[stage] = Signal ( "inj_msb%d" % stage, valDec ) + MuxOutput[stage+1] = Signal ( "mxout%d" % (stage+1), self.nbit ) + + if ( self.nbit-valDec-1 ) == 0 : MuxInput0 = MuxOutput[stage][0] + else : MuxInput0 = MuxOutput[stage][self.nbit-valDec-1:0] + + for i in range ( valDec ) : + inj_lsb[stage][i] <= (((MuxOutput[stage][i] & dir) | (MuxOutput[stage][self.nbit-valDec+i] & ~dir)) & rot) | (dir & ~rot) + + MuxInput0 = Cat ( MuxInput0, inj_lsb[stage] ) + MuxInput1 = MuxOutput[stage] + + # mettre zero, signe ou rot + for i in range ( valDec ) : + inj_msb[stage][i] <= (inj_lsb[stage][i] & rot) | (self.i[self.nbit-1] & arith) | (zero & log) + + if (self.nbit-1) == valDec : MuxInput2 = MuxOutput[stage][self.nbit-1] + else : MuxInput2 = MuxOutput[stage][self.nbit-1:valDec] + + MuxInput2 = Cat ( inj_msb[stage], MuxInput2 ) + mux_cmd[stage] = Cat ( c0[stage], c1[stage] ) + + MuxOutput[stage + 1] <= mux_cmd[stage].Mux ( { '0' : MuxInput0 + , '1' : MuxInput0 + , '2' : MuxInput2 + , '3' : MuxInput1 + } + ) + + # Normalizing the output signal names + self.s <= MuxOutput[nbStages] + + def GetModelName ( cls, param ) : + + modelName = "shifter" + + modelName += "_" + modelName += str(param['nbit']) + modelName += "bits" + + if param['type'] == 0x12 : modelName += "_logical_left" + elif param['type'] == 0xa : modelName += "_arith_left" + elif param['type'] == 0x6 : modelName += "_circular_left" + elif param['type'] == 0x11 : modelName += "_logical_right" + elif param['type'] == 0x9 : modelName += "_arith_right" + elif param['type'] == 0x5 : modelName += "_circular_right" + + return modelName + + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'type' : 'integer'} + + GetParam = classmethod ( GetParam ) diff --git a/stratus1/src/stratus/st_slansky.py b/stratus1/src/stratus/st_slansky.py new file mode 100644 index 00000000..1d42a4df --- /dev/null +++ b/stratus1/src/stratus/st_slansky.py @@ -0,0 +1,409 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Roselyne AVOT-CHOTIN - Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./st_slansky.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from stratus import * + +class Sub ( Model ) : + + def __init__(self, name, param): + Model.__init__(self, name, param) + if 'nbit' in param: + self.nbit = param['nbit'] + self.nbit0 = self.nbit + self.nbit1 = self.nbit + else: + self.nbit0 = param['nbit0'] + self.nbit1 = param['nbit1'] + self.nbit = max(self.nbit0,self.nbit1) + + if 'signed' not in param : self._signed = True + else : self._signed = param['signed'] + + if 'extended' not in param : self._extended = False + else : self._extended = param['extended'] + + if (self.nbit < 2): raise "\n[Stratus ERROR] slansky : input arity should be greater than 1.\n" + + def Interface(self): + self.i0 = SignalIn("i0", self.nbit0) + self.i1 = SignalIn("i1", self.nbit1) + if self._extended : self.o = SignalOut("o", self.nbit+1) + else : self.o = SignalOut("o", self.nbit) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + # extand the inputs to have the same width + if (self.nbit0 < self.nbit) : + i0e = Signal("i0e", self.nbit) + if self._signed : i0e <= self.i0.Extend(self.nbit,'signed') + else : i0e <= self.i0.Extend(self.nbit,'zero') + else: + i0e = self.i0 + if (self.nbit1 < self.nbit) : + i1e = Signal("i1e", self.nbit) + if self._signed : i1e <= self.i1.Extend(self.nbit,'signed') + else : i1e <= self.i1.Extend(self.nbit,'zero') + else: + i1e = self.i1 + + Generate ( "Slansky", "slansky_cin_%d" % ( self.nbit ), param={'nbit':self.nbit,'cin':True, 'extended':self._extended} ) + Inst ( "slansky_cin_%d" % ( self.nbit ) + , map = { 'i0' : i0e + , 'i1' : ~i1e + , 'cin' : One(1) + , 'o' : self.o + , 'vdd' : self.vdd + , 'vss' : self.vss + } + ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'nbit0' : 'integer', 'nbit1' : 'integer'} + + GetParam = classmethod ( GetParam ) + + +class Slansky ( Model ) : + + def __init__(self, name, param): + Model.__init__(self, name, param) + if 'nbit' in param: + self.nbit = param['nbit'] + self.nbit0 = self.nbit + self.nbit1 = self.nbit + else: + self.nbit0 = param['nbit0'] + self.nbit1 = param['nbit1'] + self.nbit = max(self.nbit0,self.nbit1) + + if 'signed' not in param : self._signed = True + else : self._signed = param['signed'] + + if 'extended' not in param : self._extended = False + else : self._extended = param['extended'] + + if 'cin' not in param : self._cin = False + else : self._cin = param['cin'] + + if (self.nbit < 2): raise "\n[Stratus ERROR] slansky : input arity should be greater than 1.\n" + + def Interface(self): + self.i0 = SignalIn("i0", self.nbit0) + self.i1 = SignalIn("i1", self.nbit1) + if self._cin : self.cin = SignalIn("cin", 1) + if self._extended : self.o = SignalOut("o", self.nbit+1) + else : self.o = SignalOut("o", self.nbit) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + # extand the inputs to have the same width + if (self.nbit0 < self.nbit) : + i0e = Signal("i0e", self.nbit) + if self._signed : i0e <= self.i0.Extend(self.nbit,'signed') + else : i0e <= self.i0.Extend(self.nbit,'zero') + else: + i0e = self.i0 + if (self.nbit1 < self.nbit) : + i1e = Signal("i1e", self.nbit) + if self._signed : i1e <= self.i1.Extend(self.nbit,'signed') + else : i1e <= self.i1.Extend(self.nbit,'zero') + else: + i1e = self.i1 + + # pigi preprocessing + [p,g] = pigi(i0e,i1e) + + # Slansky algorithm + [pp,gg] = pg_tree(p,g,'slansky') + + # postprocessing : + if self._cin : self.o[0] <= p[0] ^ self.cin + else : self.o[0] <= p[0].Buffer() + + for i in range(1,self.nbit): + if self._cin : self.o[i] <= p[i] ^ (gg[i-1] | (pp[i-1] & self.cin)) + else : self.o[i] <= p[i] ^ gg[i-1] + + if self._extended: + if self._signed: + ovft = Signal("ovft",1) + if self._cin: + ovft <= (gg[self.nbit-1] | (pp[self.nbit-1] & self.cin)) ^ (gg[self.nbit-2] | (pp[self.nbit-2] & self.cin)) + # pb inout asimut remplacement de o[nbit-1] par sa valeur + # self.o[self.nbit] <= (self.o[self.nbit-1] & ~ovf) | (cout & ovf) + self.o[self.nbit] <= ((p[self.nbit-1] ^ (gg[self.nbit-2] | (pp[self.nbit-2] & self.cin))) & ~ovft) | (gg[self.nbit-1] & ovft) + else: + ovft <= gg[self.nbit-1] ^ gg[self.nbit-2] + # pb inout asimut remplacement de o[nbit-1] par sa valeur + # self.o[self.nbit] <= (self.o[self.nbit-1] & ~ovf) | (cout & ovf) + self.o[self.nbit] <= ((p[self.nbit-1] ^ gg[self.nbit-2]) & ~ovft) | (gg[self.nbit-1] & ovft) + else: + if self._cin: + self.o[self.nbit] <= gg[self.nbit-1] | (pp[self.nbit-1] & self.cin) + else: + self.o[self.nbit] <= gg[self.nbit-1].Buffer() + + def GetModelName ( cls, param ) : + name = 'slansky' + + if 'nbit' in param: + name += '_%d' % (param['nbit']) + else: + if param['nbit0'] != param['nbit1'] : name += '_%dx%d' % (param['nbit0'], param['nbit1']) + else : name += '_%d' % (param['nbit0']) + + name += "bits" + + if ('cin' in param) and (param['cin']) : name += '_cin' + + return name + GetModelName = classmethod ( GetModelName ) + + def GetParam ( cls ): + + return {'nbit' : 'integer', 'nbit0' : 'integer', 'nbit1' : 'integer', 'cin' : 'boolean'} + + GetParam = classmethod ( GetParam ) + +#################################################################################################### +nb_pigi = 0 +nb_pg_tree = 0 + +def pigi(a,b): + global nb_pigi + nb_pigi += 1 + pi = Signal("pi%d_a" %nb_pigi,a._arity) + gi = Signal("gi%d_a" %nb_pigi,a._arity) + Generate ( "st_slansky.PiGiBus", "pigibus%d" % a._arity, param = {'nbit' : a._arity} ) + Inst("pigibus%d" % a._arity, + map = { + 'a' : a, + 'b' : b, + 'pi' : pi, + 'gi' : gi, + 'vdd' : a._st_cell._st_vdds[0], + 'vss' : a._st_cell._st_vsss[0] + }, + ) + return [pi,gi] + +class PiGiBus(Model): + def __init__(self, name, param): + Model.__init__(self, name, param) + self.nbit = param['nbit'] + if self.nbit < 1: + raise 'PiGiBus : input arity should be greater than 0' + + def Interface(self): + self.a = SignalIn("a",self.nbit) + self.b = SignalIn("b",self.nbit) + self.pi = SignalOut("pi",self.nbit) + self.gi = SignalOut("gi",self.nbit) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + for i in range (self.nbit): + Generate ( "st_slansky.PiGi", "pigi" ) + Inst("pigi", + map = { + 'a' : self.a[i], + 'b' : self.b[i], + 'pi' : self.pi[i], + 'gi' : self.gi[i], + 'vdd': self.vdd, + 'vss': self.vss + } + ) + + def GetParam ( cls ): + + return {'nbit' : 'integer'} + + GetParam = classmethod ( GetParam ) + + +class PiGi(Model): + def Interface(self): + self.a = SignalIn("a",1) + self.b = SignalIn("b",1) + self.pi = SignalOut("pi",1) + self.gi = SignalOut("gi",1) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + self.pi <= self.a ^ self.b + self.gi <= self.a & self.b + +######################## +def pg_tree(pi,gi,algo): + global nb_pg_tree + nb_pg_tree += 1 + p = Signal("p%d_a" %nb_pg_tree,pi._arity) + g = Signal("g%d_a" %nb_pg_tree,pi._arity) + Generate ( "st_slansky.PGTree", "pgtree%d%s" % ( pi._arity, algo ), param = {'nbit' : pi._arity, 'algo' : algo} ) + Inst("pgtree%d%s" % ( pi._arity, algo ), + map = { + 'pi' : pi, + 'gi' : gi, + 'p' : p, + 'g' : g, + 'vdd' : pi._st_cell._st_vdds[0], + 'vss' : pi._st_cell._st_vsss[0] + } + ) + return [p,g] + +class PGTree(Model): + + def __init__(self, name, param): + Model.__init__(self, name, param) + self.nbit = param['nbit'] + if self.nbit < 1: + raise 'input arity should be greater than 0' + self.algo = param['algo'] + if self.algo != 'slansky': + raise '%s algorithm is not yet implemented' %self.algo + + def Interface(self): + self.pi = SignalIn("pi",self.nbit) + self.gi = SignalIn("gi",self.nbit) + self.p = SignalOut("p",self.nbit) + self.g = SignalOut("g",self.nbit) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + nb_stages = log2(self.nbit) + matrix = prefixMatrix(self.algo,self.nbit) + p = [] + g = [] + p.append(self.pi) + g.append(self.gi) + # group propagation + Generate ( "st_slansky.PG", "pg" ) + for i in range(0, nb_stages): + p.append(Signal("p%d" %(i+1), self.nbit)) + g.append(Signal("g%d" %(i+1), self.nbit)) + for j in range(0, self.nbit): + if (j % 2**i) == 0: + k = j-1 + if matrix[i][j] == 1: + Inst("pg", + map = { + 'p1' : p[i][j], + 'g1' : g[i][j], + 'p2' : p[i][k], + 'g2' : g[i][k], + 'p' : p[i+1][j], + 'g' : g[i+1][j], + 'vdd' : self.vdd, + 'vss' : self.vss + } + ) + else: + p[i+1][j] <= p[i][j].Buffer() + g[i+1][j] <= g[i][j].Buffer() + self.p <= p[nb_stages].Buffer() + self.g <= g[nb_stages].Buffer() + + def GetParam ( cls ): + + return {'nbit' : 'integer'} + + GetParam = classmethod ( GetParam ) + + +class PG(Model): + def Interface(self): + self.p1 = SignalIn("p1",1) + self.g1 = SignalIn("g1",1) + self.p2 = SignalIn("p2",1) + self.g2 = SignalIn("g2",1) + self.p = SignalOut("p",1) + self.g = SignalOut("g",1) + + self.vdd = VddIn("vdd") + self.vss = VssIn("vss") + + def Netlist(self): + self.p <= self.p1 & self.p2 + self.g <= self.g1 | (self.g2 & self.p1) + +def prefixMatrix(algo,size): + if algo == 'slansky': + nb_stages = log2(size) + matrix = [] + for i in range(0, nb_stages): + matrix.append([]) + connection = True + j = -1 + while (j < size-1): + connection = not connection + k = -1 + while((k < 2**i-1) and (j < size-1)): + j = j + 1 + k = k + 1 + if connection : + matrix[i].append(1) + else: + matrix[i].append(0) + return matrix + else: + raise '%s algorithm is not yet implemented' %algo diff --git a/stratus1/src/stratus/stratus.py b/stratus1/src/stratus/stratus.py new file mode 100644 index 00000000..2955b979 --- /dev/null +++ b/stratus1/src/stratus/stratus.py @@ -0,0 +1,71 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./stratus.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +from st_model import * +from st_net import * +from st_instance import * +from st_placement import * +from st_placeAndRoute import * +from st_ref import * +from st_generate import * +from st_const import * +from st_cat import * +from st_param import * +from st_getrealmodel import GetWeightTime, GetWeightArea + +from util_Const import * +from util_Defs import * +from util_Misc import * +from util_Gen import * +from util_Shift import * +from util_uRom import * +from util import * + +from patterns import * diff --git a/stratus1/src/stratus/util.py b/stratus1/src/stratus/util.py new file mode 100644 index 00000000..206b6690 --- /dev/null +++ b/stratus1/src/stratus/util.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Misc.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +import re + +def getModelName ( model, param ) : + modelName = model.lower() + modelName = re.sub ( "\.", "_", modelName ) + for key in param : + modelName += "_" + modelName += str(key).lower() + modelName += str(param[key]).lower() + + return modelName diff --git a/stratus1/src/stratus/util_Const.py b/stratus1/src/stratus/util_Const.py new file mode 100644 index 00000000..8ad527ad --- /dev/null +++ b/stratus1/src/stratus/util_Const.py @@ -0,0 +1,285 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Const.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +import sys, types + +XLONG_SIZE = 8 + + +########## +## btol ## +########## +def btol ( aDigit ) : + global LV_const + + digit = 0 + + if aDigit == '0' : digit = 0 + elif aDigit == '1' : digit = 1 + else : + err = "\n[Stratus ERROR] : Invalid digit \'%c\' in boolean string \"%s\"\n" % ( aDigit, LV_const ) + raise err + + return digit + + +########## +## otol ## +########## +def otol ( aDigit ) : + global LV_const + + digit = -1 + + if aDigit >= '0' and aDigit <= '7' : digit = int ( aDigit ) + + if digit < 0 : + err = "\n[Stratus ERROR] : Invalid digit \'%c\' in octal string \"%s\".\n" % ( aDigit, LV_const ) + raise err + + return digit + + +########## +## xtol ## +########## +def xtol ( aDigit ) : + global LV_const + + digit = -1 + + if aDigit >= '0' and aDigit <= '9' : digit = int ( aDigit ) + elif aDigit == 'a' or aDigit == 'A' : digit = 10 + elif aDigit == 'b' or aDigit == 'B' : digit = 11 + elif aDigit == 'c' or aDigit == 'C' : digit = 12 + elif aDigit == 'd' or aDigit == 'D' : digit = 13 + elif aDigit == 'e' or aDigit == 'E' : digit = 14 + elif aDigit == 'f' or aDigit == 'F' : digit = 15 + + if digit < 0 : + err = "\n[Stratus ERROR] : Invalid digit \'%c\' in hexadecimal string \"%s\".\n" % ( aDigit, LV_const ) + raise err + + return digit + + +########## +## ltox ## +########## +def ltox ( aDigit ) : + digit = '\0' + + if aDigit >= 0 and aDigit <= 9 : digit = str ( aDigit ) + elif aDigit == 10 : digit = 'a' + elif aDigit == 11 : digit = 'b' + elif aDigit == 12 : digit = 'c' + elif aDigit == 13 : digit = 'd' + elif aDigit == 14 : digit = 'e' + elif aDigit == 15 : digit = 'f' + + if digit == '\0' : + err = "\n[Stratus ERROR] : Invalid number %d in hexadecimal conversion.\n" % aDigit + raise err + + return digit + + +########### +## newxl ## +########### +class newxl : + + def __init__ ( self ) : + self._size = 0L + self._l = [] + + for i in range ( XLONG_SIZE ) : self._l.append ( 0L ) + + + ########### + ## atoxl ## + ########### + def atoxl ( self, asConst ) : + global LV_const + + LV_const = asConst + + if type ( asConst ) != types.StringType : raise "\n[Stratus ERROR] : the constant must be described in a string.\n" + + base = 1 + offset = 2 + + if asConst[0] == '0' : + if asConst[1] == 'b' or asConst[1] == 'B' : base = 1 + elif asConst[1] == 'x' or asConst[1] == 'X' : base = 4 + elif asConst[1] == 'o' or asConst[1] == 'O' : base = 3 + else : + err = "\n[Stratus ERROR] : one has to specify the basis of the constant : 0b or 0x or 0o.\n" + raise err + else : + err = "\n[Stratus ERROR] : one has to specify the basis of the constant : 0b or 0x or 0o.\n" + raise err + + length = len ( asConst ) + + self._size = (length - offset) * base + + xl_size = self._size / 32 + if self._size % 32 : xl_size += 1 + + for i in range ( xl_size ) : + iRight = length - 1 - ( 32 / base ) * i + iLeft = length - ( 32 / base ) * ( i + 1 ) + + if iLeft < offset : iLeft = offset + + power = 1 + + while iRight >= iLeft : + if base == 1 : +# self._l[i] += btol ( asConst[iRight] ) << ( power - 1 ) + temp1 = power - 1 + temp2 = btol ( asConst[iRight] ) + while temp1 : + temp2 = temp2 * 2 + temp1 = temp1 - 1 + + self._l[i] += temp2 + + elif base == 3 : +# self._l[i] += otol ( asConst[iRight] ) << ( power - 1 ) + temp1 = power - 1 + temp2 = otol ( asConst[iRight] ) + while temp1 : + temp2 = temp2 * 2 + temp1 = temp1 - 1 + + self._l[i] += temp2 + + elif base == 4 : +# self._l[i] += xtol ( asConst[iRight] ) << ( power - 1 ) + temp1 = power - 1 + temp2 = xtol ( asConst[iRight] ) + while temp1 : + temp2 = temp2 * 2 + temp1 = temp1 - 1 + + self._l[i] += temp2 + + power += base + + iRight -= 1 + + + ############## + ## getxlbit ## + ############## + def getxlbit ( self, aBit ) : + i = aBit / 32 + +# mask = ( 1 << ( aBit % 32 ) ) + mask = 1 + temp = aBit % 32 + while temp : + mask = mask * 2 + temp = temp - 1 + + + if i >= XLONG_SIZE : + err = "\n[Stratus ERROR] : Requested bit", aBit, "is out of range\n" + raise err + + if self._l[i] & mask : return 1L + else : return 0L + + + ############### + ## getxlhexa ## + ############### + def getxlhexa ( self, aBit ) : + i = aBit / 32 + shift = aBit % 32 + + if i >= XLONG_SIZE : + err = "\n[Stratus ERROR] : Requested hexa %ld is out of range.\n" % aBit + raise err + + return ( ( self._l[i] ) >> shift ) & 15 + + + ############## + ## xltovhdl ## + ############## + def xltovhdl ( self ) : + pS = '' + + i = self._size + + if i % 4 : + pS = 'B\"' + + while i % 4 : + if self.getxlbit ( i - 1 ) : pS += '1' + else : pS += '0' + + i -= 1 + + if i >= 4 : + if pS != '' : pS += '\" & ' + + pS += 'X\"' + + i -= 4 + for j in range ( i, -1, -4 ) : + pS += ltox ( self.getxlhexa ( j ) ) + + pS += '\"' + + return pS diff --git a/stratus1/src/stratus/util_Defs.py b/stratus1/src/stratus/util_Defs.py new file mode 100644 index 00000000..dd35384f --- /dev/null +++ b/stratus1/src/stratus/util_Defs.py @@ -0,0 +1,122 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Defs.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from st_placement import Place, NOSYM, SYM_Y, FIXED +from st_ref import XY +from util_Gen import F_MSB_FIRST + +Y_SLICE = 50 + +# for DpgenAdder +F_ADDER_CIN = 0x00000001 +F_ADDER_SIGN = 0x00000002 +F_ADDER_OVER = 0x00000004 + + + +################ +## slice_to_y ## +################ +def slice_to_y ( s ) : + return s * Y_SLICE + + +################## +## slice_to_sym ## +################## +def slice_to_sym ( s ) : + if s % 2 : return SYM_Y + else : return NOSYM + + +################## +## slice_to_bit ## +################## +def slice_to_bit ( s, N, m ) : + if m : m = N - 1 - s + else : m = s + + return m + + +#################### +## dpgen_port_bit ## +#################### +def dpgen_port_bit ( n, flags, s ) : + return slice_to_bit ( s + , n + , flags & F_MSB_FIRST + ) + + + +################# +## dpgen_place ## +################# +def dpgen_place ( Ins, x, y, plac = FIXED ) : + sym = NOSYM + if ( y / 50 ) % 2 : sym = SYM_Y + + Place ( Ins, sym, XY ( x, y ), plac ) + + +################### +## VHDL_BUS_WIDE ## +################### +def VHDL_BUS_WIDE ( msb, lsb, n, flags ) : + + if flags & F_MSB_FIRST : temp = "to" + else : temp = "downto" + + bus = "(%ld %s %ld)" % ( dpgen_port_bit ( n, flags, msb ) + , temp + , dpgen_port_bit ( n, flags, lsb ) + ) + + return bus diff --git a/stratus1/src/stratus/util_Gen.py b/stratus1/src/stratus/util_Gen.py new file mode 100644 index 00000000..af1a47f0 --- /dev/null +++ b/stratus1/src/stratus/util_Gen.py @@ -0,0 +1,102 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Gen.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +F_LSB_FIRST = 0x00000000 # flags macro +F_MSB_FIRST = 0x00000001 +F_BEHAV = 0x00000004 + + +DPGEN_INV = 1 +DPGEN_BUFF = 2 +DPGEN_NAND2 = 3 +DPGEN_NAND3 = 4 +DPGEN_NAND4 = 5 +DPGEN_AND2 = 6 +DPGEN_AND3 = 7 +DPGEN_AND4 = 8 +DPGEN_NOR2 = 9 +DPGEN_NOR3 = 10 +DPGEN_NOR4 = 11 +DPGEN_OR2 = 12 +DPGEN_OR3 = 13 +DPGEN_OR4 = 14 +DPGEN_XNOR2 = 15 +DPGEN_XOR2 = 16 +DPGEN_NMUX2 = 17 +DPGEN_MUX2 = 18 +DPGEN_NBUSE = 19 +DPGEN_BUSE = 20 +DPGEN_NAND2MASK = 21 +DPGEN_NOR2MASK = 22 +DPGEN_XNOR2MASK = 23 +DPGEN_ADSB2F = 24 +DPGEN_SHIFT = 25 +DPGEN_NUL = 26 +DPGEN_CONST = 27 +DPGEN_RF1 = 28 +DPGEN_RF1R0 = 29 +DPGEN_RF1D = 30 +DPGEN_RF1DR0 = 31 +DPGEN_FIFO = 32 +DPGEN_RF2 = 33 +DPGEN_RF2R0 = 34 +DPGEN_RF2D = 35 +DPGEN_RF2DR0 = 36 +DPGEN_RAM = 37 +DPGEN_ROM = 38 +DPGEN_ROMTS = 39 +DPGEN_DFF = 40 +DPGEN_DFFT = 41 +DPGEN_SFF = 42 +DPGEN_SFFT = 43 +DPGEN_ROM2 = 44 +DPGEN_ROM4 = 45 +DPGEN_SHROT = 46 +DPGEN_UNKNOWN = 47 diff --git a/stratus1/src/stratus/util_Misc.py b/stratus1/src/stratus/util_Misc.py new file mode 100644 index 00000000..a9dc8767 --- /dev/null +++ b/stratus1/src/stratus/util_Misc.py @@ -0,0 +1,98 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Misc.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + + +########### +## ilog2 ## +########### +def ilog2 ( x ) : + i = 0 + while x : + i = i + 1 + x = x >> 1 + return i + +########### +## iexp2 ## +########### +def iexp2 ( x ) : + return ( 1 << x ) + +############### +## get_depth ## +############### +def get_depth ( x, depth ) : + mDepth = ilog2 ( x ) + + for i in range ( depth , mDepth + 1, 1 ) : + if x & ( 1 << i ) : return i + + return 0 + +########## +## log2 ## +########## +def log2 ( x ) : + import math + + if x <= 1 : return 0 + +# l = int(math.ceil(math.log(x-0.4999)/math.log(2))) +# if l >= 48 : raise "ERROR in log2." +# return l + + try: + l = int(math.ceil(math.log(x-0.4999)/math.log(2))) + if l>=48: raise OverflowError + # x is small enough : float rounding is accurate enough + return l + except OverflowError: + # x is too large for direct float handling + # with this method, no limit is known + return log2((x+0xffffffffL)/0x100000000L)+32 diff --git a/stratus1/src/stratus/util_Place.py b/stratus1/src/stratus/util_Place.py new file mode 100644 index 00000000..43421564 --- /dev/null +++ b/stratus1/src/stratus/util_Place.py @@ -0,0 +1,70 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Place.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +NOSYM = 1000 +SYM_X = 1001 +SYM_Y = 1002 +SYMXY = 1003 +ROT_P = 1004 +ROT_M = 1005 +SY_RP = 1006 +SY_RM = 1007 + +UNPLACED = 1010 +PLACED = 1011 +FIXED = 1012 + +UNDEFINED = 1020 +NORTH = 1021 +SOUTH = 1022 +EAST = 1023 +WEST = 1024 + +MYPITCH = 5 +MYSLICE = 50 diff --git a/stratus1/src/stratus/util_Route.py b/stratus1/src/stratus/util_Route.py new file mode 100644 index 00000000..b8185c15 --- /dev/null +++ b/stratus1/src/stratus/util_Route.py @@ -0,0 +1,62 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Route.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from Hurricane import * + +# For the placement of the model, for the standard cells mask +POWER = 2 +OCCUPIED = 1 +FREE = 0 + +# For the placement of the pads +CARRE = 800 + +# information sur le placement des couronnes +RING_INTERVAL = DbU_lambda ( 3 ) +RING_WIDTH = DbU_lambda ( 12 ) diff --git a/stratus1/src/stratus/util_Shift.py b/stratus1/src/stratus/util_Shift.py new file mode 100644 index 00000000..f0e8f39a --- /dev/null +++ b/stratus1/src/stratus/util_Shift.py @@ -0,0 +1,67 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_Shift.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +################ +def ln2p ( n ) : + i = 0 + j = n & 1 + + if ( n ) : + i = -1 + while n > 0 : + j += ( n & 1 ) + i += 1 + n >>= 1 + + return i + ( j > 1 ) + +################################ +def SYM ( BitIndex, sym, mys ) : + if BitIndex & 1 : return mys + else : return sym diff --git a/stratus1/src/stratus/util_uRom.py b/stratus1/src/stratus/util_uRom.py new file mode 100644 index 00000000..6c16ae07 --- /dev/null +++ b/stratus1/src/stratus/util_uRom.py @@ -0,0 +1,111 @@ +#!/usr/bin/python + +# This file is part of the Coriolis Project. +# Copyright (C) Laboratoire LIP6 - Departement ASIM +# Universite Pierre et Marie Curie +# +# Main contributors : +# Christophe Alexandre +# Sophie Belloeil +# Hugo Clement +# Jean-Paul Chaput +# Damien Dupuis +# Christian Masson +# Marek Sroka +# +# The Coriolis Project is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# The Coriolis Project 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 the Coriolis Project; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# License-Tag +# Authors-Tag +# =================================================================== +# +# x-----------------------------------------------------------------x +# | | +# | C O R I O L I S | +# | S t r a t u s - Netlists/Layouts Description | +# | | +# | Author : Sophie BELLOEIL | +# | E-mail : Sophie.Belloeil@asim.lip6.fr | +# | =============================================================== | +# | Py Module : "./util_uRom.py" | +# | *************************************************************** | +# | U p d a t e s | +# | | +# x-----------------------------------------------------------------x + + +from util_Gen import * + + +## Local constants ## +##################### +ERROR_INDEX = 4096 + +CELLS_ROM2 = 5 +CELLS_ROM4 = 17 + +SIZE_SNAME = 1024 + +## Local Variable ## +#################### +global LV_tsLeafCell + +LV_tsLeafCell = ["dp_rom2_buf", "zero_x0", "buf_x4", "inv_x4", "one_x0", "dp_rom4_buf", "zero_x0", "a2_x4", "a2_x4", "buf_x4", "a2_x4", "buf_x4", "dp_rom4_xr2_x4", "o2_x4", "a2_x4", "dp_rom4_nxr2_x4", "buf_x4", "o2_x4", "buf_x4", "o2_x4", "o2_x4", "one_x0"] + + +## Functions Definitions ## +########################### + +##################################################################################### +def get_index_Cell ( aiSlice, LV_Function, LV_xl0, LV_xl1, LV_xl2 = 0, LV_xl3 = 0 ) : + + index = ERROR_INDEX + + if LV_Function == DPGEN_ROM2 : + index = ( LV_xl1.getxlbit ( aiSlice ) << 1 ) + index += LV_xl0.getxlbit ( aiSlice ) + + elif LV_Function == DPGEN_ROM4 : + index = ( LV_xl3.getxlbit ( aiSlice ) << 3 ) + index += ( LV_xl2.getxlbit ( aiSlice ) << 2 ) + index += ( LV_xl1.getxlbit ( aiSlice ) << 1 ) + index += LV_xl0.getxlbit ( aiSlice ) + + return index + +################################################################### +def get_model_Cell ( aiSlice, LV_Function, aiCell, LV_iLeafCell ) : + global LV_tsLeafCell + + index = ERROR_INDEX + + if LV_Function in ( DPGEN_ROM4, DPGEN_ROM2 ) : index = LV_iLeafCell + 1 + aiCell + + if index >= ERROR_INDEX : return "bug_leaf" + + return LV_tsLeafCell[index] + +###################################### +def get_model_Buffer ( LV_Function, LV_iLeafCell ) : + global LV_tsLeafCell + + index = ERROR_INDEX + + if LV_Function in ( DPGEN_ROM4, DPGEN_ROM2 ) : index = LV_iLeafCell + + if index == ERROR_INDEX : return "bug_buff" + + return LV_tsLeafCell[index]