├── .gitignore
├── LICENSE.txt
├── README.txt
├── assembly_process_definitions.xml
├── chiplet_nre_study_def.xml
├── chiplet_nre_study_netlist.xml
├── design.py
├── generate_grid_test_files.py
├── generate_grid_test_files_3d.py
├── generate_plot.py
├── io_definitions.xml
├── layer_definitions.xml
├── load_and_test_design.py
├── load_and_test_design_test_breakdown.py
├── netlist.xml
├── readDesignFromFile.py
├── run_all_sweeps.sh
├── search_and_replace.py
├── sip.xml
├── sweep_assembly_process.sh
├── sweep_chiplet_size.sh
├── sweep_defect_density.sh
├── sweep_nre.sh
├── sweep_nre_1_custom.sh
├── sweep_reach.sh
├── sweep_substrates.sh
├── sweep_test_coverage.sh
├── sweep_test_coverage_immature.sh
├── test_definitions.xml
└── wafer_process_definitions.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | __*
2 | *.png
3 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2025 UCLA NanoCAD Laboratory
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | =======================================================================
2 | Copyright 2025 UCLA NanoCAD Laboratory
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | =======================================================================
16 | Author: Alexander Graening (agraening@ucla.edu)
17 |
18 | ====================================
19 | README for Chiplet Cost Model
20 | ====================================
21 |
22 | General Usage:
23 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml netlist.xml sip.xml
24 |
25 | The above command will run the cost calculation on the demo configuration file sip.xml and demo netlist file netlist.xml
26 |
27 | To generate the plots in the paper "CATCH: a Cost Analysis Tool for Co-optimization of chiplet-based Heterogeneous systems" you can launch the script run_all_sweeps.sh
28 | sh run_all_sweeps.sh
29 |
30 | Requirements:
31 | Currently, I am running this using:
32 | Python 3.10.6
33 | Numpy 1.25.0
34 | xml.etree.ElementTree 1.3.0
35 |
36 |
37 | ====================================
38 | Included Files:
39 | ====================================
40 |
41 | design.py
42 | Contains class definitions for the chip class that is core to the model along with class definitions for layers, IOs, testing processes, wafer processes, and assembly methods.
43 |
44 | generate_grid_test_files.py
45 | This is used to generate the netlist and system definition files for the 800mm^2 testcase. The chiplets are placed next to each other on an interposer.
46 |
47 | generate_grid_test_files_3D.py
48 | This is used to generate the netlist and system definition files for the 800mm^2 testcase. The chiplets are stacked on top of each other in a single stack.
49 |
50 | load_and_test_design.py
51 | This is used to pass file names as an argument and build the system. This also prints out the computed system information.
52 |
53 | load_and_test_design_test_breakdown.py
54 | This is a variation of the above file to split the cost into scrap cost and non-scrap cost for plotting.
55 |
56 | readDesignFromFile.py
57 | Functions for reading xml files into the dictionary format and processing into the class structure are included here.
58 |
59 | search_and_replace.py
60 | This simply takes an input file and replaces one string with another. This is used to modify the configuration files to run sweeps.
61 |
62 | sip.xml
63 | Demo system definition file
64 |
65 | netlist.xml
66 | Demo netlist file
67 |
68 | io_definitions.xml
69 | IO definitions file
70 |
71 | layer_definitions.xml
72 | Layer definition file. This contains both "combined" layers that model a full stackup and individual layers such as metal and active layers to build a full stackup based on number of required metal layers.
73 |
74 | test_definitions.xml
75 | Test process definition file. This contains the constants necessary to compute testing cost and to compute a testing method aware yield.
76 |
77 | wafer_process_definitions.xml
78 | This contains the constants that are generally shared about parameters such as reticle size and wafer processing yield.
79 |
80 | assembly_process_definitions.xml
81 | This contains definitions of constants necessary for computing the assembly cost and yield impact.
82 |
83 | chiplet_nre_study_def.xml and chiplet_nre_study_netlist.xml
84 | Configuration files for study with a single low volume chip in a design with 3 high volume chips.
85 |
86 | run_all_sweeps.sh
87 | Runs all sweep scripts.
88 |
89 | sweep_assembly_process.sh
90 | Runs sweep on the assembly process across different 800mm2 homogeneous graph processor test cases.
91 |
92 | sweep_chiplet_size.sh
93 | Runs sweep of different 800mm2 homogeneous graph processor test cases for different process technology nodes.
94 |
95 | sweep_defect_density.sh
96 | Runs sweep defect density across different 800mm2 homogeneous graph processor test cases.
97 |
98 | sweep_nre.sh
99 | Runs sweep of different quantities across different 800mm2 homogeneous graph processor test cases without.
100 |
101 | sweep_nre_1_custom.sh
102 | Runs a sweep of quantity for a design with a single low-volume die and 3 high volume dies.
103 |
104 | sweep_reach.sh
105 | Runs a sweep of reach across a testcase.
106 |
107 | sweep_substrates.sh
108 | Compares organic, silicon, and glass for one example.
109 |
110 | sweep_test_coverage.sh
111 | Sweeps test coverage at the "typical" defect density used for the paper.
112 |
113 | sweep_test_coverage_immature.sh
114 | Sweeps test coverage at an elevated defect density.
115 |
116 |
117 | ====================================
118 | General Summary
119 | ====================================
120 |
121 | The general organization of the code:
122 | - Class definitions and model functions are included in design.py
123 | - Functions for reading the design are included in readDesignFromFile.py
124 | - load_and_test_design.py is a wrapper that makes this easier to use to test a single design.
125 | - Example sweeps are included in distinct .sh scripts and can all be run by launching run_all_sweeps.sh
126 |
127 | Modify or create new .xml files to evaluate new systems and processes. To add new considerations, edit the corresponding class in design.py.
128 |
--------------------------------------------------------------------------------
/assembly_process_definitions.xml:
--------------------------------------------------------------------------------
1 |
76 |
77 |
90 |
91 |
113 |
114 |
136 |
137 |
159 |
160 |
173 |
195 |
196 |
218 |
219 |
241 |
242 |
264 |
265 |
278 |
300 |
301 |
304 |
326 |
327 |
328 |
--------------------------------------------------------------------------------
/chiplet_nre_study_def.xml:
--------------------------------------------------------------------------------
1 |
18 |
40 |
62 |
63 |
85 |
86 |
108 |
109 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/chiplet_nre_study_netlist.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
25 |
26 |
32 |
33 |
39 |
40 |
46 |
47 |
53 |
54 |
60 |
61 |
67 |
68 |
74 |
75 |
81 |
82 |
88 |
89 |
95 |
96 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/generate_grid_test_files.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | import math
18 | import sys
19 | import os
20 | # Generate a system definition .xml file.
21 |
22 |
23 | # As input, take the number of chiplets, IO type, a bidirectional flag, external bandwidth, and the total power as inputs.
24 | if len(sys.argv) != 8:
25 | print("ERROR: Incorrect Number of Input Arguments\nUsage: python generate_test_files.py \nExiting...")
26 | sys.exit(1)
27 |
28 |
29 | number_of_chiplets = int(sys.argv[1])
30 | interchiplet_IO_type = sys.argv[2]
31 | bidirectional = sys.argv[3]
32 | organic_flag_str = sys.argv[4]
33 | total_ext_bandwidth = float(sys.argv[5])
34 | total_power = float(sys.argv[6])
35 | logic_fraction = float(sys.argv[7])
36 |
37 | total_chiplet_area = 800
38 |
39 | area_of_chiplets = total_chiplet_area / number_of_chiplets
40 | power_per_chiplet = total_power / number_of_chiplets
41 |
42 | identifier = "chiplet_" + str(number_of_chiplets) + "_" + str(math.floor(area_of_chiplets))
43 |
44 | test_process = "KGD_free_test"
45 | interposer_test_process = "KGD_interposer_free_test"
46 | wafer_process = "process_1"
47 | # wafer_diameter = "300"
48 | # edge_exclusion = "3"
49 | # wafer_process_yield = " 0.94"
50 | # reticle_x = "26"
51 | # reticle_y = "33"
52 |
53 | # externalInputs = "0"
54 | # externalOutputs = "0"
55 |
56 | system_quantity = "10000000"
57 | quantity=str(int(system_quantity) * number_of_chiplets)
58 |
59 | if bidirectional == "True":
60 | bidirectional_flag = True
61 | elif bidirectional == "False":
62 | bidirectional_flag = False
63 | else:
64 | print("ERROR: Invalid bidirectional flag\nExiting...")
65 | sys.exit(1)
66 |
67 | if organic_flag_str == "True" or organic_flag_str == "true":
68 | organic_flag = True
69 | elif organic_flag_str == "False" or organic_flag_str == "false":
70 | organic_flag = False
71 | else:
72 | organic_flag = False
73 |
74 | if organic_flag:
75 | assembly_process = "organic_simultaneous_bonding"
76 | interposer_stackup = "1:combined_interposer_organic"
77 | else:
78 | assembly_process = "silicon_individual_bonding"
79 | interposer_stackup = "1:combined_interposer_silicon"
80 |
81 | chip_stackup = "1:combined_5nm"
82 |
83 | # Generate def xml file
84 | def_file = open(identifier + "_def" + ".xml", "w")
85 |
86 | def_file.write("\n")
108 |
109 | for i in range(number_of_chiplets):
110 | def_file.write("\t\n")
132 | def_file.write("\t\n")
133 |
134 | def_file.write("\n")
135 | def_file.close()
136 |
137 | # Generate netlist xml file
138 | # Open netlist file
139 | netlist_file = open(identifier + "_netlist" + ".xml", "w")
140 | netlist_file.write("\n")
141 |
142 | edge_bandwidth = total_ext_bandwidth / (math.sqrt(number_of_chiplets) * 4)
143 |
144 | for i in range(number_of_chiplets):
145 | if i == 0 or i == number_of_chiplets - 1 or i == math.sqrt(number_of_chiplets) - 1 or i == number_of_chiplets - math.sqrt(number_of_chiplets):
146 | # corner
147 | external_bandwidth = edge_bandwidth * 2
148 | elif i % math.sqrt(number_of_chiplets) == 0 or i % math.sqrt(number_of_chiplets) == math.sqrt(number_of_chiplets) - 1:
149 | # edge
150 | external_bandwidth = edge_bandwidth
151 | netlist_file.write("\t\n")
157 | netlist_file.write("\t\n")
158 | if bidirectional_flag != True:
159 | # Now the other direction
160 | netlist_file.write("\t\n")
166 | netlist_file.write("\t\n")
167 |
168 | # Now define internal connections assuming a grid of squares with the same edge bandwidth between each adjacent chiplets.
169 | for i in range(number_of_chiplets):
170 | if i % math.sqrt(number_of_chiplets) != math.sqrt(number_of_chiplets) - 1: # Connect to chiplet on the right
171 | netlist_file.write("\t\n")
177 | netlist_file.write("\t\n")
178 | if bidirectional_flag != True:
179 | if i % math.sqrt(number_of_chiplets) != 0: # Connect to chiplet on the left
180 | netlist_file.write("\t\n")
186 | netlist_file.write("\t\n")
187 | if i >= math.sqrt(number_of_chiplets): # Connect to chiplet above
188 | netlist_file.write("\t\n")
194 | netlist_file.write("\t\n")
195 | if bidirectional_flag != True:
196 | if i < number_of_chiplets - math.sqrt(number_of_chiplets): # Connect to chiplet below
197 | netlist_file.write("\t\n")
203 | netlist_file.write("\t\n")
204 |
205 |
206 | netlist_file.write("\n")
207 | netlist_file.close()
208 | print("Generated " + identifier + "_def.xml and " + identifier + "_netlist.xml")
209 |
--------------------------------------------------------------------------------
/generate_grid_test_files_3d.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | import math
18 | import sys
19 | import os
20 | # Generate a system definition .xml file.
21 |
22 |
23 | # As input, take the number of chiplets, IO type, a bidirectional flag, external bandwidth, and the total power as inputs.
24 | if len(sys.argv) != 8:
25 | print("ERROR: Incorrect Number of Input Arguments\nUsage: python generate_test_files_3d.py \nExiting...")
26 | sys.exit(1)
27 |
28 |
29 | number_of_chiplets = int(sys.argv[1])
30 | interchiplet_IO_type = sys.argv[2]
31 | bidirectional = sys.argv[3]
32 | organic_flag_str = sys.argv[4]
33 | total_ext_bandwidth = float(sys.argv[5])
34 | total_power = float(sys.argv[6])
35 | logic_fraction = float(sys.argv[7])
36 |
37 | total_chiplet_area = 800
38 |
39 | area_of_chiplets = total_chiplet_area / number_of_chiplets
40 | power_per_chiplet = total_power / number_of_chiplets
41 |
42 | identifier = "chiplet_" + str(number_of_chiplets) + "_" + str(math.floor(area_of_chiplets))
43 |
44 | test_process = "KGD_free_test"
45 | interposer_test_process = "KGD_interposer_free_test"
46 | wafer_process = "process_1"
47 | # wafer_diameter = "300"
48 | # edge_exclusion = "3"
49 | # wafer_process_yield = " 0.94"
50 | # reticle_x = "26"
51 | # reticle_y = "33"
52 |
53 | # externalInputs = "0"
54 | # externalOutputs = "0"
55 |
56 | system_quantity = "10000000"
57 | quantity=str(int(system_quantity) * number_of_chiplets)
58 |
59 | if bidirectional == "True":
60 | bidirectional_flag = True
61 | elif bidirectional == "False":
62 | bidirectional_flag = False
63 | else:
64 | print("ERROR: Invalid bidirectional flag\nExiting...")
65 | sys.exit(1)
66 |
67 | if organic_flag_str == "True" or organic_flag_str == "true":
68 | organic_flag = True
69 | elif organic_flag_str == "False" or organic_flag_str == "false":
70 | organic_flag = False
71 | else:
72 | organic_flag = False
73 |
74 | if organic_flag:
75 | assembly_process = "organic_simultaneous_bonding"
76 | interposer_stackup = "1:combined_interposer_organic"
77 | else:
78 | assembly_process = "silicon_individual_bonding"
79 | interposer_stackup = "1:combined_interposer_silicon"
80 |
81 | chip_stackup = "1:combined_5nm"
82 |
83 | # Generate def xml file
84 | def_file = open(identifier + "_def" + ".xml", "w")
85 |
86 | def_file.write("\n")
108 |
109 | for i in range(number_of_chiplets):
110 | def_file.write("\t\n")
132 |
133 | for i in range(number_of_chiplets):
134 | def_file.write("\t\n")
135 |
136 | def_file.write("\n")
137 | def_file.close()
138 |
139 | # Generate netlist xml file
140 | # Open netlist file
141 | netlist_file = open(identifier + "_netlist" + ".xml", "w")
142 | netlist_file.write("\n")
143 |
144 | edge_bandwidth = total_ext_bandwidth / (math.sqrt(number_of_chiplets) * 4)
145 |
146 | for i in range(number_of_chiplets):
147 | if i == 0 or i == number_of_chiplets - 1 or i == math.sqrt(number_of_chiplets) - 1 or i == number_of_chiplets - math.sqrt(number_of_chiplets):
148 | # corner
149 | external_bandwidth = edge_bandwidth * 2
150 | elif i % math.sqrt(number_of_chiplets) == 0 or i % math.sqrt(number_of_chiplets) == math.sqrt(number_of_chiplets) - 1:
151 | # edge
152 | external_bandwidth = edge_bandwidth
153 | netlist_file.write("\t\n")
159 | netlist_file.write("\t\n")
160 | # Now the other direction
161 | netlist_file.write("\t\n")
167 | netlist_file.write("\t\n")
168 |
169 | # Now define internal connections assuming a grid of squares with the same edge bandwidth between each adjacent chiplets.
170 | for i in range(number_of_chiplets):
171 | if i % math.sqrt(number_of_chiplets) != math.sqrt(number_of_chiplets) - 1: # Connect to chiplet on the right
172 | netlist_file.write("\t\n")
178 | netlist_file.write("\t\n")
179 | if bidirectional_flag != True:
180 | if i % math.sqrt(number_of_chiplets) != 0: # Connect to chiplet on the left
181 | netlist_file.write("\t\n")
187 | netlist_file.write("\t\n")
188 | if i >= math.sqrt(number_of_chiplets): # Connect to chiplet above
189 | netlist_file.write("\t\n")
195 | netlist_file.write("\t\n")
196 | if bidirectional_flag != True:
197 | if i < number_of_chiplets - math.sqrt(number_of_chiplets): # Connect to chiplet below
198 | netlist_file.write("\t\n")
204 | netlist_file.write("\t\n")
205 |
206 |
207 | netlist_file.write("\n")
208 | netlist_file.close()
209 | print("Generated " + identifier + "_def.xml and " + identifier + "_netlist.xml")
210 |
--------------------------------------------------------------------------------
/generate_plot.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | import matplotlib.pyplot as plt
18 | import math
19 | import sys
20 |
21 | def read_data(filename):
22 | with open(filename, 'r') as file:
23 | lines = file.readlines()
24 |
25 | # Extract x-axis and y-axis
26 | x_axis_label = lines[0].strip().split(':')[1].strip()
27 | y_axis_label = lines[1].strip().split(':')[1].strip()
28 |
29 | # Extract x-labels from line 2 starting after the ":"
30 | x_labels = lines[2].strip().split(':')[1].strip().split()
31 | #x_labels = lines[2].strip().split()[1:]
32 |
33 | y_values = []
34 | series_labels = []
35 |
36 | stack = False
37 |
38 | # Extract the numbers from the subsequent lines
39 | if lines[3].strip().split()[0] == 'series:':
40 | lines_per_series = len(x_labels) + 1
41 | for series in range(0, (len(lines) - 3) // lines_per_series):
42 | series_labels.append(lines[3 + series * lines_per_series].strip().split(':')[1].strip())
43 | sub_list = []
44 | for line in lines[lines_per_series * series + 4:lines_per_series * (series + 1) + 4 - 1]:
45 | sub_str_list = line.strip().split()
46 | sub_list.append([float(value) for value in sub_str_list])
47 | #sub_list.append([float(value) for value in line.strip().split()])
48 | y_values.append(sub_list)
49 | elif lines[3].strip().split()[0] == 'stack:':
50 | # series_labels should be interpreted as the labels for the different segments of the stacked bar chart here.
51 | series_labels = lines[3].strip().split(':')[1].strip().split()
52 | intermediate_y_values = []
53 | lines_per_series = len(x_labels)
54 | for line in lines[4:lines_per_series + 4]:
55 | sub_list = []
56 | for value in line.strip().split():
57 | sub_list.append(float(value))
58 | intermediate_y_values.append(sub_list)
59 | for i in range(len(intermediate_y_values[0])):
60 | y_values.append([intermediate_y_values[j][i] for j in range(len(intermediate_y_values))])
61 | stack = True
62 | else:
63 | series_labels.append("")
64 | series = [float(line.strip()) for line in lines[3:]]
65 | y_values.append(series)
66 |
67 | return x_axis_label, y_axis_label, x_labels, y_values, series_labels, stack
68 |
69 | def plot_data(x_axis_label, y_axis_label, x_labels, y_values, series_labels, stack, rotation, plot_type, output_filename, x_justification='right'):
70 | plt.figure(figsize=(10, 6))
71 |
72 | bar_width = 0.5
73 |
74 | if stack:
75 | for i in range(len(y_values)):
76 | sum_y_values = []
77 | for j in range(len(y_values[i])):
78 | sum_y_values.append(sum([y_values[k][j] for k in range(i)]))
79 | plt.bar(x_labels, y_values[i], label=series_labels[i], bottom=sum_y_values, width=bar_width)
80 | plt.legend()
81 | else:
82 | if plot_type == 'line':
83 | if len(series_labels) > 1:
84 | for i in range(len(y_values)):
85 | plt.plot(x_labels, y_values[i], marker='o', label=series_labels[i])
86 | plt.legend()
87 | else:
88 | plt.plot(x_labels, y_values[0], marker='o')
89 | elif plot_type == 'bar':
90 | if len(series_labels) > 1:
91 | for i in range(len(y_values)):
92 | plt.bar(x_labels, y_values[i], label=series_labels[i], width=bar_width)
93 | plt.legend()
94 | else:
95 | plt.bar(x_labels, y_values[0], width=bar_width)
96 | else:
97 | print("Invalid plot type. Use 'line' or 'bar'.")
98 | return
99 |
100 | fontsize=22
101 |
102 | plt.xlabel(x_axis_label, fontsize=fontsize)
103 | plt.ylabel(y_axis_label, fontsize=fontsize)
104 | # plt.title(f'{x_axis_label} vs {y_axis_label}', fontsize=fontsize)
105 | if len(series_labels) > 1:
106 | # Count up the total number of characters in the series labels
107 | total_chars = sum([len(label) for label in series_labels])
108 | n_cols = math.ceil(len(series_labels)/math.ceil(total_chars/20))
109 | plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.2), fontsize=fontsize-10, ncol=n_cols)
110 | plt.grid(True)
111 | plt.xticks(rotation=rotation, ha=x_justification, fontsize=fontsize)
112 | plt.yticks(fontsize=fontsize)
113 | plt.tight_layout()
114 | # Output to file
115 | plt.savefig(output_filename)
116 | # Display the plot
117 | # plt.show()
118 |
119 | def main():
120 | if len(sys.argv) != 6:
121 | print("Usage: python generate_plot.py ")
122 | sys.exit(1)
123 |
124 | filename = sys.argv[1]
125 | rotation = float(sys.argv[2])
126 | x_justification = sys.argv[3]
127 | plot_type = sys.argv[4]
128 | output_filename = sys.argv[5]
129 | x_axis_label, y_axis_label, x_labels, y_values, series_labels, stack = read_data(filename)
130 | plot_data(x_axis_label, y_axis_label, x_labels, y_values, series_labels, stack, rotation, plot_type, output_filename, x_justification)
131 |
132 | if __name__ == "__main__":
133 | main()
134 |
--------------------------------------------------------------------------------
/io_definitions.xml:
--------------------------------------------------------------------------------
1 |
78 |
79 |
80 |
84 |
86 |
88 |
89 |
91 |
92 |
101 |
102 |
103 |
112 |
113 |
122 |
123 |
132 |
133 |
142 |
143 |
152 |
153 |
155 |
157 |
158 |
160 |
161 |
170 |
171 |
173 |
174 |
178 |
187 |
188 |
197 |
198 |
207 |
208 |
217 |
218 |
227 |
228 |
237 |
238 |
247 |
248 |
257 |
258 |
267 |
268 |
270 |
271 |
272 |
281 |
282 |
291 |
292 |
301 |
302 |
305 |
314 |
315 |
324 |
325 |
334 |
335 |
344 |
345 |
354 |
355 |
356 |
365 |
366 |
367 |
--------------------------------------------------------------------------------
/layer_definitions.xml:
--------------------------------------------------------------------------------
1 |
72 |
73 |
74 |
75 |
76 |
87 |
88 |
90 |
91 |
102 |
103 |
104 |
114 |
115 |
116 |
126 |
127 |
128 |
138 |
139 |
141 |
143 |
144 |
145 |
146 |
147 |
157 |
158 |
168 |
169 |
172 |
182 |
183 |
186 |
196 |
197 |
200 |
210 |
211 |
212 |
222 |
223 |
224 |
225 |
235 |
236 |
246 |
247 |
257 |
258 |
259 |
260 |
270 |
271 |
281 |
282 |
292 |
293 |
294 |
304 |
305 |
315 |
316 |
326 |
327 |
328 |
--------------------------------------------------------------------------------
/load_and_test_design.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Filename: load_and_test_design.py
19 | # Author: Alexander Graening
20 | # Affiliation: University of California, Los Angeles
21 | # Email: agraening@ucla.edu
22 | #
23 | # Description: This is the main file used to launch loading a single design and viewing cost.
24 | # ====================================================================================
25 |
26 | import design as d
27 | import readDesignFromFile as readDesign
28 | import sys
29 | import time
30 |
31 |
32 | # Main function
33 | def main():
34 | # Get start time
35 | start_time = time.time()
36 | # Read the file names as command line arguments.
37 | if len(sys.argv) != 8:
38 | print("Usage: python load_and_test_design.py ")
39 | return 1
40 |
41 | # Read the File Names as Command Line Arguments
42 | io_file = sys.argv[1]
43 | layer_file = sys.argv[2]
44 | wafer_process_file = sys.argv[3]
45 | assembly_process_file = sys.argv[4]
46 | test_file = sys.argv[5]
47 | netlist_file = sys.argv[6]
48 | chip_file = sys.argv[7]
49 |
50 | # Read the Design Library Files
51 | io_list = readDesign.io_definition_list_from_file(io_file)
52 | layer_list = readDesign.layer_definition_list_from_file(layer_file)
53 | wafer_process_list = readDesign.wafer_process_definition_list_from_file(wafer_process_file)
54 | assembly_process_list = readDesign.assembly_process_definition_list_from_file(assembly_process_file)
55 | test_process_list = readDesign.test_process_definition_list_from_file(test_file)
56 |
57 | # Read the Design Netlist File
58 | adjacency_matrix, utilization, names = readDesign.global_adjacency_matrix_from_file(netlist_file,io_list)
59 |
60 | # Read the System Definition
61 | sip = d.Chip(filename = chip_file, etree = None, parent_chip = None, wafer_process_list = wafer_process_list, assembly_process_list = assembly_process_list, test_process_list = test_process_list, layers = layer_list, ios = io_list, adjacency_matrix_definitions = adjacency_matrix, average_bandwidth_utilization=utilization, block_names = names, static = False)
62 |
63 | # Print the Design Description
64 | # sip.print_description()
65 |
66 | #print("Cost of design = " + str(sip.get_cost()))
67 | print(sip.compute_total_cost())
68 |
69 | # for chip in sip.get_chips():
70 | # print(chip.name + " " + str(chip.get_cost()))
71 |
72 | end_time = time.time()
73 |
74 | #print("Total time: " + str(end_time - start_time) + " seconds")
75 |
76 | return 0
77 |
78 |
79 | # Setup auto-run of main function.
80 | if __name__ == "__main__":
81 | main()
82 |
--------------------------------------------------------------------------------
/load_and_test_design_test_breakdown.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Filename: load_and_test_design.py
19 | # Author: Alexander Graening
20 | # Affiliation: University of California, Los Angeles
21 | # Email: agraening@ucla.edu
22 | #
23 | # Description: This is the main file used to launch loading a single design and viewing cost.
24 | # ====================================================================================
25 |
26 | import design as d
27 | import readDesignFromFile as readDesign
28 | import sys
29 | import time
30 |
31 |
32 | # Main function
33 | def main():
34 | # Get start time
35 | start_time = time.time()
36 | # Read the file names as command line arguments.
37 | if len(sys.argv) != 8:
38 | print("Usage: python load_and_test_design.py ")
39 | return 1
40 |
41 | # Read the File Names as Command Line Arguments
42 | io_file = sys.argv[1]
43 | layer_file = sys.argv[2]
44 | wafer_process_file = sys.argv[3]
45 | assembly_process_file = sys.argv[4]
46 | test_file = sys.argv[5]
47 | netlist_file = sys.argv[6]
48 | chip_file = sys.argv[7]
49 |
50 | # Read the Design Library Files
51 | io_list = readDesign.io_definition_list_from_file(io_file)
52 | layer_list = readDesign.layer_definition_list_from_file(layer_file)
53 | wafer_process_list = readDesign.wafer_process_definition_list_from_file(wafer_process_file)
54 | assembly_process_list = readDesign.assembly_process_definition_list_from_file(assembly_process_file)
55 | test_process_list = readDesign.test_process_definition_list_from_file(test_file)
56 |
57 | # Read the Design Netlist File
58 | adjacency_matrix, utilization, names = readDesign.global_adjacency_matrix_from_file(netlist_file,io_list)
59 |
60 | # Read the System Definition
61 | sip = d.Chip(filename = chip_file, etree = None, parent_chip = None, wafer_process_list = wafer_process_list, assembly_process_list = assembly_process_list, test_process_list = test_process_list, layers = layer_list, ios = io_list, adjacency_matrix_definitions = adjacency_matrix, average_bandwidth_utilization=utilization, block_names = names, static = False)
62 |
63 | # Print the Design Description
64 | # sip.print_description()
65 |
66 | #print("Cost of design = " + str(sip.get_cost()))
67 | print(str(sip.compute_total_non_scrap_cost()) + " " + str(sip.compute_scrap_cost()))
68 |
69 | # for chip in sip.get_chips():
70 | # print(chip.name + " " + str(chip.get_cost()))
71 |
72 | end_time = time.time()
73 |
74 | #print("Total time: " + str(end_time - start_time) + " seconds")
75 |
76 | return 0
77 |
78 |
79 | # Setup auto-run of main function.
80 | if __name__ == "__main__":
81 | main()
82 |
--------------------------------------------------------------------------------
/netlist.xml:
--------------------------------------------------------------------------------
1 |
75 |
76 |
77 |
78 |
84 |
85 |
86 |
92 |
93 |
94 |
100 |
101 |
102 |
108 |
109 |
110 |
116 |
117 |
118 |
124 |
125 |
126 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/readDesignFromFile.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Filename: readDesignFromFile.py
19 | # Author: Alexander Graening
20 | # Affiliation: University of California, Los Angeles
21 | # Email: agraening@ucla.edu
22 | #
23 | # Description: This file contains the functions to read the given library .xml files.
24 | # ====================================================================================
25 |
26 | import design as d
27 | import numpy as np
28 | import xml.etree.ElementTree as ET
29 | import math
30 | import sys
31 |
32 | # Note that in if you add new parameters to the XML file, you will need to add them to the class constructors in design.py
33 | # This means that you will also need to add the initial values to the class declaration in the following functions
34 | # otherwise there will be a rather confusing error since the static attribute will be set True by default.
35 |
36 | # Function to read the wafer process definitions.
37 | def wafer_process_definition_list_from_file(filename):
38 | # print("Reading wafer process definitions from file: " + filename)
39 | # Read the XML file.
40 | tree = ET.parse(filename)
41 | # Get root of the XML file.
42 | root = tree.getroot()
43 | # List of wafer process .
44 | wp_list = []
45 | # Iterate over the IO definitions.
46 | for wp_def in root:
47 | # Create an Wafer Process object.
48 | wp = d.WaferProcess(name = "", wafer_diameter = 0.0, edge_exclusion = 0.0, wafer_process_yield = 0.0,
49 | dicing_distance = 0.0, reticle_x = 0.0, reticle_y = 0.0, wafer_fill_grid = "False",
50 | nre_front_end_cost_per_mm2_memory = 0.0, nre_back_end_cost_per_mm2_memory = 0.0,
51 | nre_front_end_cost_per_mm2_logic = 0.0, nre_back_end_cost_per_mm2_logic = 0.0,
52 | nre_front_end_cost_per_mm2_analog = 0.0, nre_back_end_cost_per_mm2_analog = 0.0,
53 | static = False)
54 | attributes = wp_def.attrib
55 | # Iterate over the IO definition attributes.
56 | # Set the IO object attributes.
57 | wp.name = attributes["name"]
58 | wp.wafer_diameter =float(attributes["wafer_diameter"])
59 | wp.edge_exclusion = float(attributes["edge_exclusion"])
60 | wp.wafer_process_yield = float(attributes["wafer_process_yield"])
61 | wp.dicing_distance = float(attributes["dicing_distance"])
62 | wp.reticle_x = float(attributes["reticle_x"])
63 | wp.reticle_y = float(attributes["reticle_y"])
64 | wp.wafer_fill_grid = attributes["wafer_fill_grid"]
65 | wp.nre_front_end_cost_per_mm2_memory = float(attributes["nre_front_end_cost_per_mm2_memory"])
66 | wp.nre_back_end_cost_per_mm2_memory = float(attributes["nre_back_end_cost_per_mm2_memory"])
67 | wp.nre_front_end_cost_per_mm2_logic = float(attributes["nre_front_end_cost_per_mm2_logic"])
68 | wp.nre_back_end_cost_per_mm2_logic = float(attributes["nre_back_end_cost_per_mm2_logic"])
69 | wp.nre_front_end_cost_per_mm2_analog = float(attributes["nre_front_end_cost_per_mm2_analog"])
70 | wp.nre_back_end_cost_per_mm2_analog = float(attributes["nre_back_end_cost_per_mm2_analog"])
71 | wp.set_static()
72 | # Append the wafer_process object to the list.
73 | wp_list.append(wp)
74 | # Return the list of wafer process definition objects.
75 | return wp_list
76 |
77 | # Define a function to read the IO definitions from a file.
78 | def io_definition_list_from_file(filename):
79 | # print("Reading IO definitions from file: " + filename)
80 | # Read the XML file.
81 | tree = ET.parse(filename)
82 | root = tree.getroot()
83 | # Create a list of IO objects.
84 | io_list = []
85 | # Iterate over the IO definitions.
86 | for io_def in root:
87 | # Create an IO object.
88 | io = d.IO(type = "", rx_area = 0.0, tx_area = 0.0, shoreline = 0.0, bandwidth = 0.0, wire_count = 0,
89 | bidirectional = "False", energy_per_bit = 0.0, reach = 0.0, static = False)
90 | attributes = io_def.attrib
91 | # Iterate over the IO definition attributes.
92 | # Set the IO object attributes.
93 | io.type = attributes["type"]
94 | io.rx_area = float(attributes["rx_area"])
95 | io.tx_area = float(attributes["tx_area"])
96 | io.shoreline = float(attributes["shoreline"])
97 | io.bandwidth = float(attributes["bandwidth"])
98 | io.wire_count = int(attributes["wire_count"])
99 | io.bidirectional = attributes["bidirectional"]
100 | io.energy_per_bit = float(attributes["energy_per_bit"])
101 | io.reach = float(attributes["reach"])
102 | io.set_static()
103 | # Append the IO object to the list.
104 | io_list.append(io)
105 | # Return the list of IO objects.
106 | return io_list
107 |
108 | # Define a function to read the layer definitions from a file.
109 | def layer_definition_list_from_file(filename):
110 | # print("Reading layer definitions from file: " + filename)
111 | # Read the XML file.
112 | tree = ET.parse(filename)
113 | root = tree.getroot()
114 | # Create a list of layer objects.
115 | layer_list = []
116 | # Iterate over the layer definitions.
117 | for layer_def in root:
118 | # Create a layer object.
119 | layer = d.Layer(name = "", active = "False", cost_per_mm2 = 0, transistor_density = 0, defect_density = 0, critical_area_ratio = 0,
120 | clustering_factor = 0, litho_percent = 0, mask_cost = 0, stitching_yield = 0, static = False)
121 | attributes = layer_def.attrib
122 | # Set the layer object attributes.
123 | layer.name = attributes["name"]
124 | layer.active = attributes["active"]
125 | layer.cost_per_mm2 = float(attributes["cost_per_mm2"])
126 | layer.transistor_density = float(attributes["transistor_density"])
127 | layer.defect_density = float(attributes["defect_density"])
128 | layer.critical_area_ratio = float(attributes["critical_area_ratio"])
129 | layer.clustering_factor = float(attributes["clustering_factor"])
130 | layer.litho_percent = float(attributes["litho_percent"])
131 | layer.mask_cost = float(attributes["nre_mask_cost"])
132 | layer.stitching_yield = float(attributes["stitching_yield"])
133 |
134 | layer.set_static()
135 | # Append the layer object to the list.
136 | layer_list.append(layer)
137 | # Return the list of layer objects.
138 | # print("At end of layer_list_from_file")
139 | return layer_list
140 |
141 | # Define a function to read the assembly process definitions from a file.
142 | def assembly_process_definition_list_from_file(filename):
143 | # print("Reading assembly process definitions from file: " + filename)
144 | # Read the XML file.
145 | tree = ET.parse(filename)
146 | root = tree.getroot()
147 | # Create a list of assembly process objects.
148 | assembly_process_list = []
149 | # Iterate over the assembly process definitions.
150 | for assembly_process_def in root:
151 | # Create an assembly process object.
152 | assembly_process = d.Assembly(name = "", materials_cost_per_mm2 = 0.0, bb_cost_per_second = None, picknplace_machine_cost = 0.0,
153 | picknplace_machine_lifetime = 1.0, picknplace_machine_uptime = 0.0, picknplace_technician_yearly_cost = 0.0,
154 | picknplace_time = 0.0, picknplace_group = 0, bonding_machine_cost = 0.0, bonding_machine_lifetime = 1.0,
155 | bonding_machine_uptime = 0.0, bonding_technician_yearly_cost = 0.0, bonding_time = 0.0,
156 | bonding_group = 0, die_separation = 0.0, edge_exclusion = 0.0, bonding_pitch = 0.0, max_pad_current_density = 0.0,
157 | alignment_yield = 0.0, bonding_yield = 0.0, dielectric_bond_defect_density = 0.0, static = False)
158 |
159 | attributes = assembly_process_def.attrib
160 |
161 | assembly_process.name = attributes["name"]
162 | if attributes["bb_cost_per_second"] == "":
163 | assembly_process.bb_cost_per_second = None
164 | else:
165 | assembly_process.bb_cost_per_second = float(attributes["bb_cost_per_second"])
166 | # # The following would set machine and technician parameters as a list of an undefined length.
167 | # # This has been switched to defining these parameters in terms of two values, one for bonding and one for pick and place.
168 | # # Leaving this for now, in case a reason comes up to rever to the old version.
169 | # assembly_process.set_machine_cost_list([float(x) for x in attributes["machine_cost_list"].split(',')])
170 | # assembly_process.set_machine_lifetime_list([float(x) for x in attributes["machine_lifetime_list"].split(',')])
171 | # assembly_process.set_machine_uptime_list([float(x) for x in attributes["machine_uptime_list"].split(',')])
172 | # assembly_process.set_technician_yearly_cost_list([float(x) for x in attributes["technician_yearly_cost_list"].split(',')])
173 | assembly_process.materials_cost_per_mm2 = float(attributes["materials_cost_per_mm2"])
174 | assembly_process.picknplace_machine_cost = float(attributes["picknplace_machine_cost"])
175 | assembly_process.picknplace_machine_lifetime = float(attributes["picknplace_machine_lifetime"])
176 | assembly_process.picknplace_machine_uptime = float(attributes["picknplace_machine_uptime"])
177 | assembly_process.picknplace_technician_yearly_cost = float(attributes["picknplace_technician_yearly_cost"])
178 | assembly_process.picknplace_time = float(attributes["picknplace_time"])
179 | assembly_process.picknplace_group = int(attributes["picknplace_group"])
180 | assembly_process.bonding_machine_cost = float(attributes["bonding_machine_cost"])
181 | assembly_process.bonding_machine_lifetime = float(attributes["bonding_machine_lifetime"])
182 | assembly_process.bonding_machine_uptime = float(attributes["bonding_machine_uptime"])
183 | assembly_process.bonding_technician_yearly_cost = float(attributes["bonding_technician_yearly_cost"])
184 | assembly_process.bonding_time = float(attributes["bonding_time"])
185 | assembly_process.bonding_group = int(attributes["bonding_group"])
186 | assembly_process.compute_picknplace_cost_per_second()
187 | assembly_process.compute_bonding_cost_per_second()
188 | assembly_process.die_separation = float(attributes["die_separation"])
189 | assembly_process.edge_exclusion = float(attributes["edge_exclusion"])
190 | assembly_process.bonding_pitch = float(attributes["bonding_pitch"])
191 | assembly_process.max_pad_current_density = float(attributes["max_pad_current_density"])
192 | assembly_process.alignment_yield = float(attributes["alignment_yield"])
193 | assembly_process.bonding_yield = float(attributes["bonding_yield"])
194 | assembly_process.dielectric_bond_defect_density = float(attributes["dielectric_bond_defect_density"])
195 |
196 | assembly_process.set_static()
197 |
198 | # Append the assembly process object to the list.
199 | assembly_process_list.append(assembly_process)
200 | # Return the list of assembly process objects.
201 | return assembly_process_list
202 |
203 | # Define a function to read the test process definitions from a file.
204 | def test_process_definition_list_from_file(filename):
205 | # print("Reading test process definitions from file: " + filename)
206 | # Read the XML file.
207 | tree = ET.parse(filename)
208 | root = tree.getroot()
209 | # Create a list of test process objects.
210 | test_process_list = []
211 | # Iterate over the test process definitions.
212 | for test_process_def in root:
213 | # Create a test process object.
214 | test_process = d.Test(name = "",
215 | time_per_test_cycle = 0.0, cost_per_second = 0.0, samples_per_input = 1,
216 | test_self = "False", bb_self_pattern_count = "", bb_self_scan_chain_length = "",
217 | self_defect_coverage = 0.0, self_test_reuse = 1,
218 | self_num_scan_chains = 0, self_num_io_per_scan_chain = 0, self_num_test_io_offset = 0,
219 | self_test_failure_dist = "normal",
220 | test_assembly = "False", bb_assembly_pattern_count = "", bb_assembly_scan_chain_length = "",
221 | assembly_defect_coverage = 0.0, assembly_test_reuse = 1,
222 | assembly_num_scan_chains = 0, assembly_num_io_per_scan_chain = 0, assembly_num_test_io_offset = 0,
223 | assembly_test_failure_dist = "normal",
224 | static = False)
225 |
226 | attributes = test_process_def.attrib
227 | test_process.name = attributes["name"]
228 | test_process.time_per_test_cycle = float(attributes["time_per_test_cycle"])
229 | test_process.samples_per_input = int(attributes["samples_per_input"])
230 |
231 | test_process.cost_per_second = float(attributes["cost_per_second"])
232 |
233 | test_process.test_self = attributes["test_self"]
234 | if attributes["bb_self_pattern_count"] == "":
235 | test_process.bb_self_pattern_count = None
236 | else:
237 | test_process.bb_self_pattern_count = int(attributes["bb_self_pattern_count"])
238 | if attributes["bb_self_scan_chain_length"] == "":
239 | test_process.bb_self_scan_chain_length = None
240 | else:
241 | test_process.bb_self_scan_chain_length = int(attributes["bb_self_scan_chain_length"])
242 | test_process.self_defect_coverage = float(attributes["self_defect_coverage"])
243 |
244 | test_process.self_test_reuse = int(attributes["self_test_reuse"])
245 | test_process.self_num_scan_chains = int(attributes["self_num_scan_chains"])
246 | test_process.self_num_io_per_scan_chain = int(attributes["self_num_io_per_scan_chain"])
247 | test_process.self_num_test_io_offset = int(attributes["self_num_test_io_offset"])
248 |
249 | test_process.self_test_failure_dist = attributes["self_test_failure_dist"]
250 |
251 | test_process.test_assembly = attributes["test_assembly"]
252 | if attributes["bb_assembly_pattern_count"] == "":
253 | test_process.bb_assembly_pattern_count = None
254 | else:
255 | test_process.bb_assembly_pattern_count = int(attributes["bb_assembly_pattern_count"])
256 | if attributes["bb_assembly_scan_chain_length"] == "":
257 | test_process.bb_assembly_scan_chain_length = None
258 | else:
259 | test_process.bb_assembly_scan_chain_length = int(attributes["bb_assembly_scan_chain_length"])
260 | test_process.assembly_defect_coverage = float(attributes["assembly_defect_coverage"])
261 |
262 | test_process.assembly_test_reuse = int(attributes["assembly_test_reuse"])
263 | test_process.assembly_num_scan_chains = int(attributes["assembly_num_scan_chains"])
264 | test_process.assembly_num_io_per_scan_chain = int(attributes["assembly_num_io_per_scan_chain"])
265 | test_process.assembly_num_test_io_offset = int(attributes["assembly_num_test_io_offset"])
266 |
267 | test_process.assembly_test_failure_dist = attributes["assembly_test_failure_dist"]
268 |
269 | test_process.set_static()
270 |
271 | #test_process.set_name(attributes["name"])
272 | #test_process.set_test_self(True if attributes["test_self"] == "True" or attributes["test_self"] == "TRUE" or attributes["test_self"] == "true" else False)
273 | #test_process.set_test_assembly(True if attributes["test_assembly"] == "True" or attributes["test_assembly"] == "TRUE" or attributes["test_assembly"] == "true" else False)
274 | #test_process.set_self_defect_coverage(float(attributes["self_defect_coverage"]))
275 | #test_process.set_assembly_defect_coverage(float(attributes["assembly_defect_coverage"]))
276 | #test_process.set_self_test_cost_per_mm2(float(attributes["self_test_cost_per_mm2"]))
277 | #test_process.set_assembly_test_cost_per_mm2(float(attributes["assembly_test_cost_per_mm2"]))
278 | #test_process.set_self_pattern_count(int(attributes["self_pattern_count"]))
279 | #test_process.set_assembly_pattern_count(int(attributes["assembly_pattern_count"]))
280 | #test_process.set_self_test_failure_dist(int(attributes["self_test_failure_dist"]))
281 | #test_process.set_assembly_test_failure_dist(int(attributes["assembly_test_failure_dist"]))
282 | #test_process.set_static()
283 |
284 | test_process_list.append(test_process)
285 |
286 | return test_process_list
287 |
288 | # Define a function to construct the global adjacency matrix from the netlist file.
289 | def global_adjacency_matrix_from_file(filename, io_list):
290 | # TOSO: Add comments on building adjacency matrix.
291 | # print("Reading netlist from file: " + filename)
292 | # Read the XML file.
293 | tree = ET.parse(filename)
294 | root = tree.getroot()
295 |
296 | # Split the root.attrib["block_names"] string at commas and store in list.
297 | block_names = []
298 |
299 | # The output format is a dictionary of items with format {type: numpy array adjacencey matrix}
300 | global_adjacency_matrix = {}
301 | # The following contains entries mirroring the global adjacency matrix
302 | # For each entry in the global adjacency matrix, this indicates the average bandwidth utilization
303 | # that should be used for the power calculation.
304 | average_bandwidth_utilization = {}
305 |
306 | # Iterate over the net definitions.
307 | for net_def in root:
308 | link_average_bandwidth_utilization = float(net_def.attrib["average_bandwidth_utilization"])
309 | link_type = net_def.attrib["type"]
310 | # Check if the type of net is already a key in the dictionary.
311 | if link_type not in global_adjacency_matrix:
312 | # print("Adding new net type to adjacency matrix: " + link_type)
313 | # If so, append the new net to the existing adjacency matrix.
314 | global_adjacency_matrix[link_type] = np.zeros((len(block_names), len(block_names)))
315 | average_bandwidth_utilization[link_type] = np.zeros((len(block_names), len(block_names)))
316 |
317 | # If block 0 or block 1 is not in the list of block names, add it.
318 | if net_def.attrib["block0"] not in block_names:
319 | # print("Adding new block to adjacency matrix: " + net_def.attrib["block0"])
320 | block_names.append(net_def.attrib["block0"])
321 | # Add a row and column to each numpy adjacency matrix.
322 | for key in global_adjacency_matrix:
323 | global_adjacency_matrix[key] = np.pad(global_adjacency_matrix[key], ((0,1),(0,1)), 'constant', constant_values=0)
324 | average_bandwidth_utilization[key] = np.pad(average_bandwidth_utilization[key], ((0,1),(0,1)), 'constant', constant_values=0)
325 | if net_def.attrib["block1"] not in block_names:
326 | # print("Adding new block to adjacency matrix: " + net_def.attrib["block1"])
327 | block_names.append(net_def.attrib["block1"])
328 | # Add a row and column to each numpy adjacency matrix.
329 | for key in global_adjacency_matrix:
330 | global_adjacency_matrix[key] = np.pad(global_adjacency_matrix[key], ((0,1),(0,1)), 'constant', constant_values=0)
331 | average_bandwidth_utilization[key] = np.pad(average_bandwidth_utilization[key], ((0,1),(0,1)), 'constant', constant_values=0)
332 |
333 | io_bandwidth = None
334 | bidirectional = None
335 |
336 | # print("Searching for and IO type that matches " + link_type)
337 | for io in io_list:
338 | #print(io.type())
339 | if link_type == io.type:
340 | io_bandwidth = io.bandwidth
341 | bidirectional = io.bidirectional
342 |
343 | if io_bandwidth is None or bidirectional is None:
344 | print("ERROR: Net type " + link_type + " not found in io_list.")
345 | sys.exit(1)
346 |
347 | # Find the indices of the two blocks connected by the net.
348 | block1_index = block_names.index(net_def.attrib["block0"])
349 | block2_index = block_names.index(net_def.attrib["block1"])
350 |
351 | if net_def.attrib["bb_count"] == "":
352 | ios_to_add = int(math.ceil(float(net_def.attrib["bandwidth"])/io_bandwidth))
353 | else:
354 | ios_to_add = int(net_def.attrib["bb_count"])
355 | if ios_to_add == 0:
356 | peak_utilization_factor = 1
357 | else:
358 | peak_utilization_factor = float(net_def.attrib["bandwidth"])/(ios_to_add*io_bandwidth)
359 | link_average_bandwidth_utilization *= peak_utilization_factor
360 | if not bidirectional:
361 | if average_bandwidth_utilization[link_type][block1_index,block2_index] == 0:
362 | average_bandwidth_utilization[link_type][block1_index,block2_index] = link_average_bandwidth_utilization
363 | else:
364 | average_bandwidth_utilization[link_type][block1_index,block2_index] = (average_bandwidth_utilization[link_type][block1_index,block2_index]*global_adjacency_matrix[link_type][block1_index,block2_index] + link_average_bandwidth_utilization*ios_to_add)/(global_adjacency_matrix[link_type][block1_index,block2_index] + ios_to_add)
365 | global_adjacency_matrix[link_type][block1_index,block2_index] += ios_to_add
366 | else:
367 | if average_bandwidth_utilization[link_type][block1_index,block2_index] == 0:
368 | average_bandwidth_utilization[link_type][block1_index,block2_index] = link_average_bandwidth_utilization
369 | else:
370 | average_bandwidth_utilization[link_type][block1_index,block2_index] = (average_bandwidth_utilization[link_type][block1_index,block2_index]*global_adjacency_matrix[link_type][block1_index,block2_index] + link_average_bandwidth_utilization*ios_to_add)/(global_adjacency_matrix[link_type][block1_index,block2_index] + ios_to_add)
371 | global_adjacency_matrix[link_type][block1_index,block2_index] += ios_to_add
372 | if average_bandwidth_utilization[link_type][block2_index,block1_index] == 0:
373 | average_bandwidth_utilization[link_type][block2_index,block1_index] = link_average_bandwidth_utilization
374 | else:
375 | average_bandwidth_utilization[link_type][block2_index,block1_index] = (average_bandwidth_utilization[link_type][block2_index,block1_index]*global_adjacency_matrix[link_type][block2_index,block1_index] + link_average_bandwidth_utilization*ios_to_add)/(global_adjacency_matrix[link_type][block2_index,block1_index] + ios_to_add)
376 | global_adjacency_matrix[link_type][block2_index,block1_index] += ios_to_add
377 |
378 | return global_adjacency_matrix, average_bandwidth_utilization, block_names
379 |
380 | # Define a function to construct the root chip and all subchips from a definition file.
381 | def chip_from_dict(etree, io_list, layer_list, wafer_process_list, assembly_process_list, test_process_list, global_adjacency_matrix, average_bandwidth_utilization, block_names):
382 | chip = d.Chip(filename = None, etree = etree, parent_chip = None, wafer_process_list = wafer_process_list, assembly_process_list = assembly_process_list, test_process_list = test_process_list, layers = layer_list, ios = io_list, adjacency_matrix_definitions = global_adjacency_matrix, average_bandwidth_utilization=average_bandwidth_utilization, block_names = block_names, static = False)
383 | return chip
384 |
--------------------------------------------------------------------------------
/run_all_sweeps.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Filename: run_all_sweeps.sh
19 | # Author: Alexander Graening
20 | # Affiliation: University of California, Los Angeles
21 | # Email: agraening@ucla.edu
22 | # ====================================================================================
23 |
24 |
25 | # Sweep script for CATCH: a Cost Analysis Tool for Co-optimization of chiplet-based Heterogeneous systems"
26 | # Simply run with sh run_all_sweeps.sh to generate all plots in the paper.
27 |
28 | # For sweeps, use python search_and_replace.py
29 | # Also, clean up temp files to avoid workspace bloat.
30 |
31 | echo
32 | echo "Running all sweeps"
33 |
34 | echo
35 | python generate_grid_test_files.py 2 UCIe_advanced True False 32 100 0.0
36 | python generate_grid_test_files.py 4 UCIe_advanced True False 32 100 0.0
37 | python generate_grid_test_files.py 9 UCIe_advanced True False 32 100 0.0
38 | python generate_grid_test_files.py 16 UCIe_advanced True False 32 100 0.0
39 | python generate_grid_test_files.py 25 UCIe_advanced True False 32 100 0.0
40 | python generate_grid_test_files.py 36 UCIe_advanced True False 32 100 0.0
41 | python generate_grid_test_files.py 49 UCIe_advanced True False 32 100 0.0
42 | python generate_grid_test_files.py 64 UCIe_advanced True False 32 100 0.0
43 |
44 | echo
45 | echo "Sweeping size"
46 | sh sweep_chiplet_size.sh > sweep_chiplet_size_results.txt
47 | cat sweep_chiplet_size_results.txt
48 | python generate_plot.py sweep_chiplet_size_results.txt 0 center line sweep_chiplet_size_results.png
49 | rm sweep_chiplet_size_results.txt
50 |
51 | echo
52 | echo "Sweeping defect density"
53 | sh sweep_defect_density.sh > sweep_defect_density_results.txt
54 | cat sweep_defect_density_results.txt
55 | python generate_plot.py sweep_defect_density_results.txt 0 center line sweep_defect_density_results.png
56 | rm sweep_defect_density_results.txt
57 |
58 | echo
59 | echo "Sweeping assembly process"
60 | sh sweep_assembly_process.sh > sweep_assembly_process_results.txt
61 | cat sweep_assembly_process_results.txt
62 | python generate_plot.py sweep_assembly_process_results.txt 0 center line sweep_assembly_process_results.png
63 | rm sweep_assembly_process_results.txt
64 |
65 | echo
66 | echo "Sweeping NRE"
67 | sh sweep_nre.sh > sweep_nre_results.txt
68 | cat sweep_nre_results.txt
69 | python generate_plot.py sweep_nre_results.txt 0 center line sweep_nre_results.png
70 | rm sweep_nre_results.txt
71 |
72 | echo "Cleaning up"
73 | rm chiplet_2_400_def.xml
74 | rm chiplet_2_400_netlist.xml
75 | rm chiplet_4_200_def.xml
76 | rm chiplet_4_200_netlist.xml
77 | rm chiplet_9_88_def.xml
78 | rm chiplet_9_88_netlist.xml
79 | rm chiplet_16_50_def.xml
80 | rm chiplet_16_50_netlist.xml
81 | rm chiplet_25_32_def.xml
82 | rm chiplet_25_32_netlist.xml
83 | rm chiplet_36_22_def.xml
84 | rm chiplet_36_22_netlist.xml
85 | rm chiplet_49_16_def.xml
86 | rm chiplet_49_16_netlist.xml
87 | rm chiplet_64_12_def.xml
88 | rm chiplet_64_12_netlist.xml
89 |
90 | # To see the impact of sweeping design quantity to see the impact on NRE for
91 | # a case where a single design unit is repeated homogeneously across the design
92 | # we adjust the design costs as below.
93 | #
94 | # Note that the design cost here increases for smaller dies to account for the
95 | # increasing quantities since different dies are not marked as the same.
96 | # Instead, quantities are inflated.
97 | echo
98 | python generate_grid_test_files.py 2 UCIe_advanced True False 32 100 0.02
99 | python generate_grid_test_files.py 4 UCIe_advanced True False 32 100 0.04
100 | python generate_grid_test_files.py 9 UCIe_advanced True False 32 100 0.09
101 | python generate_grid_test_files.py 16 UCIe_advanced True False 32 100 0.16
102 | python generate_grid_test_files.py 25 UCIe_advanced True False 32 100 0.25
103 | python generate_grid_test_files.py 36 UCIe_advanced True False 32 100 0.36
104 | python generate_grid_test_files.py 49 UCIe_advanced True False 32 100 0.49
105 | python generate_grid_test_files.py 64 UCIe_advanced True False 32 100 0.64
106 |
107 | echo
108 | echo "Sweeping NRE"
109 | sh sweep_nre.sh > sweep_nre_design_results.txt
110 | cat sweep_nre_design_results.txt
111 | python generate_plot.py sweep_nre_design_results.txt 0 center line sweep_nre_design_results.png
112 | rm sweep_nre_design_results.txt
113 |
114 | echo "Cleaning up"
115 | rm chiplet_2_400_def.xml
116 | rm chiplet_2_400_netlist.xml
117 | rm chiplet_4_200_def.xml
118 | rm chiplet_4_200_netlist.xml
119 | rm chiplet_9_88_def.xml
120 | rm chiplet_9_88_netlist.xml
121 | rm chiplet_16_50_def.xml
122 | rm chiplet_16_50_netlist.xml
123 | rm chiplet_25_32_def.xml
124 | rm chiplet_25_32_netlist.xml
125 | rm chiplet_36_22_def.xml
126 | rm chiplet_36_22_netlist.xml
127 | rm chiplet_49_16_def.xml
128 | rm chiplet_49_16_netlist.xml
129 | rm chiplet_64_12_def.xml
130 | rm chiplet_64_12_netlist.xml
131 |
132 | # NRE_1_custom uses a custom test case
133 |
134 | echo
135 | echo "Sweeping NRE with a single custom die in a group of 4"
136 | sh sweep_nre_1_custom.sh > sweep_nre_1_custom_results.txt
137 | cat sweep_nre_1_custom_results.txt
138 | python generate_plot.py sweep_nre_1_custom_results.txt 0 center bar sweep_nre_1_custom_results.png
139 | rm sweep_nre_1_custom_results.txt
140 |
141 | echo
142 | python generate_grid_test_files.py 16 UCIe_standard True True 10000 100 0.0
143 |
144 | echo
145 | echo "Sweep IO reach"
146 | sh sweep_reach.sh > sweep_reach_results.txt
147 | cat sweep_reach_results.txt
148 | python generate_plot.py sweep_reach_results.txt 0 center bar sweep_reach_results.png
149 | rm sweep_reach_results.txt
150 |
151 | echo "Cleaning up"
152 | rm chiplet_16_50_def.xml
153 | rm chiplet_16_50_netlist.xml
154 |
155 | echo
156 | python generate_grid_test_files.py 16 UCIe_standard True True 32 100 0.0
157 |
158 | echo
159 | echo "Sweeping different substrates"
160 | sh sweep_substrates.sh > sweep_substrates_results.txt
161 | cat sweep_substrates_results.txt
162 | python generate_plot.py sweep_substrates_results.txt 0 center bar sweep_substrates_results.png
163 | rm sweep_substrates_results.txt
164 |
165 | echo
166 | echo "Sweep test coverage"
167 | sh sweep_test_coverage.sh > sweep_test_coverage_results.txt
168 | cat sweep_test_coverage_results.txt
169 | python generate_plot.py sweep_test_coverage_results.txt 0 center bar sweep_test_coverage_results.png
170 | rm sweep_test_coverage_results.txt
171 |
172 | echo
173 | echo "Sweep test coverage immature process"
174 | sh sweep_test_coverage_immature.sh > sweep_test_coverage_immature_results.txt
175 | cat sweep_test_coverage_immature_results.txt
176 | python generate_plot.py sweep_test_coverage_immature_results.txt 0 center bar sweep_test_coverage_immature_results.png
177 | rm sweep_test_coverage_immature_results.txt
178 |
179 | echo "Cleaning up"
180 | rm chiplet_16_50_def.xml
181 | rm chiplet_16_50_netlist.xml
182 |
183 | # The following sweeps use the same basic testcase.
184 | echo
185 | python generate_grid_test_files_3d.py 16 UCIe_advanced True False 32 100 0.0
186 |
187 | echo
188 | echo "Sweep test coverage 3D"
189 | sh sweep_test_coverage.sh > sweep_test_coverage_results.txt
190 | cat sweep_test_coverage_results.txt
191 | python generate_plot.py sweep_test_coverage_results.txt 0 center bar sweep_test_coverage_3d_results.png
192 | rm sweep_test_coverage_results.txt
193 |
194 | echo
195 | echo "Sweep test coverage 3D immature process"
196 | sh sweep_test_coverage_immature.sh > sweep_test_coverage_immature_results.txt
197 | cat sweep_test_coverage_immature_results.txt
198 | python generate_plot.py sweep_test_coverage_immature_results.txt 0 center bar sweep_test_coverage_immature_3d_results.png
199 | rm sweep_test_coverage_immature_results.txt
200 |
201 | echo "Cleaning up"
202 | rm chiplet_16_50_def.xml
203 | rm chiplet_16_50_netlist.xml
204 |
--------------------------------------------------------------------------------
/search_and_replace.py:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # Read command line arguments
18 | import sys
19 |
20 | if len(sys.argv) != 5:
21 | print("Usage: python script.py input_file string_to_replace replacement_string output_file")
22 | sys.exit(1)
23 |
24 | input_file, string_to_replace, replacement_string, output_file = sys.argv[1:]
25 |
26 | # Read input file
27 | try:
28 | with open(input_file, 'r') as fin:
29 | content = fin.read()
30 | except FileNotFoundError:
31 | print(f"Input file '{input_file}' not found.")
32 | sys.exit(1)
33 |
34 | # Replace occurrences
35 | new_content = content.replace(string_to_replace, replacement_string)
36 |
37 | # Write to output file
38 | with open(output_file, 'w') as fout:
39 | fout.write(new_content)
40 |
41 | # print(f"Replaced '{string_to_replace}' with '{replacement_string}' in '{input_file}'. Result saved in '{output_file}'.")
42 |
43 |
--------------------------------------------------------------------------------
/sip.xml:
--------------------------------------------------------------------------------
1 |
128 |
129 |
155 |
181 |
207 |
208 |
209 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/sweep_assembly_process.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE_PRE="chiplet_"
24 | INPUT_FILE_POST="_def.xml"
25 | INPUT_NETLIST_PRE="chiplet_"
26 | INPUT_NETLIST_POST="_netlist.xml"
27 |
28 | #SERIES="organic_25_simultaneous_bonding organic_55_simultaneous_bonding organic_simultaneous_bonding silicon_individual_bonding silicon_45_individual_bonding"
29 | SERIES="silicon_individual_bonding silicon_simultaneous_bonding organic_simultaneous_bonding"
30 | SWEEP="2_400 4_200 9_88 16_50 25_32 36_22 49_16 64_12"
31 |
32 | # echo "Creating a temporary file temp_${INPUT_FILE}"
33 | echo "x-axis label: Count_Size(mm2)"
34 | echo "y-axis label: Cost ($)"
35 | echo "Sweep: ${SWEEP}"
36 | for series in $SERIES
37 | do
38 | echo "series: ${series}"
39 | for size in $SWEEP
40 | do
41 | INPUT_FILE="${INPUT_FILE_PRE}${size}${INPUT_FILE_POST}"
42 | INPUT_NETLIST="${INPUT_NETLIST_PRE}${size}${INPUT_NETLIST_POST}"
43 | # echo "Replacing ${ap} in ${INPUT_FILE}"
44 | python search_and_replace.py ${INPUT_FILE} silicon_individual_bonding ${series} temp_${INPUT_FILE}
45 |
46 | # echo "$ap"
47 | # If ap includes the word "silicon", then also replace "combined_interposer_organic" with "combined_interposer_silicon"
48 | if echo "$series" | grep -q "silicon"; then
49 | # echo "Replacing combined_interposer_organic with combined_interposer_silicon"
50 | python search_and_replace.py temp_${INPUT_FILE} combined_interposer_organic combined_interposer_silicon temp_${INPUT_FILE}
51 | python search_and_replace.py ${INPUT_NETLIST} UCIe_standard UCIe_advanced temp_${INPUT_NETLIST}
52 | elif echo "$series" | grep -q "organic"; then
53 | # echo "Replacing combined_interposer_silicon with combined_interposer_organic"
54 | python search_and_replace.py temp_${INPUT_FILE} combined_interposer_silicon combined_interposer_organic temp_${INPUT_FILE}
55 | python search_and_replace.py ${INPUT_NETLIST} UCIe_advanced UCIe_standard temp_${INPUT_NETLIST}
56 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
57 | else
58 | echo "Error: assembly process does not contain silicon or organic"
59 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
60 | fi
61 |
62 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml temp_${INPUT_NETLIST} temp_${INPUT_FILE}
63 | # Note that it is possible to replace multiple lines by running search and replace on the output file instead of regenerating from scratch.
64 | # python search_and_replace.py temp_${INPUT_FILE} temp_${INPUT_FILE}
65 | rm temp_${INPUT_FILE}
66 | rm temp_${INPUT_NETLIST}
67 | done
68 | done
69 |
--------------------------------------------------------------------------------
/sweep_chiplet_size.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE_PRE="chiplet_"
24 | INPUT_FILE_POST="_def.xml"
25 | INPUT_NETLIST_PRE="chiplet_"
26 | INPUT_NETLIST_POST="_netlist.xml"
27 |
28 | SWEEP="2_400 4_200 9_88 16_50 25_32 36_22 49_16 64_12"
29 | TECHNOLOGIES="3nm 5nm 7nm 10nm 12nm 40nm"
30 |
31 | echo "x-axis label: Count_Size(mm2)"
32 | echo "y-axis label: Cost ($)"
33 | echo "Sweep: ${SWEEP}"
34 | for tech in $TECHNOLOGIES
35 | do
36 | echo "series: ${tech}"
37 |
38 | for size in $SWEEP
39 | do
40 | INPUT_FILE="${INPUT_FILE_PRE}${size}${INPUT_FILE_POST}"
41 | INPUT_NETLIST="${INPUT_NETLIST_PRE}${size}${INPUT_NETLIST_POST}"
42 | python search_and_replace.py ${INPUT_FILE} combined_5nm combined_${tech} temp_${INPUT_FILE}
43 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml ${INPUT_NETLIST} temp_${INPUT_FILE}
44 | rm temp_${INPUT_FILE}
45 | done
46 | done
47 |
--------------------------------------------------------------------------------
/sweep_defect_density.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE_PRE="chiplet_"
24 | INPUT_FILE_POST="_def.xml"
25 | INPUT_NETLIST_PRE="chiplet_"
26 | INPUT_NETLIST_POST="_netlist.xml"
27 |
28 | SWEEP="2_400 4_200 9_88 16_50 25_32 36_22 49_16 64_12"
29 | DEFECT_DENSITY="0.001 0.005 0.01"
30 |
31 | echo "x-axis label: Count_Size(mm2)"
32 | echo "y-axis label: Cost ($)"
33 | echo "Sweep: ${SWEEP}"
34 | tech="3nm"
35 | for dd in $DEFECT_DENSITY
36 | do
37 | echo "series: ${dd}"
38 |
39 | for size in $SWEEP
40 | do
41 | INPUT_FILE="${INPUT_FILE_PRE}${size}${INPUT_FILE_POST}"
42 | INPUT_NETLIST="${INPUT_NETLIST_PRE}${size}${INPUT_NETLIST_POST}"
43 | python search_and_replace.py ${INPUT_FILE} combined_5nm combined_3nm_${dd} temp_${INPUT_FILE}
44 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml ${INPUT_NETLIST} temp_${INPUT_FILE}
45 | rm temp_${INPUT_FILE}
46 | done
47 | done
48 |
--------------------------------------------------------------------------------
/sweep_nre.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE_PRE="chiplet_"
24 | INPUT_FILE_POST="_def.xml"
25 | INPUT_NETLIST_PRE="chiplet_"
26 | INPUT_NETLIST_POST="_netlist.xml"
27 |
28 | SWEEP="2_400 4_200 9_88 16_50 25_32 36_22 49_16 64_12"
29 |
30 | QUANTITIES="10000 100000 1000000 10000000"
31 |
32 |
33 | echo "x-axis label: Count_Size(mm2)"
34 | echo "y-axis label: Cost ($)"
35 | echo "Sweep: ${SWEEP}"
36 | for q in $QUANTITIES
37 | do
38 | echo "series: ${q}"
39 |
40 | for size in $SWEEP
41 | do
42 | INPUT_FILE="${INPUT_FILE_PRE}${size}${INPUT_FILE_POST}"
43 | INPUT_NETLIST="${INPUT_NETLIST_PRE}${size}${INPUT_NETLIST_POST}"
44 | python search_and_replace.py ${INPUT_FILE} 10000000 $q temp_${INPUT_FILE}
45 | # Extract the part of size before a '_' and set it to a variable
46 | NUM_CHIPS=$(echo $size | cut -d'_' -f1)
47 | # Multiply NUM_CHIPS by 10000000 and set it to a variable
48 | QUANTITY_TO_REPLACE=$(($NUM_CHIPS * 10000000))
49 | NEW_QUANTITY=$(($NUM_CHIPS * $q))
50 | python search_and_replace.py temp_${INPUT_FILE} $QUANTITY_TO_REPLACE $NEW_QUANTITY temp_${INPUT_FILE}
51 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml ${INPUT_NETLIST} temp_${INPUT_FILE}
52 | rm temp_${INPUT_FILE}
53 | done
54 | done
55 |
--------------------------------------------------------------------------------
/sweep_nre_1_custom.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE="chiplet_nre_study_def.xml"
24 | INPUT_NETLIST="chiplet_nre_study_netlist.xml"
25 |
26 | QUANTITIES="10000 100000 1000000 10000000"
27 |
28 | echo "x-axis label: New Die Quantity"
29 | echo "y-axis label: Cost ($)"
30 | echo "Sweep: $QUANTITIES"
31 | for q in $QUANTITIES
32 | do
33 | python search_and_replace.py ${INPUT_FILE} INSERTSWEEPQUANTITY $q temp_${INPUT_FILE}
34 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml ${INPUT_NETLIST} temp_${INPUT_FILE}
35 | rm temp_${INPUT_FILE}
36 | done
37 |
--------------------------------------------------------------------------------
/sweep_reach.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE="chiplet_16_50_def.xml"
24 | INPUT_NETLIST_FILE="chiplet_16_50_netlist.xml"
25 | INPUT_IO_FILE="io_definitions.xml"
26 | INPUT_LAYER_FILE="layer_definitions.xml"
27 | INPUT_WAFER_FILE="wafer_process_definitions.xml"
28 | INPUT_ASSEMBLY_FILE="assembly_process_definitions.xml"
29 | INPUT_TEST_FILE="test_definitions.xml"
30 |
31 | IO_NAME="UCIe_standard"
32 | NEW_IO_NAME="2Gbs_100vCDM_"
33 | SWEEP="2mm 5mm 10mm 20mm"
34 |
35 | # echo "Creating a temporary file temp_${INPUT_FILE}"
36 | echo "x-axis label: Reach (mm)"
37 | echo "y-axis label: Cost ($)"
38 | echo "Sweep Reach for ${IO_NAME}: ${SWEEP}"
39 | for io in $SWEEP
40 | #organic_25_simultaneous_bonding organic_55_simultaneous_bonding organic_simultaneous_bonding silicon_individual_bonding silicon_45_individual_bonding
41 | do
42 | # echo "Replacing ${ap} in ${INPUT_FILE}"
43 | python search_and_replace.py ${INPUT_NETLIST_FILE} ${IO_NAME} ${NEW_IO_NAME}${io} temp_${INPUT_NETLIST_FILE}
44 |
45 | python load_and_test_design.py ${INPUT_IO_FILE} ${INPUT_LAYER_FILE} ${INPUT_WAFER_FILE} ${INPUT_ASSEMBLY_FILE} ${INPUT_TEST_FILE} temp_${INPUT_NETLIST_FILE} ${INPUT_FILE}
46 | # Note that it is possible to replace multiple lines by running search and replace on the output file instead of regenerating from scratch.
47 | # python search_and_replace.py temp_${INPUT_FILE} temp_${INPUT_FILE}
48 | done
49 | rm temp_${INPUT_NETLIST_FILE}
50 | # echo "Temp file removed."
51 |
--------------------------------------------------------------------------------
/sweep_substrates.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE="chiplet_16_50_def.xml"
24 | INPUT_NETLIST="chiplet_16_50_netlist.xml"
25 |
26 | SWEEP="organic silicon glass"
27 | # SWEEP="organic_simultaneous_bonding silicon_individual_bonding"
28 |
29 | # echo "Creating a temporary file temp_${INPUT_FILE}"
30 | echo "x-axis label: Substrate"
31 | echo "y-axis label: Cost ($)"
32 | echo "Sweep: ${SWEEP}"
33 | for ap in $SWEEP
34 | #organic_25_simultaneous_bonding organic_55_simultaneous_bonding organic_simultaneous_bonding silicon_individual_bonding silicon_45_individual_bonding
35 | do
36 | # echo "Replacing ${ap} in ${INPUT_FILE}"
37 | if echo "$ap" | grep -q "organic"; then
38 | # echo "Replacing silicon_individual_bonding with organic_simultaneous_bonding"
39 | python search_and_replace.py ${INPUT_FILE} silicon_individual_bonding organic_simultaneous_bonding temp_${INPUT_FILE}
40 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
41 | elif echo "$ap" | grep -q "silicon"; then
42 | # echo "Replacing silicon_individual_bonding with silicon_individual_bonding"
43 | python search_and_replace.py ${INPUT_FILE} silicon_individual_bonding silicon_individual_bonding temp_${INPUT_FILE}
44 | python search_and_replace.py temp_${INPUT_NETLIST} UCIe_standard UCIe_advanced temp_${INPUT_NETLIST}
45 | elif echo "$ap" | grep -q "glass"; then
46 | # echo "Replacing silicon_individual_bonding with silicon_individual_bonding"
47 | python search_and_replace.py ${INPUT_FILE} silicon_individual_bonding glass_individual_bonding temp_${INPUT_FILE}
48 | python search_and_replace.py temp_${INPUT_NETLIST} UCIe_standard UCIe_advanced temp_${INPUT_NETLIST}
49 | else
50 | echo "Error: ap does not contain silicon, organic, or glass"
51 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
52 | fi
53 |
54 | # echo "$ap"
55 | # If ap includes the word "silicon", then also replace "combined_interposer_silicon" with "combined_interposer_silicon"
56 | if echo "$ap" | grep -q "silicon"; then
57 | # echo "Replacing combined_interposer_silicon with combined_interposer_silicon"
58 | python search_and_replace.py temp_${INPUT_FILE} combined_interposer_silicon combined_interposer_silicon temp_${INPUT_FILE}
59 | python search_and_replace.py ${INPUT_NETLIST} UCIe_standard UCIe_advanced temp_${INPUT_NETLIST}
60 | elif echo "$ap" | grep -q "organic"; then
61 | # echo "Replacing combined_interposer_silicon with combined_interposer_organic"
62 | python search_and_replace.py temp_${INPUT_FILE} combined_interposer_silicon combined_interposer_organic temp_${INPUT_FILE}
63 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
64 | elif echo "$ap" | grep -q "glass"; then
65 | # echo "Replacing combined_interposer_silicon with combined_interposer_organic"
66 | python search_and_replace.py temp_${INPUT_FILE} combined_interposer_silicon combined_interposer_glass temp_${INPUT_FILE}
67 | python search_and_replace.py ${INPUT_NETLIST} UCIe_standard UCIe_advanced temp_${INPUT_NETLIST}
68 | else
69 | echo "Error: ap does not contain silicon, organic, or glass"
70 | cp ${INPUT_NETLIST} temp_${INPUT_NETLIST}
71 | fi
72 |
73 | python load_and_test_design.py io_definitions.xml layer_definitions.xml wafer_process_definitions.xml assembly_process_definitions.xml test_definitions.xml temp_${INPUT_NETLIST} temp_${INPUT_FILE}
74 | # Note that it is possible to replace multiple lines by running search and replace on the output file instead of regenerating from scratch.
75 | # python search_and_replace.py temp_${INPUT_FILE} temp_${INPUT_FILE}
76 | done
77 | rm temp_${INPUT_FILE}
78 | rm temp_${INPUT_NETLIST}
79 | # echo "Temp file removed."
80 |
--------------------------------------------------------------------------------
/sweep_test_coverage.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE="chiplet_16_50_def.xml"
24 | INPUT_NETLIST_FILE="chiplet_16_50_netlist.xml"
25 | INPUT_IO_FILE="io_definitions.xml"
26 | INPUT_LAYER_FILE="layer_definitions.xml"
27 | INPUT_WAFER_FILE="wafer_process_definitions.xml"
28 | INPUT_ASSEMBLY_FILE="assembly_process_definitions.xml"
29 | INPUT_TEST_FILE="test_definitions.xml"
30 |
31 | SWEEP="0.5 0.9 0.95 1.0"
32 |
33 | # echo "Creating a temporary file temp_${INPUT_FILE}"
34 | echo "x-axis label: Fault Coverage"
35 | echo "y-axis label: Cost ($)"
36 | echo "Sweep Test Coverage For: ${SWEEP}"
37 | echo "stack: non-scrap scrap"
38 | for coverage in $SWEEP
39 | #organic_25_simultaneous_bonding organic_55_simultaneous_bonding organic_simultaneous_bonding silicon_individual_bonding silicon_45_individual_bonding
40 | do
41 | # echo "Replacing ${ap} in ${INPUT_FILE}"
42 | # python search_and_replace.py ${INPUT_FILE} organic_simultaneous_bonding silicon_individual_bonding temp_${INPUT_FILE}
43 | # python search_and_replace.py temp_${INPUT_FILE} combined_interposer_organic combined_interposer_silicon temp_${INPUT_FILE}
44 | python search_and_replace.py ${INPUT_FILE} combined_5nm combined_3nm_0.005 temp_${INPUT_FILE}
45 | python search_and_replace.py temp_${INPUT_FILE} KGD_free_test free_test_${coverage} temp_${INPUT_FILE}
46 |
47 | python load_and_test_design_test_breakdown.py ${INPUT_IO_FILE} ${INPUT_LAYER_FILE} ${INPUT_WAFER_FILE} ${INPUT_ASSEMBLY_FILE} ${INPUT_TEST_FILE} ${INPUT_NETLIST_FILE} temp_${INPUT_FILE}
48 | # Note that it is possible to replace multiple lines by running search and replace on the output file instead of regenerating from scratch.
49 | # python search_and_replace.py temp_${INPUT_FILE} temp_${INPUT_FILE}
50 | done
51 | rm temp_${INPUT_FILE}
52 | # echo "Temp file removed."
53 |
--------------------------------------------------------------------------------
/sweep_test_coverage_immature.sh:
--------------------------------------------------------------------------------
1 | # =======================================================================
2 | # Copyright 2025 UCLA NanoCAD Laboratory
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | # =======================================================================
16 |
17 | # ====================================================================================
18 | # Author: Alexander Graening
19 | # Affiliation: University of California, Los Angeles
20 | # Email: agraening@ucla.edu
21 | # ====================================================================================
22 |
23 | INPUT_FILE="chiplet_16_50_def.xml"
24 | INPUT_NETLIST_FILE="chiplet_16_50_netlist.xml"
25 | INPUT_IO_FILE="io_definitions.xml"
26 | INPUT_LAYER_FILE="layer_definitions.xml"
27 | INPUT_WAFER_FILE="wafer_process_definitions.xml"
28 | INPUT_ASSEMBLY_FILE="assembly_process_definitions.xml"
29 | INPUT_TEST_FILE="test_definitions.xml"
30 |
31 | SWEEP="0.5 0.9 0.95 1.0"
32 |
33 | # echo "Creating a temporary file temp_${INPUT_FILE}"
34 | echo "x-axis label: Fault Coverage"
35 | echo "y-axis label: Cost ($)"
36 | echo "Sweep Test Coverage For: ${SWEEP}"
37 | echo "stack: non-scrap scrap"
38 | for coverage in $SWEEP
39 | #organic_25_simultaneous_bonding organic_55_simultaneous_bonding organic_simultaneous_bonding silicon_individual_bonding silicon_45_individual_bonding
40 | do
41 | # echo "Replacing ${ap} in ${INPUT_FILE}"
42 | # python search_and_replace.py ${INPUT_FILE} organic_simultaneous_bonding silicon_individual_bonding temp_${INPUT_FILE}
43 | # python search_and_replace.py temp_${INPUT_FILE} combined_interposer_organic combined_interposer_silicon temp_${INPUT_FILE}
44 | python search_and_replace.py ${INPUT_FILE} combined_5nm combined_3nm_0.01 temp_${INPUT_FILE}
45 | python search_and_replace.py temp_${INPUT_FILE} KGD_free_test free_test_${coverage} temp_${INPUT_FILE}
46 |
47 | python load_and_test_design_test_breakdown.py ${INPUT_IO_FILE} ${INPUT_LAYER_FILE} ${INPUT_WAFER_FILE} ${INPUT_ASSEMBLY_FILE} ${INPUT_TEST_FILE} ${INPUT_NETLIST_FILE} temp_${INPUT_FILE}
48 | # Note that it is possible to replace multiple lines by running search and replace on the output file instead of regenerating from scratch.
49 | # python search_and_replace.py temp_${INPUT_FILE} temp_${INPUT_FILE}
50 | done
51 | rm temp_${INPUT_FILE}
52 | # echo "Temp file removed."
53 |
--------------------------------------------------------------------------------
/test_definitions.xml:
--------------------------------------------------------------------------------
1 |
100 |
101 |
102 |
103 |
104 |
133 |
134 |
163 |
164 |
165 |
166 |
195 |
196 |
225 |
226 |
255 |
256 |
285 |
286 |
315 |
316 |
345 |
346 |
375 |
376 |
405 |
406 |
435 |
436 |
465 |
466 |
467 |
--------------------------------------------------------------------------------
/wafer_process_definitions.xml:
--------------------------------------------------------------------------------
1 |
73 |
74 |
81 |
82 |
86 |
87 |
88 |
103 |
104 |
119 |
120 |
121 |
--------------------------------------------------------------------------------