FABulous-FPGA 2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. fabulous/__init__.py +5 -0
  2. fabulous/custom_exception.py +66 -0
  3. fabulous/fabric_cad/README.md +152 -0
  4. fabulous/fabric_cad/__init__.py +5 -0
  5. fabulous/fabric_cad/gen_bitstream_spec.py +286 -0
  6. fabulous/fabric_cad/gen_design_top_wrapper.py +246 -0
  7. fabulous/fabric_cad/gen_npnr_model.py +253 -0
  8. fabulous/fabric_cad/timing_model/FABulous_timing_model.py +1037 -0
  9. fabulous/fabric_cad/timing_model/FABulous_timing_model_interface.py +104 -0
  10. fabulous/fabric_cad/timing_model/__init__.py +8 -0
  11. fabulous/fabric_cad/timing_model/hdlnx/__init__.py +7 -0
  12. fabulous/fabric_cad/timing_model/hdlnx/hdlnx_timing_model.py +89 -0
  13. fabulous/fabric_cad/timing_model/hdlnx/sdfnx/__init__.py +6 -0
  14. fabulous/fabric_cad/timing_model/hdlnx/sdfnx/sdf_to_graph.py +362 -0
  15. fabulous/fabric_cad/timing_model/hdlnx/sdfnx/sdf_to_graph_base.py +200 -0
  16. fabulous/fabric_cad/timing_model/hdlnx/sdfnx/timing_graph.py +329 -0
  17. fabulous/fabric_cad/timing_model/hdlnx/verilog_gate_level.py +1046 -0
  18. fabulous/fabric_cad/timing_model/models.py +427 -0
  19. fabulous/fabric_cad/timing_model/tools/__init__.py +6 -0
  20. fabulous/fabric_cad/timing_model/tools/specification.py +248 -0
  21. fabulous/fabric_cad/timing_model/tools/sta_tools/__init__.py +6 -0
  22. fabulous/fabric_cad/timing_model/tools/sta_tools/opensta.py +359 -0
  23. fabulous/fabric_cad/timing_model/tools/synth_tools/__init__.py +4 -0
  24. fabulous/fabric_cad/timing_model/tools/synth_tools/yosys.py +467 -0
  25. fabulous/fabric_definition/__init__.py +17 -0
  26. fabulous/fabric_definition/bel.py +167 -0
  27. fabulous/fabric_definition/cell_spec.py +230 -0
  28. fabulous/fabric_definition/configmem.py +35 -0
  29. fabulous/fabric_definition/define.py +163 -0
  30. fabulous/fabric_definition/fabric.py +726 -0
  31. fabulous/fabric_definition/gen_io.py +64 -0
  32. fabulous/fabric_definition/port.py +292 -0
  33. fabulous/fabric_definition/supertile.py +311 -0
  34. fabulous/fabric_definition/switch_matrix.py +71 -0
  35. fabulous/fabric_definition/tile.py +428 -0
  36. fabulous/fabric_definition/wire.py +107 -0
  37. fabulous/fabric_definition/yosys_obj.py +521 -0
  38. fabulous/fabric_files/FABulous_project_template_common/Fabric/gds_config.yaml +61 -0
  39. fabulous/fabric_files/FABulous_project_template_common/Fabric/std_cell_library.yaml +96 -0
  40. fabulous/fabric_files/FABulous_project_template_common/Test/.gitignore +17 -0
  41. fabulous/fabric_files/FABulous_project_template_common/Test/build_fabulous_fabric.tcl +4 -0
  42. fabulous/fabric_files/FABulous_project_template_common/Test/compile.Taskfile.yml +62 -0
  43. fabulous/fabric_files/FABulous_project_template_common/Test/makehex.py +28 -0
  44. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/DSP.csv +4 -0
  45. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/DSP_bot/DSP_bot.csv +8 -0
  46. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/DSP_bot/DSP_bot_switch_matrix.list +230 -0
  47. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/DSP_top/DSP_top.csv +7 -0
  48. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/DSP_top/DSP_top_switch_matrix.list +215 -0
  49. fabulous/fabric_files/FABulous_project_template_common/Tile/DSP/gds_config.yaml +6 -0
  50. fabulous/fabric_files/FABulous_project_template_common/Tile/LUT4AB/LUT4AB.csv +17 -0
  51. fabulous/fabric_files/FABulous_project_template_common/Tile/LUT4AB/LUT4AB_ConfigMem.csv +21 -0
  52. fabulous/fabric_files/FABulous_project_template_common/Tile/LUT4AB/LUT4AB_switch_matrix.list +301 -0
  53. fabulous/fabric_files/FABulous_project_template_common/Tile/LUT4AB/gds_config.yaml +6 -0
  54. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_DSP/N_term_DSP.csv +14 -0
  55. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_DSP/N_term_DSP_switch_matrix.list +15 -0
  56. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_DSP/gds_config.yaml +4 -0
  57. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_RAM_IO/N_term_RAM_IO.csv +12 -0
  58. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_RAM_IO/N_term_RAM_IO_switch_matrix.list +16 -0
  59. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_RAM_IO/gds_config.yaml +4 -0
  60. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single/N_term_single.csv +15 -0
  61. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single/N_term_single_switch_matrix.list +15 -0
  62. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single/gds_config.yaml +4 -0
  63. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single2/N_term_single2.csv +14 -0
  64. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single2/N_term_single2_switch_matrix.list +15 -0
  65. fabulous/fabric_files/FABulous_project_template_common/Tile/N_term_single2/gds_config.yaml +4 -0
  66. fabulous/fabric_files/FABulous_project_template_common/Tile/RAM_IO/RAM_IO.csv +45 -0
  67. fabulous/fabric_files/FABulous_project_template_common/Tile/RAM_IO/RAM_IO_switch_matrix.list +230 -0
  68. fabulous/fabric_files/FABulous_project_template_common/Tile/RAM_IO/gds_config.yaml +4 -0
  69. fabulous/fabric_files/FABulous_project_template_common/Tile/RegFile/RegFile.csv +6 -0
  70. fabulous/fabric_files/FABulous_project_template_common/Tile/RegFile/RegFile_switch_matrix.list +222 -0
  71. fabulous/fabric_files/FABulous_project_template_common/Tile/RegFile/gds_config.yaml +6 -0
  72. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_DSP/S_term_DSP.csv +14 -0
  73. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_DSP/S_term_DSP_switch_matrix.list +15 -0
  74. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_DSP/gds_config.yaml +4 -0
  75. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_RAM_IO/S_term_RAM_IO.csv +12 -0
  76. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_RAM_IO/S_term_RAM_IO_switch_matrix.list +16 -0
  77. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_RAM_IO/gds_config.yaml +4 -0
  78. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single/S_term_single.csv +16 -0
  79. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single/S_term_single_switch_matrix.list +17 -0
  80. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single/gds_config.yaml +4 -0
  81. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single2/S_term_single2.csv +14 -0
  82. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single2/S_term_single2_switch_matrix.list +15 -0
  83. fabulous/fabric_files/FABulous_project_template_common/Tile/S_term_single2/gds_config.yaml +4 -0
  84. fabulous/fabric_files/FABulous_project_template_common/Tile/W_IO/W_IO.csv +22 -0
  85. fabulous/fabric_files/FABulous_project_template_common/Tile/W_IO/W_IO_switch_matrix.list +69 -0
  86. fabulous/fabric_files/FABulous_project_template_common/Tile/W_IO/gds_config.yaml +4 -0
  87. fabulous/fabric_files/FABulous_project_template_common/Tile/include/Base.csv +43 -0
  88. fabulous/fabric_files/FABulous_project_template_common/Tile/include/Base.list +75 -0
  89. fabulous/fabric_files/FABulous_project_template_common/Tile/include/gds_config.yaml +61 -0
  90. fabulous/fabric_files/FABulous_project_template_common/Tile/include/gf180mcuD_latchmap.v +7 -0
  91. fabulous/fabric_files/FABulous_project_template_common/fabric.csv +47 -0
  92. fabulous/fabric_files/FABulous_project_template_common/user_design/top_wrapper.v +159 -0
  93. fabulous/fabric_files/FABulous_project_template_verilog/FABulous.tcl +7 -0
  94. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/BlockRAM_1KB.v +216 -0
  95. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/ConfigFSM.v +106 -0
  96. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/Frame_Data_Reg.v +19 -0
  97. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/Frame_Select.v +21 -0
  98. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/bitbang.v +84 -0
  99. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/config_UART.v +633 -0
  100. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/eFPGA_Config.v +99 -0
  101. fabulous/fabric_files/FABulous_project_template_verilog/Fabric/models_pack.v +204 -0
  102. fabulous/fabric_files/FABulous_project_template_verilog/Test/Makefile +83 -0
  103. fabulous/fabric_files/FABulous_project_template_verilog/Test/README.md +28 -0
  104. fabulous/fabric_files/FABulous_project_template_verilog/Test/Taskfile.yml +232 -0
  105. fabulous/fabric_files/FABulous_project_template_verilog/Test/gen_gl_xinit.py +303 -0
  106. fabulous/fabric_files/FABulous_project_template_verilog/Test/sequential_16bit_en_tb.v +126 -0
  107. fabulous/fabric_files/FABulous_project_template_verilog/Tile/DSP/DSP_bot/MULADD.v +86 -0
  108. fabulous/fabric_files/FABulous_project_template_verilog/Tile/LUT4AB/LUT4c_frame_config_dffesr.v +123 -0
  109. fabulous/fabric_files/FABulous_project_template_verilog/Tile/LUT4AB/MUX8LUT_frame_config_mux.v +156 -0
  110. fabulous/fabric_files/FABulous_project_template_verilog/Tile/RAM_IO/Config_access.v +21 -0
  111. fabulous/fabric_files/FABulous_project_template_verilog/Tile/RAM_IO/InPass4_frame_config_mux.v +75 -0
  112. fabulous/fabric_files/FABulous_project_template_verilog/Tile/RAM_IO/OutPass4_frame_config_mux.v +79 -0
  113. fabulous/fabric_files/FABulous_project_template_verilog/Tile/RegFile/RegFile_32x4.v +77 -0
  114. fabulous/fabric_files/FABulous_project_template_verilog/Tile/W_IO/Config_access.v +23 -0
  115. fabulous/fabric_files/FABulous_project_template_verilog/Tile/W_IO/IO_1_bidirectional_frame_config_pass.v +50 -0
  116. fabulous/fabric_files/FABulous_project_template_verilog/user_design/sequential_16bit_en.v +22 -0
  117. fabulous/fabric_files/FABulous_project_template_vhdl/FABulous.tcl +2 -0
  118. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/BlockRAM_1KB.vhdl +262 -0
  119. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/ConfigFSM.vhdl +160 -0
  120. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/Frame_Data_Reg.vhdl +52 -0
  121. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/Frame_Select.vhdl +52 -0
  122. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/bitbang.vhdl +124 -0
  123. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/config_UART.vhdl +716 -0
  124. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/eFPGA_Config.vhdl +166 -0
  125. fabulous/fabric_files/FABulous_project_template_vhdl/Fabric/models_pack.vhdl +456 -0
  126. fabulous/fabric_files/FABulous_project_template_vhdl/Test/Makefile +155 -0
  127. fabulous/fabric_files/FABulous_project_template_vhdl/Test/README.md +33 -0
  128. fabulous/fabric_files/FABulous_project_template_vhdl/Test/Taskfile.yml +195 -0
  129. fabulous/fabric_files/FABulous_project_template_vhdl/Test/sequential_16bit_en_tb.vhdl +270 -0
  130. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/DSP/DSP_bot/MULADD.vhdl +106 -0
  131. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/LUT4AB/LUT4c_frame_config_dffesr.vhdl +228 -0
  132. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/LUT4AB/MUX8LUT_frame_config_mux.vhdl +202 -0
  133. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/RAM_IO/Config_access.vhdl +50 -0
  134. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/RAM_IO/InPass4_frame_config_mux.vhdl +115 -0
  135. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/RAM_IO/OutPass4_frame_config_mux.vhdl +113 -0
  136. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/RegFile/RegFile_32x4.vhdl +90 -0
  137. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/W_IO/Config_access.vhdl +50 -0
  138. fabulous/fabric_files/FABulous_project_template_vhdl/Tile/W_IO/IO_1_bidirectional_frame_config_pass.vhdl +83 -0
  139. fabulous/fabric_files/FABulous_project_template_vhdl/user_design/sequential_16bit_en.vhdl +45 -0
  140. fabulous/fabric_files/__init__.py +1 -0
  141. fabulous/fabric_files/dummy_files/DUMMY_switch_matrix.list +310 -0
  142. fabulous/fabric_generator/.gitignore +13 -0
  143. fabulous/fabric_generator/__init__.py +17 -0
  144. fabulous/fabric_generator/code_generator/__init__.py +6 -0
  145. fabulous/fabric_generator/code_generator/code_generator.py +853 -0
  146. fabulous/fabric_generator/code_generator/code_generator_VHDL.py +745 -0
  147. fabulous/fabric_generator/code_generator/code_generator_Verilog.py +546 -0
  148. fabulous/fabric_generator/gds_generator/__init__.py +1 -0
  149. fabulous/fabric_generator/gds_generator/flows/__init__.py +5 -0
  150. fabulous/fabric_generator/gds_generator/flows/fabric_macro_flow.py +729 -0
  151. fabulous/fabric_generator/gds_generator/flows/fabric_optimisation_flow.py +616 -0
  152. fabulous/fabric_generator/gds_generator/flows/flow_define.py +188 -0
  153. fabulous/fabric_generator/gds_generator/flows/tile_macro_flow.py +286 -0
  154. fabulous/fabric_generator/gds_generator/gen_io_pin_config_yaml.py +298 -0
  155. fabulous/fabric_generator/gds_generator/helper.py +167 -0
  156. fabulous/fabric_generator/gds_generator/script/__init__.py +1 -0
  157. fabulous/fabric_generator/gds_generator/script/add_buffers.tcl +57 -0
  158. fabulous/fabric_generator/gds_generator/script/extract_site_info.tcl +20 -0
  159. fabulous/fabric_generator/gds_generator/script/fabric_io_place.py +205 -0
  160. fabulous/fabric_generator/gds_generator/script/odb_power.py +130 -0
  161. fabulous/fabric_generator/gds_generator/script/odb_protocol.py +46 -0
  162. fabulous/fabric_generator/gds_generator/script/pdn.tcl +55 -0
  163. fabulous/fabric_generator/gds_generator/script/pdn_config.tcl +138 -0
  164. fabulous/fabric_generator/gds_generator/script/tile_io_place.py +1179 -0
  165. fabulous/fabric_generator/gds_generator/script/vhdl_json_header.py +73 -0
  166. fabulous/fabric_generator/gds_generator/steps/__init__.py +5 -0
  167. fabulous/fabric_generator/gds_generator/steps/add_buffer.py +76 -0
  168. fabulous/fabric_generator/gds_generator/steps/auto_diode.py +148 -0
  169. fabulous/fabric_generator/gds_generator/steps/condition_magic_drc.py +24 -0
  170. fabulous/fabric_generator/gds_generator/steps/custom_pdn.py +46 -0
  171. fabulous/fabric_generator/gds_generator/steps/diodes_on_ports.py +34 -0
  172. fabulous/fabric_generator/gds_generator/steps/extract_pdk_info.py +58 -0
  173. fabulous/fabric_generator/gds_generator/steps/fabric_IO_placement.py +72 -0
  174. fabulous/fabric_generator/gds_generator/steps/fabric_area_opt.py +846 -0
  175. fabulous/fabric_generator/gds_generator/steps/magic_streamout.py +38 -0
  176. fabulous/fabric_generator/gds_generator/steps/odb_connect_pdn.py +44 -0
  177. fabulous/fabric_generator/gds_generator/steps/round_die_area.py +56 -0
  178. fabulous/fabric_generator/gds_generator/steps/tile_IO_placement.py +97 -0
  179. fabulous/fabric_generator/gds_generator/steps/tile_area_opt.py +673 -0
  180. fabulous/fabric_generator/gds_generator/steps/timed_detailed_routing.py +109 -0
  181. fabulous/fabric_generator/gds_generator/steps/vhdl_json_header.py +45 -0
  182. fabulous/fabric_generator/gds_generator/steps/while_step.py +171 -0
  183. fabulous/fabric_generator/gen_fabric/__init__.py +14 -0
  184. fabulous/fabric_generator/gen_fabric/fabric_automation.py +879 -0
  185. fabulous/fabric_generator/gen_fabric/gen_configmem.py +532 -0
  186. fabulous/fabric_generator/gen_fabric/gen_fabric.py +602 -0
  187. fabulous/fabric_generator/gen_fabric/gen_helper.py +200 -0
  188. fabulous/fabric_generator/gen_fabric/gen_switchmatrix.py +591 -0
  189. fabulous/fabric_generator/gen_fabric/gen_tile.py +1137 -0
  190. fabulous/fabric_generator/gen_fabric/gen_top_wrapper.py +368 -0
  191. fabulous/fabric_generator/parser/__init__.py +1 -0
  192. fabulous/fabric_generator/parser/parse_configmem.py +178 -0
  193. fabulous/fabric_generator/parser/parse_csv.py +887 -0
  194. fabulous/fabric_generator/parser/parse_hdl.py +336 -0
  195. fabulous/fabric_generator/parser/parse_switchmatrix.py +216 -0
  196. fabulous/fabulous.py +992 -0
  197. fabulous/fabulous_api.py +916 -0
  198. fabulous/fabulous_cli/__init__.py +5 -0
  199. fabulous/fabulous_cli/cmd_compile_design.py +235 -0
  200. fabulous/fabulous_cli/cmd_run_simulation.py +343 -0
  201. fabulous/fabulous_cli/fabulous_cli.py +1846 -0
  202. fabulous/fabulous_cli/helper.py +1000 -0
  203. fabulous/fabulous_settings.py +692 -0
  204. fabulous/geometry_generator/__init__.py +22 -0
  205. fabulous/geometry_generator/bel_geometry.py +223 -0
  206. fabulous/geometry_generator/fabric_geometry.py +420 -0
  207. fabulous/geometry_generator/geometry_gen.py +71 -0
  208. fabulous/geometry_generator/geometry_obj.py +55 -0
  209. fabulous/geometry_generator/port_geometry.py +138 -0
  210. fabulous/geometry_generator/sm_geometry.py +531 -0
  211. fabulous/geometry_generator/tile_geometry.py +696 -0
  212. fabulous/geometry_generator/wire_geometry.py +391 -0
  213. fabulous/processpool.py +43 -0
  214. fabulous_fpga-2.dist-info/METADATA +226 -0
  215. fabulous_fpga-2.dist-info/RECORD +233 -0
  216. fabulous_fpga-2.dist-info/WHEEL +5 -0
  217. fabulous_fpga-2.dist-info/entry_points.txt +3 -0
  218. fabulous_fpga-2.dist-info/licenses/AUTHORS.md +21 -0
  219. fabulous_fpga-2.dist-info/licenses/LICENSE +201 -0
  220. fabulous_fpga-2.dist-info/top_level.txt +2 -0
  221. fabulous_nix/__init__.py +1 -0
  222. fabulous_nix/build_hooks.py +58 -0
  223. fabulous_nix/flake.lock +305 -0
  224. fabulous_nix/flake.nix +394 -0
  225. fabulous_nix/nix/default.nix +53 -0
  226. fabulous_nix/nix/overlay/python.nix +60 -0
  227. fabulous_nix/nix/tools/fabulator.nix +114 -0
  228. fabulous_nix/nix/tools/ghdl-bin.nix +69 -0
  229. fabulous_nix/nix/tools/nextpnr.nix +53 -0
  230. fabulous_nix/nix/tools/yosys.nix +102 -0
  231. fabulous_nix/pyproject.toml +182 -0
  232. fabulous_nix/uv.lock +2373 -0
  233. schema/std_cell_library.schema.json +91 -0
fabulous/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ """FABulous FPGA framework package.
2
+
3
+ This file marks the FABulous directory as a Python package so Sphinx and tools can
4
+ import modules (e.g., FABulous.fabric_definition) during documentation builds.
5
+ """
@@ -0,0 +1,66 @@
1
+ """Custom exception classes for the FABulous framework.
2
+
3
+ This module defines all custom exceptions used throughout the FABulous framework for
4
+ better error handling and debugging. Each exception class is designed for specific error
5
+ scenarios that can occur during fabric generation, parsing, and configuration.
6
+ """
7
+
8
+
9
+ class CommandError(Exception):
10
+ """Exception raised for errors in the command execution."""
11
+
12
+
13
+ class EnvironmentNotSet(Exception):
14
+ """Exception raised when the environment is not set."""
15
+
16
+
17
+ class InvalidFileType(Exception):
18
+ """Exception raised for unsupported file types."""
19
+
20
+
21
+ class FabricParsingError(Exception):
22
+ """Exception raised for errors in fabric parsing."""
23
+
24
+
25
+ class SpecMissMatch(Exception):
26
+ """Exception raised when a required FASM file is missing."""
27
+
28
+
29
+ class InvalidPortType(Exception):
30
+ """Exception raised for invalid port types."""
31
+
32
+
33
+ class InvalidFabricDefinition(Exception):
34
+ """Exception raised for invalid fabric definitions."""
35
+
36
+
37
+ class InvalidFabricParameter(Exception):
38
+ """Exception raised for invalid fabric parameters."""
39
+
40
+
41
+ class InvalidSwitchMatrixDefinition(Exception):
42
+ """Exception raised for invalid matrix definitions."""
43
+
44
+
45
+ class InvalidListFileDefinition(Exception):
46
+ """Exception raised for invalid list file formats."""
47
+
48
+
49
+ class InvalidTileDefinition(Exception):
50
+ """Exception raised for invalid tile definitions."""
51
+
52
+
53
+ class InvalidSupertileDefinition(Exception):
54
+ """Exception raised for invalid supertile definitions."""
55
+
56
+
57
+ class InvalidBelDefinition(Exception):
58
+ """Exception raised for invalid BEL definitions."""
59
+
60
+
61
+ class PipelineCommandError(Exception):
62
+ """Exception raised for errors in command line arguments."""
63
+
64
+
65
+ class InvalidState(Exception):
66
+ """Exception raised for invalid state during fabric generation."""
@@ -0,0 +1,152 @@
1
+ # FABulous bitstream generation
2
+
3
+ ## Bitstream for a single tile
4
+
5
+ The fabric description file contains a table with the allocation of all tiles, like for example:
6
+
7
+ |FabricBegin| | | | | | | | | |
8
+ |---|---|---|---|---|---|---|---|---|---|
9
+ |NULL|N_term_single2|N_term_single2|N_term_single|N_term_single|N_term_single|N_term_single|N_term_single|N_term_single|NULL|
10
+ |W_IO|RegFile|DSP_top|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
11
+ |W_IO|RegFile|DSP_bot|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
12
+ |W_IO|RegFile|DSP_top|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
13
+ |W_IO|RegFile|DSP_bot|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
14
+ |W_IO|RegFile|DSP_top|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
15
+ |W_IO|RegFile|DSP_bot|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
16
+ |W_IO|RegFile|DSP_top|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
17
+ |W_IO|RegFile|DSP_bot|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|LUT4AB|CPU_IO|
18
+ |NULL|S_term_single2|S_term_single2|S_term_single|S_term_single|S_term_single|S_term_single|S_term_single|S_term_single|NULL|
19
+ |**FabricEnd**|
20
+
21
+ Let us take tile type LUT4AB as an example for the bitstream. This tile has the following BELs:
22
+
23
+ | | | |
24
+ |---|---|---|
25
+ |BEL|LUT4c_frame_config.vhdl|LA_|
26
+ |BEL|LUT4c_frame_config.vhdl|LB_|
27
+ |BEL|LUT4c_frame_config.vhdl|LC_|
28
+ |BEL|LUT4c_frame_config.vhdl|LD_|
29
+ |BEL|LUT4c_frame_config.vhdl|LE_|
30
+ |BEL|LUT4c_frame_config.vhdl|LF_|
31
+ |BEL|LUT4c_frame_config.vhdl|LG_|
32
+ |BEL|LUT4c_frame_config.vhdl|LH_|
33
+ |BEL|MUX8LUT_frame_config.vhdl|
34
+ |MATRIX|LUT4AB_switch_matrix.VHDL|
35
+ |EndTILE|
36
+
37
+ These are 8 LUT BELs (each of which use 18 configuration bits) and a MUX8LUT (which uses 2 configuration bits). The latter BEL is used to cascade multiple smaller LUTs to implement one or more larger LUTs, if needed. The LUT4AB tile also provides a switch matrix (which uses 392 configuration bits).
38
+
39
+ The configuration bits for each LUT4c BEL are:
40
+
41
+ - [15…0] LUT init value (the truth table)
42
+ - [16] c_out_mux; ‘1’: use flip flop output, ‘0’: use combinatorial LUT output
43
+ - [17] c_I0mux; ‘1’: use I0 as Carry in; ‘0’ normal mode (I0 driven by input routing multiplexer)
44
+
45
+ The 2 configuration bits of the MUX8LUT BEL describe if we cascade to implement 4 x LUT5, 2 x LUT6 or 1 x LUT7.
46
+
47
+ The switch matrix is generated from the adjacency table ```LUT4AB_switch_matrix.csv```.
48
+
49
+ In that file, each row describes one configurable switch matrix multiplexer. The exact encoding of switch matrix multiplexers is defined in function TODO where we generate the multiplexer and where we write a dictionary for the final bitstream assembly.
50
+ The configuration bits of the individual switch matrix multiplexers are concatenated in the order they appear in the adjacency table, as can be seen in the generated RTL code:
51
+
52
+ ```
53
+ -- switch matrix multiplexer N1BEG0 MUX-4
54
+ N1BEG0_input <= J_l_CD_END1 & JW2END3 & J2MID_CDb_END3 & LC_O after 80 ps;
55
+ N1BEG0 <= N1BEG0_input(TO_INTEGER(UNSIGNED(ConfigBits(1 downto 0))));
56
+
57
+ -- switch matrix multiplexer N1BEG1 MUX-4
58
+ N1BEG1_input <= J_l_EF_END2 & JW2END0 & J2MID_EFb_END0 & LD_O after 80 ps;
59
+ N1BEG1 <= N1BEG1_input(TO_INTEGER(UNSIGNED(ConfigBits(3 downto 2))));
60
+
61
+ …
62
+
63
+ -- switch matrix multiplexer J_l_GH_BEG3 MUX-4
64
+ J_l_GH_BEG3_input <= JW2END4 & W2END0 & E6END0 & N4END0 after 80 ps;
65
+ J_l_GH_BEG3 <= J_l_GH_BEG3_input(TO_INTEGER(UNSIGNED(ConfigBits(391 downto 390))));
66
+ ```
67
+
68
+ When generating the Multiplexers, FABulous is writing metadata that contains a dictionary that denotes for each possible switch matrix multiplexer setting the corresponding bits.
69
+
70
+ A tile bitstream is formed by concatenating all configuration bits of all BELs in exactly the order as specified in the LUT4AB tile descriptor followed by the switch matrix configuration bits.
71
+ Note that all BELs (including the LUTs, DSPs, etc.) and the switch matrix expose their configuration bits in the respective BEL interface and the configuration bits are stored centralized in a module <tile_type>_ConfigMem, which is provided in each tile.
72
+ For a LUT4AB tile, the concatenated tile bitstream is:
73
+
74
+ | | |
75
+ |---|---|
76
+ |[17…0]|LUT LA|
77
+ |[35…18]|LUT LB|
78
+ |[53…36]|LUT LC|
79
+ |[71…54]|LUT LD|
80
+ |[89…72]|LUT LE|
81
+ |[107…90]|LUT LF|
82
+ |[125…108]|LUT LG|
83
+ |[143…126]|LUT LH|
84
+ |[145…144]|MUX8LUT|
85
+ |[537…146]|Switch matrix|
86
+
87
+ The bold numbers are the base configuration bit offsets for the different BELs and the switch matrix. For instance, to configure the C-LUT (LC) as a 4-input AND gate using the flip-flop output and not using the carry chain, we have to set the tile configuration bits:
88
+
89
+ | | |
90
+ |---|---|
91
+ |[53]|‘0’ # no carry chain|
92
+ |[52]|‘1’ # use flip-flop output|
93
+ |[51…36]|‘1000_0000_0000_0000’ # AND truth table|
94
+
95
+ In order to translate a FASM switch matrix routing entry into the tile configuration, we look up the FASM entry in the corresponding tile type switch matrix routing dictionary (file TODO) and add the base bit offset (here 146) to the reported bits.
96
+ For instance, to configure the switch matrix setting JW2END0  N1BEG1, we set tile configuration bits [149]=’1’ and [148]=’0’.
97
+
98
+ ## Shift register configuration mode
99
+
100
+ In shift register configuration mode, the tile configuration bitstream is implemented as a single long shift register. At the moment we configure bitserial. To speed this up, multiple parallel chains (e.g., 32) maybe used. However, bitserial mode is expensive as it needs flip flops (rather than latches) and it is not well suited for partial reconfiguration.
101
+ Therefore, we recommend shift register configuration only for tiny fabrics (less than 200 LUTs) as frame-based reconfiguration is in almost any case superior.
102
+
103
+ ## Frame-based configuration
104
+
105
+ A typical CLB tile with 8 LUTs will have somewhere between 500 and 1500 configuration bits. This is mostly depending on the LUT size and switch matrix multiplexer encoding (e.g. binary encoded versus one-hot).
106
+ These configuration bits have to be packed into i configuration frames with a tile frame data width of j bits. Ideally, i and j are about the same for minimal wire cost. In FABulous, we use j horizontal frame data bits per CLB row. This means that we use the same number of horizontal fame data bits for all tile types. The number of configuration frames (which correspond to an equal number of vertical select frame lines), will be adjusted for the actual total number of required tile configuration bits. For example, a DSP tile commonly needs fewer configuration bits as a LUT tile.
107
+
108
+ As a pragmatic solution, we defined the frame data width j=32 bits in FABulous. This fits well most practical requirements and makes it easy to interface the configuration logic with standard buses.
109
+
110
+ For the LUT2AB tile with 538 tile configuration bits, we have selected i=20 configuration frames. This results in i x j = 640 addressable configuration bits. In this example, we will leave 640 – 538 = 102 addressable configuration bits unused in each LUT4AB tile. Note that no latches will be generated for those unused configuration bits.
111
+
112
+ By default, FABulous is tightly packing the used configuration bits (538 for the LUT4AB example) in their original order into 32-bit frames (starting with frame 0).
113
+ However, a user can specify a tile configuration mapping file that looks as follows (see file LUT4AB_ConfigMem.csv for the full example):
114
+
115
+ ```
116
+ #frame_name,frame_index,bits_used_in_frame,used_bits_mask,ConfigBits_ranges
117
+ frame0,0,32,1111_1111_1111_1111_0001_0001_0001_0001,15:00,16,17,144,145
118
+ frame1,1,32,1111_1111_1111_1111_0001_0001_0000_0000,33:18,34,35
119
+ frame2,2,32,1111_1111_1111_1111_0001_0001_0011_0011,51:36,52,53,515:514,517:516,#,J_l_CD_BEG0,J_l_CD_BEG1
120
+ frame3,3,32,1111_1111_1111_1111_0001_0001_0011_0011,69:54,70,71,519:518,521:520,#,J_l_CD_BEG2,J_l_CD_BEG3
121
+ ```
122
+
123
+ The important information in each line (i.e. a tile configuration frame) is a bitmask that is for each frame denoting which addressable configuration bits will be used. For instance in frame0, we are using 20 configuration bits (out of the 32 possible configuration bits). The bitmask is specified MSB to LSB index [31…0].
124
+
125
+ After the bit mask, we specify a list of tile configuration bits in exactly the same order as the bit mask. These tile configuration bits will be mapped to the frame configuration bits.
126
+
127
+ For example, the 20 bits of frame0 are specified as:
128
+
129
+ ```frame0,0,32,1111_1111_1111_1111_0001_0001_0001_0001,15:00,16,17,144,145```
130
+
131
+ This will map tile configuration bit [15] to bit 31 in frame0, 14 to bit 30 and so forth until tile configuration bit 145 is mapped to bit 0 in frame0. Therefore, the number of tile configuration bits has to match the number of ones in the frame mask. Ranges of tile configuration bits can be specified with the : operator. In the example, the tile configuration bits 15:0 are the init values of the A-LUT and they will be mapped to the 16 MSBs in frame0.
132
+
133
+ Future versions of FABulous will use the bitstream mapping feature for optimizing the physical implementation. In our first test chip, we used this feature to create a more human readable bitstream. For instance, we use this to locate the A-LUT to H-LUT init values in the first 8 frames at the high word position. The configuration modes are shown by nibbles (which will show up as one digit in a hex editor). Similarly, most multiplexers are represented by a single hex digit.
134
+
135
+ ## Bitstream assembly and configuration frame addressing
136
+
137
+ Configuration frames are composed by concatenating the same configuration frame index for an entire resource column. For instance, in our example, we are considering an FPGA fabric with 8 rows and 10 columns. This corresponds to resource columns with 8 CLBs, 8 RegFiles or 4 DSPs (DSPs take two vertically aligned tiles).
138
+ Each configuration frame is masked by a frame_address_mask in 32 bits. ```frame_address_mask[31:27]``` performs as binary index to indicate the column index. ```frame_address_mask[19:0]``` performs as one-hot data code to index the frame address.
139
+
140
+ In the following example, the first line is the frame_address_mask, ```frame_address_mask[31:27] = 00100``` presents the 8th column (X7), ```frame_address_mask[19:0] = 0000_0000_0000_0000_0010``` presents 2nd frame (frame1). The rest 8 lines binary bits will be masked to all LUT4ABs' frame1 at column X7.
141
+
142
+ ```
143
+ 20 00 00 02
144
+ FF FE FF FE
145
+ FF FE 00 00
146
+ FF FF FF FF
147
+ 00 00 00 00
148
+ FF FF FF FF
149
+ 00 00 00 00
150
+ FF FE FF FE
151
+ FF FE FF FE
152
+ ```
@@ -0,0 +1,5 @@
1
+ """Computer-aided design (CAD) tools for FPGA fabric development.
2
+
3
+ This package provides tools for fabric analysis, bitstream generation, and design flow
4
+ automation for FABulous FPGA fabrics.
5
+ """
@@ -0,0 +1,286 @@
1
+ """Bitstream specification generation module.
2
+
3
+ This module provides functionality to generate bitstream specifications from FPGA fabric
4
+ definitions. The specification defines how configuration bits map to physical frame
5
+ locations and is used during bitstream generation.
6
+ """
7
+
8
+ import string
9
+ from importlib.metadata import version
10
+ from typing import TYPE_CHECKING
11
+
12
+ from loguru import logger
13
+
14
+ from fabulous.fabric_definition.fabric import Fabric
15
+ from fabulous.fabric_generator.parser.parse_configmem import parseConfigMem
16
+ from fabulous.fabric_generator.parser.parse_switchmatrix import parseList, parseMatrix
17
+ from fabulous.fabulous_settings import get_context
18
+
19
+ if TYPE_CHECKING:
20
+ from fabulous.fabric_definition.configmem import ConfigMem
21
+
22
+
23
+ def generateBitstreamSpec(fabric: Fabric) -> dict[str, dict]:
24
+ """Generate the fabric's bitstream specification.
25
+
26
+ This is needed to tell where each FASM configuration is mapped to the physical
27
+ bitstream
28
+ The result file will be further parsed by `bit_gen.py`.
29
+
30
+ Parameters
31
+ ----------
32
+ fabric : Fabric
33
+ The fabric object for generating the bitstream specification
34
+
35
+ Returns
36
+ -------
37
+ dict[str, dict]
38
+ The bits stream specification of the fabric.
39
+ """
40
+ specData = {
41
+ "TileMap": {},
42
+ "TileSpecs": {},
43
+ "TileSpecs_No_Mask": {},
44
+ "FrameMap": {},
45
+ "FrameMapEncode": {},
46
+ "ArchSpecs": {
47
+ "MaxFramesPerCol": fabric.maxFramesPerCol,
48
+ "FrameBitsPerRow": fabric.frameBitsPerRow,
49
+ "FrameSelectWidth": fabric.frameSelectWidth,
50
+ "DesyncBit": fabric.desync_flag,
51
+ "SyncHeaderHex": fabric.syncHeaderHex,
52
+ "IncludeBorderRows": False, # Currently not supported in FABulous
53
+ "FABulousVersion": version("FABulous-FPGA"),
54
+ },
55
+ }
56
+
57
+ tileMap = {}
58
+ for y, row in enumerate(fabric.tile):
59
+ for x, tile in enumerate(row):
60
+ if tile is not None:
61
+ tileMap[f"X{x}Y{y}"] = tile.name
62
+ else:
63
+ tileMap[f"X{x}Y{y}"] = "NULL"
64
+
65
+ specData["TileMap"] = tileMap
66
+ configMemList: list[ConfigMem] = []
67
+ for y, row in enumerate(fabric.tile):
68
+ for x, tile in enumerate(row):
69
+ if tile is None:
70
+ continue
71
+ if "fabric.csv" in str(tile.tileDir):
72
+ # backward compatibility for old project structure
73
+ # We need to take the matrixDir from the tile, since there
74
+ # is the actual path to the tile defined in the fabric.csv
75
+ if tile.matrixDir.is_file():
76
+ configMemPath = tile.matrixDir.parent / f"{tile.name}_ConfigMem.csv"
77
+ elif tile.matrixDir.is_dir():
78
+ configMemPath = tile.matrixDir / f"{tile.name}_ConfigMem.csv"
79
+ else:
80
+ configMemPath = (
81
+ get_context().proj_dir
82
+ / "Tile"
83
+ / tile.name
84
+ / f"{tile.name}_ConfigMem.csv"
85
+ )
86
+ logger.warning(
87
+ f"MatrixDir for {tile.name} is not a valid file or directory. "
88
+ f"Assuming default path: {configMemPath}"
89
+ )
90
+ else:
91
+ configMemPath = tile.tileDir.parent.joinpath(
92
+ f"{tile.name}_ConfigMem.csv"
93
+ )
94
+ logger.info(f"ConfigMemPath: {configMemPath}")
95
+
96
+ if configMemPath.exists() and configMemPath.is_file():
97
+ configMemList = parseConfigMem(
98
+ configMemPath,
99
+ fabric.maxFramesPerCol,
100
+ fabric.frameBitsPerRow,
101
+ tile.globalConfigBits,
102
+ )
103
+ elif tile.globalConfigBits > 0:
104
+ logger.critical(
105
+ f"No ConfigMem csv file found for {tile.name} which "
106
+ "have config bits"
107
+ )
108
+ configMemList = []
109
+ else:
110
+ logger.info(f"No config memory for {tile.name}.")
111
+ configMemList = []
112
+
113
+ encodeDict = [-1] * (fabric.maxFramesPerCol * fabric.frameBitsPerRow)
114
+ maskDic = {}
115
+ for cfm in configMemList:
116
+ maskDic[cfm.frameIndex] = cfm.usedBitMask
117
+ # matching the value in the configBitRanges with the reversedBitMask
118
+ # bit 0 in bit mask is the first value in the configBitRanges
119
+ for i, char in enumerate(cfm.usedBitMask):
120
+ if char == "1":
121
+ encodeDict[cfm.configBitRanges.pop(0)] = (
122
+ fabric.frameBitsPerRow - 1 - i
123
+ ) + fabric.frameBitsPerRow * cfm.frameIndex
124
+
125
+ # filling the maskDic with the unused frames
126
+ for i in range(fabric.maxFramesPerCol - len(configMemList)):
127
+ maskDic[len(configMemList) + i] = "0" * fabric.frameBitsPerRow
128
+
129
+ specData["FrameMap"][tile.name] = maskDic
130
+ if tile.globalConfigBits == 0:
131
+ logger.info(f"No config memory for X{x}Y{y}_{tile.name}.")
132
+ specData["FrameMap"][tile.name] = {}
133
+ specData["FrameMapEncode"][tile.name] = {}
134
+
135
+ curBitOffset = 0
136
+ curTileMap = {}
137
+ curTileMapNoMask = {}
138
+
139
+ for i, bel in enumerate(tile.bels):
140
+ for featureKey, keyDict in bel.belFeatureMap.items():
141
+ for entry in keyDict:
142
+ if isinstance(entry, int):
143
+ for v in keyDict[entry]:
144
+ curTileMap[
145
+ f"{string.ascii_uppercase[i]}.{featureKey}"
146
+ ] = {encodeDict[curBitOffset + v]: keyDict[entry][v]}
147
+ curTileMapNoMask[
148
+ f"{string.ascii_uppercase[i]}.{featureKey}"
149
+ ] = {encodeDict[curBitOffset + v]: keyDict[entry][v]}
150
+ curBitOffset += len(keyDict[entry])
151
+
152
+ # All the generation will be working on the tile level with the tileDic
153
+ # This is added to propagate the updated switch matrix to each of the tile
154
+ # in the fabric
155
+ if tile.matrixDir.suffix == ".list":
156
+ tile.matrixDir = tile.matrixDir.with_suffix(".csv")
157
+
158
+ result = parseMatrix(tile.matrixDir, tile.name)
159
+ for source, sinkList in result.items():
160
+ controlWidth = 0
161
+ for i, sink in enumerate(reversed(sinkList)):
162
+ controlWidth = (len(sinkList) - 1).bit_length()
163
+ controlValue = f"{len(sinkList) - 1 - i:0{controlWidth}b}"
164
+ pip = f"{sink}.{source}"
165
+ if len(sinkList) < 2:
166
+ curTileMap[pip] = {}
167
+ curTileMapNoMask[pip] = {}
168
+ continue
169
+
170
+ for c, curChar in enumerate(controlValue[::-1]):
171
+ if pip not in curTileMap:
172
+ curTileMap[pip] = {}
173
+ curTileMapNoMask[pip] = {}
174
+
175
+ curTileMap[pip][encodeDict[curBitOffset + c]] = curChar
176
+ curTileMapNoMask[pip][encodeDict[curBitOffset + c]] = curChar
177
+
178
+ curBitOffset += controlWidth
179
+
180
+ # And now we add empty config bit mappings for immutable connections
181
+ # (i.e. wires), as nextpnr sees these the same as normal pips
182
+ for wire in tile.wireList:
183
+ curTileMap[f"{wire.source}.{wire.destination}"] = {}
184
+ curTileMapNoMask[f"{wire.source}.{wire.destination}"] = {}
185
+
186
+ specData["TileSpecs"][f"X{x}Y{y}"] = curTileMap
187
+ specData["TileSpecs_No_Mask"][f"X{x}Y{y}"] = curTileMapNoMask
188
+
189
+ # Supertile bitstream features. A supertile's config bits physically live in
190
+ # its master tile's frame column (the master tile's own ConfigMem leaves those
191
+ # bits free). Within the supertile config space the bit order is
192
+ # [switch-matrix bits][BEL bits], matching genSuperTile()'s ST_ConfigBits
193
+ # slicing. The BEL and switch-matrix features are added to the master tile's
194
+ # TileSpecs entry alongside the master tile's own features.
195
+ st_bel_count: dict[tuple[int, int], int] = {}
196
+ for superTile in fabric.superTileDic.values():
197
+ if not superTile.bels and superTile.supertile_matrix_dir is None:
198
+ continue
199
+
200
+ st_config_bits = superTile.total_config_bits
201
+
202
+ st_encode_dict = [-1] * (fabric.maxFramesPerCol * fabric.frameBitsPerRow)
203
+ st_mask_dic: dict[int, str] = {}
204
+ if st_config_bits > 0:
205
+ st_config_mem_list = parseConfigMem(
206
+ superTile.tileDir.parent / f"{superTile.name}_ConfigMem.csv",
207
+ fabric.maxFramesPerCol,
208
+ fabric.frameBitsPerRow,
209
+ st_config_bits,
210
+ )
211
+ for cfm in st_config_mem_list:
212
+ st_mask_dic[cfm.frameIndex] = cfm.usedBitMask
213
+ for i, char in enumerate(cfm.usedBitMask):
214
+ if char == "1":
215
+ st_encode_dict[cfm.configBitRanges.pop(0)] = (
216
+ fabric.frameBitsPerRow - 1 - i
217
+ ) + fabric.frameBitsPerRow * cfm.frameIndex
218
+
219
+ sm_connections: dict[str, list[str]] = {}
220
+ if superTile.supertile_matrix_dir is not None:
221
+ mat_path = superTile.supertile_matrix_dir
222
+ if mat_path.suffix == ".list":
223
+ for dest, src in parseList(mat_path):
224
+ sm_connections.setdefault(dest, []).append(src)
225
+ else:
226
+ sm_connections = parseMatrix(mat_path, superTile.name)
227
+
228
+ tx_local, ty_local = superTile.get_master_tile_coords()
229
+
230
+ for base_fx, base_fy, _ in fabric.iter_super_tile_placements(superTile):
231
+ ftx = base_fx + tx_local
232
+ fty = base_fy + ty_local
233
+ master_tile = fabric.tile[fty][ftx]
234
+
235
+ frame_map = specData["FrameMap"].setdefault(master_tile.name, {})
236
+ for frame_idx, mask in st_mask_dic.items():
237
+ existing = frame_map.get(frame_idx, "0" * fabric.frameBitsPerRow)
238
+ frame_map[frame_idx] = "".join(
239
+ "1" if a == "1" or b == "1" else "0"
240
+ for a, b in zip(existing, mask, strict=True)
241
+ )
242
+
243
+ curTileMap = specData["TileSpecs"].setdefault(f"X{ftx}Y{fty}", {})
244
+ curTileMapNoMask = specData["TileSpecs_No_Mask"].setdefault(
245
+ f"X{ftx}Y{fty}", {}
246
+ )
247
+
248
+ curBitOffset = 0
249
+ for source, sinkList in sm_connections.items():
250
+ controlWidth = (len(sinkList) - 1).bit_length()
251
+ if st_config_bits == 0:
252
+ # No config bits — all connections are passthrough.
253
+ for sink in sinkList:
254
+ for t in (curTileMap, curTileMapNoMask):
255
+ t[f"{sink}.{source}"] = {}
256
+ continue
257
+ for i, sink in enumerate(reversed(sinkList)):
258
+ pip = f"{sink}.{source}"
259
+ if len(sinkList) < 2:
260
+ for t in (curTileMap, curTileMapNoMask):
261
+ t[pip] = {}
262
+ continue
263
+ controlValue = f"{len(sinkList) - 1 - i:0{controlWidth}b}"
264
+ for c, curChar in enumerate(controlValue[::-1]):
265
+ for t in (curTileMap, curTileMapNoMask):
266
+ t.setdefault(pip, {})
267
+ t[pip][st_encode_dict[curBitOffset + c]] = curChar
268
+ curBitOffset += controlWidth
269
+
270
+ bel_coord = (ftx, fty)
271
+ bel_offset = len(master_tile.bels) + st_bel_count.get(bel_coord, 0)
272
+ for i, bel in enumerate(superTile.bels):
273
+ letter = string.ascii_uppercase[bel_offset + i]
274
+ for featureKey, keyDict in bel.belFeatureMap.items():
275
+ for entry in keyDict:
276
+ if not isinstance(entry, int):
277
+ continue
278
+ for v in keyDict[entry]:
279
+ for t in (curTileMap, curTileMapNoMask):
280
+ t[f"{letter}.{featureKey}"] = {
281
+ st_encode_dict[curBitOffset + v]: keyDict[entry][v]
282
+ }
283
+ curBitOffset += len(keyDict[entry])
284
+ st_bel_count[bel_coord] = bel_offset + len(superTile.bels)
285
+
286
+ return specData