Initial Project U-Ray code.
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e046f6c --- /dev/null +++ b/.gitignore
@@ -0,0 +1 @@ +database/*
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6652bd4 --- /dev/null +++ b/AUTHORS
@@ -0,0 +1,13 @@ +# This is the list of Project U-Ray significant contributors. +# +# This does not necessarily list everyone who has contributed code, +# especially since many employees of one corporation may be contributing. +# To see the full list of contributors, see the revision history in +# source control. + +# Companies +Google LLC +Antmicro Sp. z o. o. + +# Individuals +tansell@google.com, me@mith.ro (Tim 'mithro' Ansell)
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
diff --git a/README.md b/README.md new file mode 100644 index 0000000..4337305 --- /dev/null +++ b/README.md
@@ -0,0 +1,22 @@ +Project U-Ray +============= + +Project U-Ray is an attempt at documenting the bitstream format for the +[Xilinx Ultrascale and Ultrascale+ parts](https://www.xilinx.com/products/technology/ultrascale.html) +including all parts from the following lines; + * Kintex Ultrascale + * Virtex Ultrascale + * Zynq UltraScale MPSoC + * Kintex UltraScale+ + * Virtex UltraScale+ + * Zynq UltraScale+ MPSoC + +It takes a lot of the learning from +[Project X-Ray](https://github.com/SymbiFlow/prjxray) and +[Project Trellis](https://github.com/SymbiFlow/prjtrellis). + +The initial targets parts and boards are; + * [Ultra96-V2 Zynq UltraScale+ ZU3EG Development Board (ULTRA96-V2-G)](https://www.avnet.com/shop/us/products/avnet-engineering-services/aes-ultra96-v2-g-3074457345638646173/) - Xilinx Zynq UltraScale+ MPSoC ZU3EG - $USD249 + * [Genesys ZU: Zynq Ultrascale+ MPSoC Development Board](https://store.digilentinc.com/genesys-zu-zynq-ultrascale-mpsoc-development-board/) - Xilinx Zynq UltraScale+ MPSoC ZU3EG - $USD1,149 + +
diff --git a/spec/bram18.py b/spec/bram18.py new file mode 100644 index 0000000..bdb537b --- /dev/null +++ b/spec/bram18.py
@@ -0,0 +1,83 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [13:0] ra, wa, input [3:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 600 +print(" wire [35:0] int_d[0:%d-1];" % N) +print(" assign rdata = sel[0] ? int_d[sel[10:1]][35:18] : int_d[sel[10:1]][17:0];") +for i in range(N): + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.45, 0.1]) + write_width_a = 0 if (write_width_b == 36 or read_width_a == 36) else np.random.choice([0, 1, 2, 4, 9, 18]) + read_width_b = 0 if (read_width_a == 36 or write_width_b == 36) else np.random.choice([0, 1, 2, 4, 9, 18], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.55]) + + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" RAMB18E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .DOB_REG(%d),"% (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A(18'd%d)," % np.random.randint(2**18)) + print(" .INIT_B(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_A(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_B(18'd%d)" % np.random.randint(2**18)) + print(" ) ram%d (" % i) + print(" .DINADIN(wdata[15:0]),") + print(" .DINPADINP(wdata[17:16]),") + print(" .DOUTADOUT(int_d[%d][15:0])," % i) + print(" .DOUTPADOUTP(int_d[%d][17:16])," % i) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("2'b00" if write_width_a == 0 else "we[1:0]")) + print(" .DINBDIN(wdata[15:0]),") + print(" .DINPBDINP(wdata[17:16]),") + print(" .DOUTBDOUT(int_d[%d][33:18])," % i) + print(" .DOUTPBDOUTP(int_d[%d][35:34])," % i) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("2'b00" if write_width_b == 0 else ("we[3:0]" if write_width_b == 36 else "we[3:2]"))) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/bram18_2.py b/spec/bram18_2.py new file mode 100644 index 0000000..4e7763e --- /dev/null +++ b/spec/bram18_2.py
@@ -0,0 +1,89 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [13:0] ra, wa, input [3:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 200 +print(" wire [35:0] int_d[0:%d-1];" % N) +print(" assign rdata = sel[0] ? int_d[sel[10:1]][35:18] : int_d[sel[10:1]][17:0];") +for i in range(N): + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.45, 0.1]) + write_width_a = 0 if (write_width_b == 36 or read_width_a == 36) else np.random.choice([0, 1, 2, 4, 9, 18]) + read_width_b = 0 if (read_width_a == 36 or write_width_b == 36) else np.random.choice([0, 1, 2, 4, 9, 18], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.55]) + + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" (* keep, dont_touch *) RAMB18E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .DOB_REG(%d),"% (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A(18'd%d)," % np.random.randint(2**18)) + print(" .INIT_B(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_A(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_B(18'd%d)" % np.random.randint(2**18)) + print(" ) ram%d (" % i) + print(" .DINADIN(wdata[15:0]),") + print(" .DINPADINP(wdata[17:16]),") + douta_len = np.random.randint(0, 19) + if douta_len > 0: + print(" .DOUTADOUT(int_d[%d][%d:0])," % (i, min(15, douta_len - 1))) + if douta_len > 16: + print(" .DOUTPADOUTP(int_d[%d][%d:16])," % (i, douta_len - 1)) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("2'b00" if write_width_a == 0 else "we[1:0]")) + print(" .DINBDIN(wdata[15:0]),") + print(" .DINPBDINP(wdata[17:16]),") + doutb_len = np.random.randint(0, 19) + if doutb_len > 0: + print(" .DOUTBDOUT(int_d[%d][%d:18])," % (i, min(33, 17 + doutb_len))) + if doutb_len > 16: + print(" .DOUTPBDOUTP(int_d[%d][%d:34])," % (i, 17 + doutb_len)) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("2'b00" if write_width_b == 0 else ("we[3:0]" if write_width_b == 36 else "we[3:2]"))) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/bram18_3.py b/spec/bram18_3.py new file mode 100644 index 0000000..8c26653 --- /dev/null +++ b/spec/bram18_3.py
@@ -0,0 +1,89 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [13:0] ra, wa, input [3:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 500 +print(" wire [35:0] int_d[0:%d-1];" % N) +print(" assign rdata = sel[0] ? int_d[sel[10:1]][35:18] : int_d[sel[10:1]][17:0];") +for i in range(N): + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.45, 0.1]) + write_width_a = 0 if (write_width_b == 36 or read_width_a == 36) else np.random.choice([0, 1, 2, 4, 9, 18]) + read_width_b = 0 if (read_width_a == 36 or write_width_b == 36) else np.random.choice([0, 1, 2, 4, 9, 18], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.55]) + + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" (* keep, dont_touch *) RAMB18E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .DOB_REG(%d),"% (0 if (write_width_b == 36 or read_width_a == 36) else np.random.randint(2))) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A(18'd%d)," % np.random.randint(2**18)) + print(" .INIT_B(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_A(18'd%d)," % np.random.randint(2**18)) + print(" .SRVAL_B(18'd%d)" % np.random.randint(2**18)) + print(" ) ram%d (" % i) + print(" .DINADIN(wdata[15:0]),") + print(" .DINPADINP(wdata[17:16]),") + douta_bit = np.random.randint(-1, 19) + if douta_bit >= 0 and douta_bit < 16: + print(" .DOUTADOUT({int_d[%d][0]%s})," % (i, ", {%d{1'bx}}" % douta_bit if douta_bit > 0 else "")) + if douta_bit >= 16: + print(" .DOUTPADOUTP({int_d[%d][16]%s})," % (i, ", {%d{1'bx}}" % (douta_bit - 16) if douta_bit > 16 else "")) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("2'b00" if write_width_a == 0 else "we[1:0]")) + print(" .DINBDIN(wdata[15:0]),") + print(" .DINPBDINP(wdata[17:16]),") + doutb_bit = np.random.randint(-1, 19) + if doutb_bit >= 0 and doutb_bit < 16: + print(" .DOUTBDOUT({int_d[%d][18]%s})," % (i, ", {%d{1'bx}}" % doutb_bit if doutb_bit > 0 else "")) + if doutb_bit >= 16: + print(" .DOUTPBDOUTP({int_d[%d][34]%s})," % (i, ", {%d{1'bx}}" % (doutb_bit - 16) if doutb_bit > 16 else "")) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("2'b00" if write_width_b == 0 else ("we[3:0]" if write_width_b == 36 else "we[3:2]"))) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/bram36.py b/spec/bram36.py new file mode 100644 index 0000000..6e6ed40 --- /dev/null +++ b/spec/bram36.py
@@ -0,0 +1,85 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [14:0] ra, wa, input [7:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 300 +print(" wire [71:0] int_d[0:%d-1];" % N) +print(" assign rdata = int_d[sel[10:2]][18 * sel[1:0] +: 18];") +for i in range(N): + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.45]) + write_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.45]) + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36]) + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" RAMB36E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % np.random.randint(2)) + print(" .DOB_REG(%d),"% np.random.randint(2)) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .EN_ECC_PIPE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_READ(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_WRITE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .INIT_B({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_B({18'd%d, 18'd%d})" % (np.random.randint(2**18), np.random.randint(2**18))) + print(" ) ram%d (" % i) + print(" .DINADIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPADINP({wdata[17:16], wdata[17:16]}),") + print(" .DOUTADOUT({int_d[%d][31:0]})," % i) + print(" .DOUTPADOUTP({int_d[%d][35:32]})," % i) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("4'b00" if write_width_a == 0 else "we[3:0]")) + print(" .DINBDIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPBDINP({wdata[17:16], wdata[17:16]}),") + print(" .DOUTBDOUT(int_d[%d][67:36])," % i) + print(" .DOUTPBDOUTP(int_d[%d][71:68])," % i) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("4'b00" if write_width_b == 0 else "we[7:4]")) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/bram36_sdp.py b/spec/bram36_sdp.py new file mode 100644 index 0000000..def70ef --- /dev/null +++ b/spec/bram36_sdp.py
@@ -0,0 +1,85 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [14:0] ra, wa, input [7:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 300 +print(" wire [71:0] int_d[0:%d-1];" % N) +print(" assign rdata = int_d[sel[10:2]][18 * sel[1:0] +: 18];") +for i in range(N): + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36, 72]) + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36, 72], p=[0.05, 0.1, 0.1, 0.1, 0.05, 0.05, 0.45, 0.1]) + write_width_a = 0 if (write_width_b == 72 or read_width_a == 72) else np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_b = 0 if (write_width_b == 72 or read_width_a == 72) else np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.45]) + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" RAMB36E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % (0 if (write_width_b == 72 or read_width_a == 72) else np.random.randint(2))) + print(" .DOB_REG(%d)," % (0 if (write_width_b == 72 or read_width_a == 72) else np.random.randint(2))) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .EN_ECC_PIPE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_READ(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_WRITE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .INIT_B({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_B({18'd%d, 18'd%d})" % (np.random.randint(2**18), np.random.randint(2**18))) + print(" ) ram%d (" % i) + print(" .DINADIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPADINP({wdata[17:16], wdata[17:16]}),") + print(" .DOUTADOUT({int_d[%d][31:0]})," % i) + print(" .DOUTPADOUTP({int_d[%d][35:32]})," % i) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("4'b00" if write_width_a == 0 else "we[3:0]")) + print(" .DINBDIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPBDINP({wdata[17:16], wdata[17:16]}),") + print(" .DOUTBDOUT(int_d[%d][67:36])," % i) + print(" .DOUTPBDOUTP(int_d[%d][71:68])," % i) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("4'b00" if write_width_b == 0 else ("we[7:0]" if write_width_b == 72 else "we[7:4]"))) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/bram36_sdp_2.py b/spec/bram36_sdp_2.py new file mode 100644 index 0000000..b415899 --- /dev/null +++ b/spec/bram36_sdp_2.py
@@ -0,0 +1,91 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input clk, clkb, rst, ena, enb, cea, ceb, input [14:0] ra, wa, input [7:0] we, input [17:0] wdata, input [10:0] sel, output [35:0] rdata);") +N = 300 +print(" wire [71:0] int_d[0:%d-1];" % N) +print(" assign rdata = int_d[sel[10:2]][18 * sel[1:0] +: 18];") +for i in range(N): + write_width_b = np.random.choice([0, 1, 2, 4, 9, 18, 36, 72]) + read_width_a = np.random.choice([0, 1, 2, 4, 9, 18, 36, 72], p=[0.05, 0.1, 0.1, 0.1, 0.05, 0.05, 0.45, 0.1]) + write_width_a = 0 if (write_width_b == 72 or read_width_a == 72) else np.random.choice([0, 1, 2, 4, 9, 18, 36]) + read_width_b = 0 if (write_width_b == 72 or read_width_a == 72) else np.random.choice([0, 1, 2, 4, 9, 18, 36], p=[0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.45]) + cd = np.random.choice(["INDEPENDENT", "COMMON"]) + + print(" RAMB36E2 #(") + print(" .CLOCK_DOMAINS(\"%s\")," % cd) + print(" .READ_WIDTH_A(%d)," % read_width_a) + print(" .READ_WIDTH_B(%d)," % read_width_b) + print(" .WRITE_WIDTH_A(%d)," % write_width_a) + print(" .WRITE_WIDTH_B(%d)," % write_width_b) + print(" .WRITE_MODE_A(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .WRITE_MODE_B(\"%s\")," % np.random.choice(["NO_CHANGE", "READ_FIRST", "WRITE_FIRST"])) + print(" .CASCADE_ORDER_A(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .CASCADE_ORDER_B(\"%s\")," % np.random.choice(["NONE", "FIRST", "MIDDLE", "LAST"])) + print(" .DOA_REG(%d)," % (0 if (write_width_b == 72 or read_width_a == 72) else np.random.randint(2))) + print(" .DOB_REG(%d)," % (0 if (write_width_b == 72 or read_width_a == 72) else np.random.randint(2))) + print(" .ENADDRENA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .ENADDRENB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .EN_ECC_PIPE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_READ(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .EN_ECC_WRITE(\"%s\")," % np.random.choice(["FALSE", "TRUE"], p=[0.9, 0.1])) + print(" .RDADDRCHANGEA(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RDADDRCHANGEB(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .SLEEP_ASYNC(\"%s\")," % np.random.choice(["FALSE", "TRUE"])) + print(" .RSTREG_PRIORITY_A(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + print(" .RSTREG_PRIORITY_B(\"%s\")," % np.random.choice(["RSTREG", "REGCE"])) + for pin in ("CLKARDCLK", "CLKBWRCLK", "ENARDEN", "ENBWREN", "RSTRAMARSTRAM", "RSTRAMB", "RSTREGARSTREG", "RSTREGB"): + print(" .IS_%s_INVERTED(%d)," % (pin, np.random.randint(2))) + print(" .INIT_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .INIT_B({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_A({18'd%d, 18'd%d})," % (np.random.randint(2**18), np.random.randint(2**18))) + print(" .SRVAL_B({18'd%d, 18'd%d})" % (np.random.randint(2**18), np.random.randint(2**18))) + print(" ) ram%d (" % i) + print(" .DINADIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPADINP({wdata[17:16], wdata[17:16]}),") + douta_bit = np.random.randint(-1, 37) + if douta_bit >= 0 and douta_bit < 32: + print(" .DOUTADOUT({int_d[%d][0]%s})," % (i, ", {%d{1'bx}}" % douta_bit if douta_bit > 0 else "")) + if douta_bit >= 32: + print(" .DOUTPADOUTP({int_d[%d][32]%s})," % (i, ", {%d{1'bx}}" % (douta_bit - 32) if douta_bit > 32 else "")) + print(" .ADDRARDADDR(ra),") + print(" .CLKARDCLK(clk),") + print(" .ADDRENA(ena),") + print(" .ENARDEN(ena),") + print(" .REGCEAREGCE(cea),") + print(" .RSTRAMARSTRAM(rst),") + print(" .RSTREGARSTREG(rst),") + print(" .WEA(%s)," % ("4'b00" if write_width_a == 0 else "we[3:0]")) + print(" .DINBDIN({wdata[15:0], wdata[15:0]}),") + print(" .DINPBDINP({wdata[17:16], wdata[17:16]}),") + doutb_bit = np.random.randint(-1, 37) + if doutb_bit >= 0 and doutb_bit < 32: + print(" .DOUTBDOUT({int_d[%d][36]%s})," % (i, ", {%d{1'bx}}" % doutb_bit if doutb_bit > 0 else "")) + if doutb_bit >= 32: + print(" .DOUTPBDOUTP({int_d[%d][68]%s})," % (i, ", {%d{1'bx}}" % (doutb_bit - 32) if doutb_bit > 32 else "")) + print(" .ADDRBWRADDR(wa),") + print(" .CLKBWRCLK(%s)," % ("clkb" if cd == "INDEPENDENT" else "clk")) + print(" .ENBWREN(enb),") + print(" .ADDRENB(enb),") + print(" .REGCEB(ceb),") + print(" .RSTRAMB(rst),") + print(" .RSTREGB(rst),") + print(" .WEBWE(%s)" % ("4'b00" if write_width_b == 0 else ("we[7:0]" if write_width_b == 72 else "we[7:4]"))) + print(" );") + print() +print("endmodule") \ No newline at end of file
diff --git a/spec/dsp.py b/spec/dsp.py new file mode 100644 index 0000000..d550444 --- /dev/null +++ b/spec/dsp.py
@@ -0,0 +1,152 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +X = 8 +N = 120 + +root = sys.argv[2] + +def random_vector(size): + return "{%s}" % ", ".join(["d[%d]" % np.random.randint(40) for k in range(size)]) + +for x in range(X): + + + with open(root + "/dsp1/dsp%d.v" % x, "w") as f: + print("module top(input [7:0] clk, cen, rst, input [39:0] d, input [7:0] sel, output [63:0] q);", file=f) + print(" wire [8:0] r = {1'b0, rst}, e = {1'b1, cen};", file=f) + print(" wire [63:0] int_q[0:%d];" % (N-1), file=f) + print(" assign q = int_q[sel];", file=f) + for i in range(N): + use_preadd = np.random.choice([False, True]) + bmultsel = (np.random.choice(["AD", "B"]) if use_preadd else "B") + amultsel = (np.random.choice(["AD", "A"]) if use_preadd and bmultsel == "AD" else ("AD" if use_preadd else "A")) + use_patdet = np.random.choice([False, True]) + print(" DSP48E2 #(", file=f) + print(" .ADREG(%d)," % (np.random.randint(2) if use_preadd else 0), file=f) + print(" .ALUMODEREG(%d)," % np.random.randint(2), file=f) + print(" .AMULTSEL(\"%s\")," % amultsel, file=f) + print(" .AREG(%d)," % np.random.randint(3), file=f) + print(" .AUTORESET_PATDET(\"%s\")," % np.random.choice(["NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"]), file=f) + print(" .AUTORESET_PRIORITY(\"%s\")," % np.random.choice(["RESET", "CEP"]), file=f) + print(" .A_INPUT(\"DIRECT\"),", file=f) + print(" .BMULTSEL(\"%s\")," % bmultsel,file=f) + print(" .BREG(%d)," % np.random.randint(3), file=f) + print(" .B_INPUT(\"DIRECT\"),", file=f) + print(" .CARRYINREG(%d)," % np.random.randint(2), file=f) + print(" .CARRYINSELREG(%d)," % np.random.randint(2), file=f) + print(" .CREG(%d)," % np.random.randint(2), file=f) + print(" .DREG(%d)," % np.random.randint(2), file=f) + print(" .INMODEREG(%d)," % np.random.randint(2), file=f) + print(" .IS_ALUMODE_INVERTED(%d)," % np.random.randint(16), file=f) + print(" .IS_CARRYIN_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_CLK_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_INMODE_INVERTED(%d)," % np.random.randint(32), file=f) + print(" .IS_OPMODE_INVERTED(%d)," % np.random.randint(512), file=f) + print(" .IS_RSTALLCARRYIN_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTALUMODE_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTA_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTB_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTCTRL_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTC_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTD_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTINMODE_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTM_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTP_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .MASK({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .MREG(%d)," % np.random.randint(2), file=f) + print(" .OPMODEREG(%d)," % np.random.randint(2), file=f) + print(" .PATTERN({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .PREADDINSEL(\"%s\")," % np.random.choice(["A", "B"]), file=f) + print(" .PREG(%d)," % np.random.randint(2), file=f) + print(" .RND({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .SEL_MASK(\"%s\")," % np.random.choice(["MASK", "C", "ROUNDING_MODE1", "ROUNDING_MODE2"]), file=f) + print(" .SEL_PATTERN(\"%s\")," % np.random.choice(["PATTERN", "C"]), file=f) + print(" .USE_PATTERN_DETECT(\"%s\")," % ("PATDET" if use_patdet else "NO_PATDET"), file=f) + print(" .USE_SIMD(\"%s\")," % np.random.choice(["ONE48", "TWO24", "FOUR12"]), file=f) + print(" .USE_WIDEXOR(\"%s\")," % np.random.choice(["TRUE", "FALSE"]), file=f) + print(" .XORSIMD(\"%s\")" % np.random.choice(["XOR12", "XOR24_48_96"]), file=f) + print(" ) dsp_%d (" % i, file=f) + print(" .A(%s)," % random_vector(30), file=f) + print(" .ALUMODE(%s)," % random_vector(4), file=f) + print(" .B(%s)," % random_vector(18), file=f) + print(" .C(%s)," % random_vector(48), file=f) + print(" .CARRYIN(%s)," % random_vector(1), file=f) + print(" .CEA1(e[%d])," % np.random.randint(9), file=f) + print(" .CEA2(e[%d])," % np.random.randint(9), file=f) + print(" .CEAD(e[%d])," % np.random.randint(9), file=f) + print(" .CEALUMODE(e[%d])," % np.random.randint(9), file=f) + print(" .CEC(e[%d])," % np.random.randint(9), file=f) + print(" .CECARRYIN(e[%d])," % np.random.randint(9), file=f) + print(" .CECTRL(e[%d])," % np.random.randint(9), file=f) + print(" .CED(e[%d])," % np.random.randint(9), file=f) + print(" .CEINMODE(e[%d])," % np.random.randint(9), file=f) + print(" .CEM(e[%d])," % np.random.randint(9), file=f) + print(" .CEP(e[%d])," % np.random.randint(9), file=f) + print(" .CLK(clk[%d])," % np.random.randint(8), file=f) + print(" .D(%s)," % random_vector(27), file=f) + print(" .INMODE(%s)," % random_vector(5), file=f) + print(" .OPMODE(%s)," % random_vector(9), file=f) + print(" .RSTA(r[%d])," % np.random.randint(9), file=f) + print(" .RSTALLCARRYIN(r[%d])," % np.random.randint(9), file=f) + print(" .RSTALUMODE(r[%d])," % np.random.randint(9), file=f) + print(" .RSTB(r[%d])," % np.random.randint(9), file=f) + print(" .RSTC(r[%d])," % np.random.randint(9), file=f) + print(" .RSTCTRL(r[%d])," % np.random.randint(9), file=f) + print(" .RSTD(r[%d])," % np.random.randint(9), file=f) + print(" .RSTINMODE(r[%d])," % np.random.randint(9), file=f) + print(" .RSTM(r[%d])," % np.random.randint(9), file=f) + print(" .RSTP(r[%d])," % np.random.randint(9), file=f) + print(" .P(int_q[%d][47:0])," % i, file=f) + print(" .CARRYOUT(int_q[%d][51:48])," % i, file=f) + print(" .XOROUT(int_q[%d][59:52])," % i, file=f) + print(" .PATTERNDETECT(int_q[%d][60])," % i, file=f) + print(" .PATTERNBDETECT(int_q[%d][61])," % i, file=f) + print(" .OVERFLOW(int_q[%d][62])," % i, file=f) + print(" .UNDERFLOW(int_q[%d][63])" % i, file=f) + print(" );", file=f) + print("", file=f) + print("endmodule", file=f) + with open(root + "/dsp1/dsp%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/dsp1/dsp%d.v" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks AVAL-*]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks REQP-*]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_bram/dsp%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_bram/dsp%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_bram/dsp%d.bit" % (root, x), file=f) +with open(root + "/dsp1/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source dsp%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_bram/dsp%d.bit %s/frames.txt > %s/specimen_bram/dsp%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_bram/dsp%d.dump > %s/specimen_bram/dsp%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_bram/dsp%d.dump" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp%d.bit" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/dsp_2.py b/spec/dsp_2.py new file mode 100644 index 0000000..2392de2 --- /dev/null +++ b/spec/dsp_2.py
@@ -0,0 +1,160 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +X = 8 +N = 200 + +root = sys.argv[2] + +def random_vector(size): + return "{%s}" % ", ".join(["d[%d]" % np.random.randint(12) for k in range(size)]) + +for x in range(X): + + + with open(root + "/dsp2/dsp_b%d.v" % x, "w") as f: + print("module top(input [7:0] clk, cen, rst, input [11:0] d, input [7:0] sel, output [63:0] q);", file=f) + print(" wire [8:0] r = {1'b0, rst}, e = {1'b1, cen};", file=f) + print(" wire [63:0] int_q[0:%d];" % (N-1), file=f) + print(" assign q = int_q[sel];", file=f) + for i in range(N): + use_preadd = np.random.choice([False, True]) + bmultsel = (np.random.choice(["AD", "B"]) if use_preadd else "B") + amultsel = (np.random.choice(["AD", "A"]) if use_preadd and bmultsel == "AD" else ("AD" if use_preadd else "A")) + use_patdet = np.random.choice([False, True]) + print(" (* keep, dont_touch *) DSP48E2 #(", file=f) + print(" .ADREG(%d)," % (np.random.randint(2) if use_preadd else 0), file=f) + print(" .ALUMODEREG(%d)," % np.random.randint(2), file=f) + print(" .AMULTSEL(\"%s\")," % amultsel, file=f) + print(" .AREG(%d)," % np.random.randint(3), file=f) + print(" .AUTORESET_PATDET(\"%s\")," % np.random.choice(["NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"]), file=f) + print(" .AUTORESET_PRIORITY(\"%s\")," % np.random.choice(["RESET", "CEP"]), file=f) + print(" .A_INPUT(\"DIRECT\"),", file=f) + print(" .BMULTSEL(\"%s\")," % bmultsel,file=f) + print(" .BREG(%d)," % np.random.randint(3), file=f) + print(" .B_INPUT(\"DIRECT\"),", file=f) + print(" .CARRYINREG(%d)," % np.random.randint(2), file=f) + print(" .CARRYINSELREG(%d)," % np.random.randint(2), file=f) + print(" .CREG(%d)," % np.random.randint(2), file=f) + print(" .DREG(%d)," % np.random.randint(2), file=f) + print(" .INMODEREG(%d)," % np.random.randint(2), file=f) + print(" .IS_ALUMODE_INVERTED(%d)," % np.random.randint(16), file=f) + print(" .IS_CARRYIN_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_CLK_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_INMODE_INVERTED(%d)," % np.random.randint(32), file=f) + print(" .IS_OPMODE_INVERTED(%d)," % np.random.randint(512), file=f) + print(" .IS_RSTALLCARRYIN_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTALUMODE_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTA_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTB_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTCTRL_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTC_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTD_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTINMODE_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTM_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .IS_RSTP_INVERTED(%d)," % np.random.randint(2), file=f) + print(" .MASK({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .MREG(%d)," % np.random.randint(2), file=f) + print(" .OPMODEREG(%d)," % np.random.randint(2), file=f) + print(" .PATTERN({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .PREADDINSEL(\"%s\")," % np.random.choice(["A", "B"]), file=f) + print(" .PREG(%d)," % np.random.randint(2), file=f) + print(" .RND({24'd%d, 24'd%d})," % (np.random.randint(2**24), np.random.randint(2**24)), file=f) + print(" .SEL_MASK(\"%s\")," % np.random.choice(["MASK", "C", "ROUNDING_MODE1", "ROUNDING_MODE2"]), file=f) + print(" .SEL_PATTERN(\"%s\")," % np.random.choice(["PATTERN", "C"]), file=f) + print(" .USE_PATTERN_DETECT(\"%s\")," % ("PATDET" if use_patdet else "NO_PATDET"), file=f) + print(" .USE_SIMD(\"%s\")," % np.random.choice(["ONE48", "TWO24", "FOUR12"]), file=f) + print(" .USE_WIDEXOR(\"%s\")," % np.random.choice(["TRUE", "FALSE"]), file=f) + print(" .XORSIMD(\"%s\")" % np.random.choice(["XOR12", "XOR24_48_96"]), file=f) + print(" ) dsp_%d (" % i, file=f) + print(" .A(%s)," % random_vector(30), file=f) + print(" .ALUMODE(%s)," % random_vector(4), file=f) + print(" .B(%s)," % random_vector(18), file=f) + #print(" .C(%s)," % random_vector(48), file=f) + print(" .CARRYIN(%s)," % random_vector(1), file=f) + print(" .CEA1(e[%d])," % np.random.randint(9), file=f) + print(" .CEA2(e[%d])," % np.random.randint(9), file=f) + print(" .CEAD(e[%d])," % np.random.randint(9), file=f) + print(" .CEALUMODE(e[%d])," % np.random.randint(9), file=f) + print(" .CEC(e[%d])," % np.random.randint(9), file=f) + print(" .CECARRYIN(e[%d])," % np.random.randint(9), file=f) + print(" .CECTRL(e[%d])," % np.random.randint(9), file=f) + print(" .CED(e[%d])," % np.random.randint(9), file=f) + print(" .CEINMODE(e[%d])," % np.random.randint(9), file=f) + print(" .CEM(e[%d])," % np.random.randint(9), file=f) + print(" .CEP(e[%d])," % np.random.randint(9), file=f) + #print(" .D(%s)," % random_vector(27), file=f) + print(" .INMODE(%s)," % random_vector(5), file=f) + print(" .OPMODE(%s)," % random_vector(9), file=f) + print(" .RSTA(r[%d])," % np.random.randint(9), file=f) + print(" .RSTALLCARRYIN(r[%d])," % np.random.randint(9), file=f) + print(" .RSTALUMODE(r[%d])," % np.random.randint(9), file=f) + print(" .RSTB(r[%d])," % np.random.randint(9), file=f) + print(" .RSTC(r[%d])," % np.random.randint(9), file=f) + print(" .RSTCTRL(r[%d])," % np.random.randint(9), file=f) + print(" .RSTD(r[%d])," % np.random.randint(9), file=f) + print(" .RSTINMODE(r[%d])," % np.random.randint(9), file=f) + print(" .RSTM(r[%d])," % np.random.randint(9), file=f) + print(" .RSTP(r[%d])," % np.random.randint(9), file=f) + o_bit = np.random.randint(-1, 64) + if o_bit >= 0 and o_bit < 48: + print(" .P({int_q[%d][0]%s})," % (i, ", {%d{1'bx}}" % o_bit if o_bit > 0 else ""), file=f) + if o_bit >= 48 and o_bit < 52: + print(" .CARRYOUT({int_q[%d][48]%s})," % (i, ", {%d{1'bx}}" % (o_bit-48) if o_bit > 48 else ""), file=f) + if o_bit >= 52 and o_bit < 60: + print(" .XOROUT({int_q[%d][52]%s})," % (i, ", {%d{1'bx}}" % (o_bit-52) if o_bit > 52 else ""), file=f) + if o_bit == 60: + print(" .PATTERNDETECT(int_q[%d][60])," % i, file=f) + if o_bit == 61: + print(" .PATTERNBDETECT(int_q[%d][61])," % i, file=f) + if o_bit == 62: + print(" .OVERFLOW(int_q[%d][62])," % i, file=f) + if o_bit == 63: + print(" .UNDERFLOW(int_q[%d][63])," % i, file=f) + print(" .CLK(clk[%d])" % np.random.randint(8), file=f) + print(" );", file=f) + print("", file=f) + print("endmodule", file=f) + with open(root + "/dsp2/dsp_b%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/dsp2/dsp_b%d.v" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks AVAL-*]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks REQP-*]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_bram/dsp_b%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_bram/dsp_b%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_bram/dsp_b%d.bit" % (root, x), file=f) +with open(root + "/dsp2/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source dsp_b%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_bram/dsp_b%d.bit %s/frames.txt > %s/specimen_bram/dsp_b%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_bram/dsp_b%d.dump > %s/specimen_bram/dsp_b%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_bram/dsp_b%d.dump" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp_b%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp_b%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp_b%d.bit" % (root, x), file=f) + print(" rm %s/specimen_bram/dsp_b%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/flipflops.py b/spec/flipflops.py new file mode 100644 index 0000000..f9ca1dd --- /dev/null +++ b/spec/flipflops.py
@@ -0,0 +1,64 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +print("module top(input [15:0] clk, rst, cen, input [6:0] d, output q);") +N = 10000 +print(" wire [%d:0] int_d;" % N) +print(" assign int_d[6:0] = d;") +print(" assign q = int_d[%d];" % N) + +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) +for i in range(6, N): + fftype, srsig = np.random.choice(["FDPE,PRE", "FDCE,CLR", "FDSE,S", "FDRE,R"]).split(",") + sl = slices.pop() + if np.random.ranf() < 0.5: + data = "int_d[%d]" % i + else: + lutsize = np.random.randint(2, 10) + if lutsize > 6: + lutsize = 6 + print (" wire lut_q_%d;" % i) + + print(" (* BEL=\"%s%dLUT\" *) (* LOC=\"%s\" *) LUT%d #(" % (np.random.choice(list("ABCDEFGH")), np.random.randint(6 if lutsize == 6 else 5, 7), sl, lutsize)) + print(" .INIT(%d'h%016x)" % (2 ** lutsize, np.random.randint(1, (2 ** ((2 ** lutsize) - 1) - 1)))) + print(" ) lut_%d (" % i) + for j in range(lutsize): + print(" .I%d(int_d[%d])," % (j, i - j)) + print(" .O(lut_q_%d)" % i) + print(" );") + data = "lut_q_%d" % i + + print(" (* BEL=\"%sFF%s\" *) (* LOC=\"%s\" *) %s #(" % (np.random.choice(list("ABCDEFGH")), np.random.choice(["", "2"]), sl, fftype)) + print(" .IS_C_INVERTED(%s)," % np.random.choice(["0", "1"])) + print(" .IS_%s_INVERTED(%s)," % (srsig, np.random.choice(["0", "1"]))) + print(" .INIT(%s)" % np.random.choice(["1'b0", "1'b1"])) + print(" ) ff_%d (" % i) + print(" .C(clk[%d])," % np.random.randint(0, 16)) + print(" .CE(cen[%d])," % np.random.randint(0, 16)) + print(" .%s(rst[%d])," % (srsig, np.random.randint(0, 16))) + print(" .D(%s)," % (data)) + print(" .Q(int_d[%d])" % (i + 1)) + print(" );") +print("endmodule")
diff --git a/spec/gclk.py b/spec/gclk.py new file mode 100644 index 0000000..e723fbe --- /dev/null +++ b/spec/gclk.py
@@ -0,0 +1,44 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if ("BUFGCE" in site) and "HDIO" not in site and "DIV" not in site: + bufgces.append((site.split(":")[0], sl[2])) + +np.random.shuffle(bufgces) + +print("module top(input i, output o);") +N = int(len(bufgces) * 0.08) +print(" wire [%d:0] r;" % N) +print(" assign r[0] = i;") +print(" assign o = r[%d];" % N) +for i in range(N): + bg, tile = bufgces[i] + print("(* LOC=\"%s\" *)" % bg) + if "BUFGCTRL" in bg: + print(" BUFGCTRL bufg_%d (.I0(r[%d]), .I1(r[%d]), .S0(1'b1), .S1(1'b0), .CE0(1'b1), .O(r[%d]));" % (i, i, i, i+1)) + elif "DIV" in bg: + print(" BUFGCE_DIV #(.BUFGCE_DIVIDE(3)) bufg_%d (.I(r[%d]), .CLR(0), .CE(1'b1), .O(r[%d]));" % (i, i, i + 1)) + else: + print(" BUFGCE bufg_%d (.I(r[%d]), .CE(1'b1), .O(r[%d]));" % (i, i, i+1)) +print("endmodule") \ No newline at end of file
diff --git a/spec/gclk_2.py b/spec/gclk_2.py new file mode 100644 index 0000000..0cfb058 --- /dev/null +++ b/spec/gclk_2.py
@@ -0,0 +1,142 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces_by_tile = {} +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: + if sl[2] not in bufgces_by_tile: + bufgces_by_tile[sl[2]] = [] + bufgces_by_tile[sl[2]].append(site.split(":")) + +X = 64 + +root = sys.argv[2] + +for x in range(X): + buffers = [] + + tiles = list(sorted(bufgces_by_tile.keys())) + np.random.shuffle(tiles) + + for tile in tiles: + shuffled_bufs = list(bufgces_by_tile[tile]) + np.random.shuffle(shuffled_bufs) + target_type = np.random.choice(["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"] if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"]) + tile_buffers = np.random.randint(8) + found_buffers = 0 + for buf, buftype in shuffled_bufs: + if found_buffers >= tile_buffers: + break + if buftype != target_type: + continue + buffers.append((buf, buftype)) + print("%s %s" % (tile, buf)) + found_buffers += 1 + print() + def random_inversion(pins): + return ", ".join([".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins]) + + def random_control(pins): + return ", ".join([".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins]) + + with open(root + "/clkroute3/gclk%d.v" % x, "w") as f: + print("module top(input i, input [9:0] aux, d, output o, q);", file=f) + N = len(buffers) + print(" wire [%d:0] r;" % N, file=f) + print(" assign r[0] = i;", file=f) + print(" assign o = r[%d];" % N, file=f) + print(" wire [%d:0] r2;" % (2*N), file=f) + print(" assign r2[0] = d;", file=f) + print(" assign q = r2[%d];" % (2*N), file=f) + for i in range(N): + bg, buftype = buffers[i] + print("(* LOC=\"%s\" *)" % bg, file=f) + if "BUFGCTRL" in buftype: + print(" BUFGCTRL #(", file=f) + print(" %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + print(" .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" % + (np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f) + print(" ) bufgctrl_%d (" % i, file=f) + print(" .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f) + print(" %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + print(" .O(r[%d])" % (i+1), file=f) + print(" );", file=f) + elif "DIV" in buftype: + print(" BUFGCE_DIV #(", file=f) + print(" .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), file=f) + print(" %s" % random_inversion(["I", "CE", "CLR"]), file=f) + print(" ) bufgce_div_%d (" % i, file=f) + print(" .I(r[%d])," % i, file=f) + print(" %s," % random_control(["CE", "CLR"]), file=f) + print(" .O(r[%d])" % (i+1), file=f) + print(" );", file=f) + else: + print(" BUFGCE #(", file=f) + print(" .CE_TYPE(\"%s\")," % np.random.choice(["SYNC", "ASYNC"]), file=f) + print(" %s" % random_inversion(["I", "CE"]), file=f) + print(" ) bufgce_div_%d (" % i, file=f) + print(" .I(r[%d])," % i, file=f) + print(" %s," % random_control(["CE"]), file=f) + print(" .O(r[%d])" % (i+1), file=f) + print(" );", file=f) + + if np.random.randint(2) == 1: + print("FDCE ff_%d(.C(r[%d]), .CE(1'b1), .CLR(1'b0), .D(r2[%d]), .Q(r2[%d]));" % (i, i, 2*i, 2*i+1), file=f) + else: + print("assign r2[%d] = r2[%d];" % (2*i+1, 2*i), file=f) + + if np.random.randint(2) == 1: + print("SRLC32E srl_%d(.CLK(r[%d]), .CE(1'b1), .A(aux[4:0]), .D(r2[%d]), .Q(r2[%d]));" % (i, i, 2*i+1, 2*i+2), file=f) + else: + print("assign r2[%d] = r2[%d];" % (2*i+2, 2*i+1), file=f) + + print("", file=f) + print("endmodule", file=f) + with open(root + "/clkroute3/gclk%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/clkroute3/gclk%d.v" % x)), file=f) + #print("read_xdc %s" % (root + ("/clkroute3/gclk%d.xdc" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_clk/gclk%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_clk/gclk%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_clk/gclk%d.bit" % (root, x), file=f) +with open(root + "/clkroute3/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source gclk%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_clk/gclk%d.bit %s/frames.txt > %s/specimen_clk/gclk%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/gclk%d.dump > %s/specimen_clk/gclk%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_clk/gclk%d.dump" % (root, x), file=f) + print(" rm %s/specimen_clk/gclk%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_clk/gclk%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_clk/gclk%d.bit" % (root, x), file=f) + print(" rm %s/specimen_clk/gclk%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/gclk_3.py b/spec/gclk_3.py new file mode 100644 index 0000000..dfc290a --- /dev/null +++ b/spec/gclk_3.py
@@ -0,0 +1,181 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces_by_tile = {} +tiles_by_xy = {} +rclk_int_l = [] +slices_by_tile = {} +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + tiles_by_xy[int(sl[0]), int(sl[1])] = sl[2] + if sl[2].startswith("RCLK_INT_L"): + rclk_int_l.append((int(sl[0]), int(sl[1]), sl[2])) + for site in sl[4:]: + if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: + if sl[2] not in bufgces_by_tile: + bufgces_by_tile[sl[2]] = [] + bufgces_by_tile[sl[2]].append(site.split(":")) + elif "SLICE_" in site: + slices_by_tile[int(sl[0]), int(sl[1])] = site.split(":")[0] + +halfcolumn_slices_by_row = {} +for x, y, rclk in rclk_int_l: + hc_up = [] + hc_down = [] + if y not in halfcolumn_slices_by_row: + halfcolumn_slices_by_row[y] = [] + for yplus in range(y+1, y+31): + if (x, yplus) not in tiles_by_xy: + continue + if not tiles_by_xy[x, yplus].startswith("INT_"): + break + slice_x = x + np.random.choice([+1, -1]) + if (slice_x, yplus) not in slices_by_tile: + continue + hc_up.append(slices_by_tile[slice_x, yplus]) + for yminus in range(y-1, y-31, -1): + if (x, yminus) not in tiles_by_xy: + continue + if not tiles_by_xy[x, yminus].startswith("INT_"): + break + slice_x = x + np.random.choice([+1, -1]) + if (slice_x, yminus) not in slices_by_tile: + continue + hc_down.append(slices_by_tile[slice_x, yminus]) + halfcolumn_slices_by_row[y].append(hc_up) + halfcolumn_slices_by_row[y].append(hc_down) + +X = 32 + +root = sys.argv[2] + +for x in range(X): + buffers = [] + + tiles = list(sorted(bufgces_by_tile.keys())) + np.random.shuffle(tiles) + + for tile in tiles: + shuffled_bufs = list(bufgces_by_tile[tile]) + np.random.shuffle(shuffled_bufs) + target_type = np.random.choice(["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"] if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"]) + tile_buffers = np.random.randint(6) + found_buffers = 0 + for buf, buftype in shuffled_bufs: + if found_buffers >= tile_buffers: + break + if buftype != target_type: + continue + buffers.append((buf, buftype)) + print("%s %s" % (tile, buf)) + found_buffers += 1 + + def random_inversion(pins): + return ", ".join([".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins]) + + def random_control(pins): + return ", ".join([".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins]) + + with open(root + "/clkroute4/gclkb_%d.v" % x, "w") as f: + print("module top(input [23:0] i, input [9:0] aux, input d, output o, q);", file=f) + N = 24 + print(" wire [71:0] r;", file=f) + # print(" assign r[0] = i;", file=f) + # print(" assign o = r[%d];" % N, file=f) + # for i in range(N): + # bg, buftype = buffers[i] + # #print("(* LOC=\"%s\" *)" % bg, file=f) + # if "BUFGCTRL" in buftype: + # print(" BUFGCTRL #(", file=f) + # print(" %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + # print(" .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" % + # (np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f) + # print(" ) bufgctrl_%d (" % i, file=f) + # print(" .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f) + # print(" %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + # print(" .O(r[%d])" % (i+1), file=f) + # print(" );", file=f) + print(" assign r[23:0] = i;", file=f) + for i in range(12): + print(" BUFGCE_DIV #(", file=f) + print(" .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), file=f) + print(" %s" % random_inversion(["I", "CE", "CLR"]), file=f) + print(" ) bufgce_div_%d (" % i, file=f) + print(" .I(i[%d])," % i, file=f) + print(" %s," % random_control(["CE", "CLR"]), file=f) + print(" .O(r[%d])" % (24+i), file=f) + print(" );", file=f) + for i in range(36): + print(" BUFGCE #(", file=f) + print(" .CE_TYPE(\"%s\")," % np.random.choice(["SYNC", "ASYNC"]), file=f) + print(" %s" % random_inversion(["I", "CE"]), file=f) + print(" ) bufgce_%d (" % i, file=f) + print(" .I(i[%d])," % np.random.randint(24), file=f) + print(" %s," % random_control(["CE"]), file=f) + print(" .O(r[%d])" % (i+36), file=f) + print(" );", file=f) + + R2=0 + NS=16 + ffs="" + for row, hcs in sorted(halfcolumn_slices_by_row.items()): + row_clks = np.random.randint(16, 25) + clks = [np.random.randint(72) for k in range(row_clks)] + halfs = [hcs[np.random.randint(len(hcs))] for k in range(NS)] + for h in halfs: + half_clks = np.random.randint(8, 17) + rclks = [np.random.choice(clks) for k in range(half_clks)] + for sl in h: + ffs += "(* LOC=\"%s\" *) FDCE ff_%d (.C(r[%d]), .CE(aux[%d]), .CLR(1'b0), .D(r2[%d]), .Q(r2[%d]));\n" % (sl, R2, np.random.choice(rclks), np.random.randint(10), R2, R2+1) + R2 += 1 + print(" wire [%d:0] r2;" % R2, file=f) + print(" assign r2[0] = d;", file=f) + print(" assign q = r2[%d];" % R2, file=f) + print(ffs, file=f) + print("endmodule", file=f) + with open(root + "/clkroute4/gclkb_%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/clkroute4/gclkb_%d.v" % x)), file=f) + #print("read_xdc %s" % (root + ("/clkroute4/gclkb_%d.xdc" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("# set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_clk/gclkb_%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_clk/gclkb_%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_clk/gclkb_%d.bit" % (root, x), file=f) +with open(root + "/clkroute4/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source gclkb_%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_clk/gclkb_%d.bit %s/frames.txt > %s/specimen_clk/gclkb_%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/gclkb_%d.dump > %s/specimen_clk/gclkb_%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_clk/gclkb_%d.dump" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkb_%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkb_%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkb_%d.bit" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkb_%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/gclk_4.py b/spec/gclk_4.py new file mode 100644 index 0000000..7f1f314 --- /dev/null +++ b/spec/gclk_4.py
@@ -0,0 +1,188 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces_by_tile = {} +tiles_by_xy = {} +rclk_int_l = [] +slices_by_tile = {} +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + tiles_by_xy[int(sl[0]), int(sl[1])] = sl[2] + if sl[2].startswith("RCLK_INT_L"): + rclk_int_l.append((int(sl[0]), int(sl[1]), sl[2])) + for site in sl[4:]: + if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: + if sl[2] not in bufgces_by_tile: + bufgces_by_tile[sl[2]] = [] + bufgces_by_tile[sl[2]].append(site.split(":")) + elif "SLICE_" in site: + slices_by_tile[int(sl[0]), int(sl[1])] = site.split(":")[0] + +halfcolumn_slices_by_row = {} +for x, y, rclk in rclk_int_l: + hc_up = [] + hc_down = [] + if y not in halfcolumn_slices_by_row: + halfcolumn_slices_by_row[y] = [] + for yplus in range(y+1, y+31): + if (x, yplus) not in tiles_by_xy: + continue + if not tiles_by_xy[x, yplus].startswith("INT_"): + break + slice_x = x + np.random.choice([+1, -1]) + if (slice_x, yplus) not in slices_by_tile: + continue + hc_up.append(slices_by_tile[slice_x, yplus]) + for yminus in range(y-1, y-31, -1): + if (x, yminus) not in tiles_by_xy: + continue + if not tiles_by_xy[x, yminus].startswith("INT_"): + break + slice_x = x + np.random.choice([+1, -1]) + if (slice_x, yminus) not in slices_by_tile: + continue + hc_down.append(slices_by_tile[slice_x, yminus]) + halfcolumn_slices_by_row[y].append(hc_up) + halfcolumn_slices_by_row[y].append(hc_down) + +X = 32 + +root = sys.argv[2] + +for x in range(X): + buffers = [] + + tiles = list(sorted(bufgces_by_tile.keys())) + np.random.shuffle(tiles) + + for tile in tiles: + shuffled_bufs = list(bufgces_by_tile[tile]) + np.random.shuffle(shuffled_bufs) + target_type = np.random.choice(["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"] if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"]) + tile_buffers = np.random.randint(6) + found_buffers = 0 + for buf, buftype in shuffled_bufs: + if found_buffers >= tile_buffers: + break + if buftype != target_type: + continue + buffers.append((buf, buftype)) + print("%s %s" % (tile, buf)) + found_buffers += 1 + + def random_inversion(pins): + return ", ".join([".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins]) + + def random_control(pins): + return ", ".join([".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins]) + + with open(root + "/clkroute5/gclkc_%d.v" % x, "w") as f: + print("module top(input [23:0] i, input [9:0] aux, input d, output o, q);", file=f) + N = 24 + print(" wire [71:0] r;", file=f) + # print(" assign r[0] = i;", file=f) + # print(" assign o = r[%d];" % N, file=f) + # for i in range(N): + # bg, buftype = buffers[i] + # #print("(* LOC=\"%s\" *)" % bg, file=f) + # if "BUFGCTRL" in buftype: + # print(" BUFGCTRL #(", file=f) + # print(" %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + # print(" .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" % + # (np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f) + # print(" ) bufgctrl_%d (" % i, file=f) + # print(" .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f) + # print(" %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) + # print(" .O(r[%d])" % (i+1), file=f) + # print(" );", file=f) + print(" assign r[23:0] = i;", file=f) + for i in range(12): + print(" BUFGCE_DIV #(", file=f) + print(" .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), file=f) + print(" %s" % random_inversion(["I", "CE", "CLR"]), file=f) + print(" ) bufgce_div_%d (" % i, file=f) + print(" .I(i[%d])," % i, file=f) + print(" %s," % random_control(["CE", "CLR"]), file=f) + print(" .O(r[%d])" % (24+i), file=f) + print(" );", file=f) + for i in range(12): + print(" BUFGCE #(", file=f) + print(" .CE_TYPE(\"%s\")," % np.random.choice(["SYNC", "ASYNC"]), file=f) + print(" %s" % random_inversion(["I", "CE"]), file=f) + print(" ) bufgce_%d (" % i, file=f) + print(" .I(i[%d])," % np.random.randint(24), file=f) + print(" %s," % random_control(["CE"]), file=f) + print(" .O(r[%d])" % (i+36), file=f) + print(" );", file=f) + + R2=0 + NS=64 + ffs="" + for row, hcs in sorted(halfcolumn_slices_by_row.items()): + row_clks = np.random.randint(20, 25) + clks = [np.random.randint(48) for k in range(row_clks)] + hi = [] + while len(hi) < NS: + next_i = np.random.randint(len(hcs)) + while next_i in hi: + next_i = np.random.randint(len(hcs)) + hi.append(next_i) + + halfs = [hcs[hi[k]] for k in range(NS)] + for h in halfs: + half_clks = np.random.randint(13, 17) + rclks = [np.random.choice(clks) for k in range(half_clks)] + for sl in h: + ffs += "(* LOC=\"%s\" *) FDCE ff_%d (.C(r[%d]), .CE(aux[%d]), .CLR(~aux[%d]), .D(r2[%d]), .Q(r2[%d]));\n" % (sl, R2, rclks[R2 % len(rclks)], np.random.randint(10), np.random.randint(10), R2, R2+1) + R2 += 1 + print(" wire [%d:0] r2;" % R2, file=f) + print(" assign r2[0] = d;", file=f) + print(" assign q = r2[%d];" % R2, file=f) + print(ffs, file=f) + print("endmodule", file=f) + with open(root + "/clkroute5/gclkc_%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/clkroute5/gclkc_%d.v" % x)), file=f) + #print("read_xdc %s" % (root + ("/clkroute5/gclkc_%d.xdc" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("# set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_clk/gclkc_%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_clk/gclkc_%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_clk/gclkc_%d.bit" % (root, x), file=f) +with open(root + "/clkroute5/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source gclkc_%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_clk/gclkc_%d.bit %s/frames.txt > %s/specimen_clk/gclkc_%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/gclkc_%d.dump > %s/specimen_clk/gclkc_%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_clk/gclkc_%d.dump" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkc_%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkc_%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkc_%d.bit" % (root, x), file=f) + print(" rm %s/specimen_clk/gclkc_%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/memory.py b/spec/memory.py new file mode 100644 index 0000000..a8e3b36 --- /dev/null +++ b/spec/memory.py
@@ -0,0 +1,115 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys +import math + +print("module top(input [15:0] clk, cen, input [8:0] wa, input [7:0] ra, input [7:0] d, input [11:0] sel, output [3:0] q);") +N = 4096 +print(" wire [3:0] int_d[0:%d-1];" % N) +print(" assign q = int_d[sel];") + +def connect(sig, dst, len): + if sig is None: + return [] + bit = 0 + conns = [] + for x in sig: + if type(x) is tuple: + name, width = x + conns.append(".%s(%s[%d +: %d])" % (name, dst, bit, width)) + bit += width + else: + conns.append(".%s(%s[%d])" % (x, dst, bit)) + bit += 1 + return conns + +for i in range(N): + ctype = np.random.choice(["SRL16E", "SRLC32E", "RAM32X1D", "RAM32X1S", "RAM64X1D", "RAM64X1S", "RAM128X1S", "RAM128X1D", "RAM256X1D", "RAM256X1S", "RAM512X1S"]) + clockport = None + ceport = None + wraddr = None + rdaddr = None + wdata = None + rdata = None + init_len = None + if ctype in ("SRL16E", "SRLC32E"): + clockport = "CLK" + ceport = "CE" + wdata = ["D"] + rdata = ["Q"] + if ctype == "SRLC32E": + rdata.append("Q31") + rdaddr = [("A", 5)] + init_len = 32 + else: + rdaddr = ["A0", "A1", "A2", "A3"] + init_len = 16 + elif ctype in ("RAM32X1D", "RAM32X1S"): + clockport = "WCLK" + ceport = "WE" + wdata = ["D"] + wraddr = ["A0", "A1", "A2", "A3", "A4"] + init_len = 32 + if ctype == "RAM32X1D": + rdaddr = ["DPRA0", "DPRA1", "DPRA2", "DPRA3", "DPRA4"] + rdata = ["SPO", "DPO"] + else: + rdata = ["O"] + elif ctype in ("RAM64X1D", "RAM64X1S"): + clockport = "WCLK" + ceport = "WE" + wdata = ["D"] + wraddr = ["A0", "A1", "A2", "A3", "A4", "A5"] + init_len = 64 + if ctype == "RAM64X1D": + rdaddr = ["DPRA0", "DPRA1", "DPRA2", "DPRA3", "DPRA4", "DPRA5"] + rdata = ["SPO", "DPO"] + else: + rdata = ["O"] + elif ctype in ("RAM128X1S", "RAM128X1D", "RAM256X1D", "RAM256X1S", "RAM512X1S"): + init_len = int(ctype[3:6]) + abits = math.log2(init_len) + clockport = "WCLK" + ceport = "WE" + wdata = ["D"] + if ctype == "RAM128X1S": + wraddr = ["A0", "A1", "A2", "A3", "A4", "A5", "A6"] + else: + wraddr = [("A", abits)] + if ctype[-1] == "D": + rdaddr = [("DPRA", abits)] + rdata = ["SPO", "DPO"] + else: + rdata = ["O"] + else: + assert False, ctype + conns = [] + if clockport is not None: + conns.append(".%s(clk[%d])" % (clockport, np.random.randint(0, 16))) + if ceport is not None: + conns.append(".%s(cen[%d])" % (ceport, np.random.randint(0, 16))) + conns += connect(wraddr, "wa", 9) + conns += connect(rdaddr, "ra", 8) + conns += connect(wdata, "d", 8) + conns += connect(rdata, "int_d[%d]" % i, 4) + print(" %s #(" % ctype) + if init_len is not None: + initdata = np.random.randint(2, size=init_len) + print(" .INIT(%d'b%s)" % (init_len, "".join([str(_) for _ in initdata]))) + print(" ) %s_%d (" % (ctype, i)) + print(" %s" % ",\n ".join(conns)) + print(" );") +print("endmodule")
diff --git a/spec/rclk_int.py b/spec/rclk_int.py new file mode 100644 index 0000000..816924c --- /dev/null +++ b/spec/rclk_int.py
@@ -0,0 +1,74 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +N = 5000 + +bufgces = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "BUFGCE" in site and "HDIO" not in site: + bufgces.append(site.split(":")[0]) + +print("module layer_1(input [31:0] clk, input [71:0] cen, input d, output q);") +print(" wire [%d:0] r;" % N) +print(" assign r[0] = d;") +print(" assign q = r[%d];" % N) +print() +for i in range(N): + print(" FDCE ff_%d (.C(clk[%d]), .CLR(1'b0), .CE(cen[%d]), .D(r[%d]), .Q(r[%d]));" % (i, (i * 32) // N, np.random.randint(72), i, i+1)) + print() +print("endmodule") + + +M = 16 +print("module top(input [15:0] clk, cen, input d, output q);") +print(" wire [511:0] clk_int;") +print(" wire [71:0] cen_int;") +print(" assign clk_int[15:0] = clk;") +print(" assign cen_int[15:0] = cen;") +print(" assign cen_int[71:64] = 8'hFF;") +for i in range(16, 512): + a = np.random.randint(16) + b = None + while b is None or b == a: + b = np.random.randint(16) + c = None + while c is None or c == a or c == b: + c = np.random.randint(16) + bg = None + if len(bufgces) > 0: + bg = bufgces.pop() + if bg is not None and np.random.randint(3) > 0: + if "DIV" in bg: + print(" BUFGCE_DIV #(.BUFGCE_DIVIDE(3)) bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CLR(0), .CE(1'b1), .O(clk_int[%d]));" % (i, a, b, c, i)) + else: + print(" BUFGCE bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CE(1'b1), .O(clk_int[%d]));" % (i, a, b, c, i)) + else: + print(" assign clk_int[%d] = clk[%d] ^ clk[%d] ^ clk[%d];" % (i, a, b, c)) + if i < 64: + print(" assign cen_int[%d] = cen[%d] ^ cen[%d];" % (i, a, b)) +print() +print(" wire [%d:0] r;" % M) +print(" assign r[0] = d;") +print(" assign q = r[%d];" % M) +for i in range(M): + print(" layer_1 submod_%d(.clk(clk_int[%d +: 32]), .cen(cen_int), .d(r[%d]), .q(r[%d]));" % (i, 32 * i, i, i+1)) +print("endmodule")
diff --git a/spec/rclk_int_2.py b/spec/rclk_int_2.py new file mode 100644 index 0000000..059d99b --- /dev/null +++ b/spec/rclk_int_2.py
@@ -0,0 +1,122 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces = [] +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "BUFGCE" in site and "HDIO" not in site: + bufgces.append(site.split(":")[0]) + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) +orig_bufgces = list(bufgces) +np.random.shuffle(bufgces) +np.random.shuffle(slices) +X = 30 + +root = sys.argv[2] + +bufg_prob = np.random.randint(15, 20) + +for x in range(X): + with open(root + "/clkroute/clkr%d.v" % x, "w") as f: + N = 256 + M = 16 + for m in range(M): + print("module layer_1_%d(input [31:0] clk, input [71:0] cen, input d, output q);" % m, file=f) + print(" wire [%d:0] r;" % N, file=f) + print(" assign r[0] = d;", file=f) + print(" assign q = r[%d];" % N, file=f) + print("", file=f) + for i in range(N): + if N == 0 and len(slices) > 0: + loc = slices.pop() + print("(* LOC=\"%s\" *)" % loc, file=f) + print(" FDCE ff_%d (.C(clk[%d]), .CLR(1'b0), .CE(cen[%d]), .D(r[%d]), .Q(r[%d]));" % (i, (i * 32) // N, np.random.randint(72), i, i+1), file=f) + print("endmodule", file=f) + + + print("module top(input [39:0] clk, cen, input d, output q);", file=f) + num_inputs = np.random.randint(8, 40) + print(" wire [511:0] clk_int;", file=f) + print(" wire [71:0] cen_int;", file=f) + print(" assign clk_int[%d:0] = clk;" % (num_inputs - 1), file=f) + print(" assign cen_int[%d:0] = cen;" % (num_inputs - 1), file=f) + print(" assign cen_int[71:64] = 8'hFF;", file=f) + + bufgces = list(orig_bufgces) + np.random.shuffle(bufgces) + + for i in range(num_inputs, 512): + a = np.random.randint(num_inputs) + b = None + while b is None or b == a: + b = np.random.randint(num_inputs) + c = None + while c is None or c == a or c == b: + c = np.random.randint(num_inputs) + bg = None + if len(bufgces) > 0: + bg = bufgces.pop() + if bg is not None and np.random.randint(20) >= bufg_prob or (bg is not None and "DIV" in bg and np.random.randint(19) >= bufg_prob): + if "DIV" in bg: + print(" BUFGCE_DIV #(.BUFGCE_DIVIDE(%d), .IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .IS_CLR_INVERTED(%d)) bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CLR(!cen[%d]), .CE(cen[%d]), .O(clk_int[%d]));" % + (np.random.randint(1, 9), np.random.randint(2), np.random.randint(2), np.random.randint(2), i, a, b, c, np.random.randint(40), np.random.randint(40), i), file=f) + else: + ctype = np.random.choice(["", "_1"]) + params = " #(.IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .CE_TYPE(\"%s\")) " % (np.random.randint(2), np.random.randint(2), np.random.choice(["SYNC", "ASYNC", "HARD_SYNC"])) if ctype == "" else "" + print(" BUFGCE%s %s bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CE(cen[%d]), .O(clk_int[%d]));" % + (ctype, params, i, a, b, c, np.random.randint(40), i), file=f) + else: + print(" assign clk_int[%d] = clk[%d] ^ clk[%d] ^ clk[%d];" % (i, a, b, c), file=f) + if i < 64: + print(" assign cen_int[%d] = cen[%d] ^ cen[%d];" % (i, a, b), file=f) + print("", file=f) + print(" wire [%d:0] r;" % M, file=f) + print(" assign r[0] = d;", file=f) + print(" assign q = r[%d];" % M, file=f) + for i in range(M): + print(" layer_1_%d submod_%d(.clk(clk_int[%d +: 32]), .cen(cen_int), .d(r[%d]), .q(r[%d]));" % (i, i, 32 * i, i, i+1), file=f) + print("endmodule", file=f) + with open(root + "/clkroute/clkr%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/clkroute/clkr%d.v" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_clk/clkr%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_clk/clkr%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_clk/clkr%d.bit" % (root, x), file=f) +with open(root + "/clkroute/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source clkr%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_clk/clkr%d.bit %s/frames.txt > %s/specimen_clk/clkr%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/clkr%d.dump > %s/specimen_clk/clkr%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_clk/clkr%d.dump" % (root, x), file=f) + print(" rm %s/specimen_clk/clkr%d.tbits" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/rclk_int_3.py b/spec/rclk_int_3.py new file mode 100644 index 0000000..c057ded --- /dev/null +++ b/spec/rclk_int_3.py
@@ -0,0 +1,140 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +bufgces = [] +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "BUFGCE" in site and "HDIO" not in site: + bufgces.append(site.split(":")[0]) + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) +orig_bufgces = list(bufgces) +np.random.shuffle(bufgces) +np.random.shuffle(slices) +X = 30 + +root = sys.argv[2] + +bufg_prob = np.random.randint(15, 20) + +for x in range(X): + with open(root + "/clkroute2/clkrb%d.v" % x, "w") as f: + N = 256 + M = np.random.randint(24) + for m in range(M): + print("module layer_1_%d(input [31:0] clk, input [71:0] cen, input d, output q);" % m, file=f) + print(" wire [%d:0] r;" % N, file=f) + print(" assign r[0] = d;", file=f) + print(" assign q = r[%d];" % N, file=f) + print("", file=f) + for i in range(N): + if N == 0 and len(slices) > 0: + loc = slices.pop() + print("(* LOC=\"%s\" *)" % loc, file=f) + if N != 0 and np.random.randint(16) == 0: + print(" wire srl_tmp_%d;" % i, file=f) + print(" SRLC32E srl_%d (.CLK(clk[%d]), .CE(cen[%d]), .A(5'b11111), .D(r[%d]), .Q(srl_tmp_%d));" % (i, (i * 32) // N, np.random.randint(72), i, i), file=f) + print(" FDCE ff_%d (.C(clk[%d]), .CLR(1'b0), .CE(cen[%d]), .D(srl_tmp_%d), .Q(r[%d]));" % (i, (i * 32) // N, np.random.randint(72), i, i+1), file=f) + else: + print(" FDCE ff_%d (.C(clk[%d]), .CLR(1'b0), .CE(cen[%d]), .D(r[%d]), .Q(r[%d]));" % (i, (i * 32) // N, np.random.randint(72), i, i+1), file=f) + print("endmodule", file=f) + + + print("module top(input [39:0] clk, cen, input d, output q);", file=f) + num_inputs = np.random.randint(8, 40) + print(" wire [511:0] clk_int;", file=f) + print(" wire [71:0] cen_int;", file=f) + print(" assign clk_int[%d:0] = clk;" % (num_inputs - 1), file=f) + print(" assign cen_int[%d:0] = cen;" % (num_inputs - 1), file=f) + print(" assign cen_int[71:64] = 8'hFF;", file=f) + + bufgces = list(orig_bufgces) + np.random.shuffle(bufgces) + + for i in range(num_inputs, 512): + a = np.random.randint(num_inputs) + b = None + while b is None or b == a: + b = np.random.randint(num_inputs) + c = None + while c is None or c == a or c == b: + c = np.random.randint(num_inputs) + bg = None + if len(bufgces) > 0: + bg = bufgces.pop() + if bg is not None and np.random.randint(20) >= bufg_prob or (bg is not None and "DIV" in bg and np.random.randint(19) >= bufg_prob): + if "DIV" in bg: + print(" BUFGCE_DIV #(.BUFGCE_DIVIDE(%d), .IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .IS_CLR_INVERTED(%d)) bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CLR(!cen[%d]), .CE(cen[%d]), .O(clk_int[%d]));" % + (np.random.randint(1, 9), np.random.randint(2), np.random.randint(2), np.random.randint(2), i, a, b, c, np.random.randint(40), np.random.randint(40), i), file=f) + else: + ctype = np.random.choice(["", "_1"]) + params = " #(.IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .CE_TYPE(\"%s\")) " % (np.random.randint(2), np.random.randint(2), np.random.choice(["SYNC", "ASYNC"])) if ctype == "" else "" + print(" BUFGCE%s %s bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CE(cen[%d]), .O(clk_int[%d]));" % + (ctype, params, i, a, b, c, np.random.randint(40), i), file=f) + else: + print(" assign clk_int[%d] = clk[%d] ^ clk[%d] ^ clk[%d];" % (i, a, b, c), file=f) + if i < 64: + print(" assign cen_int[%d] = cen[%d] ^ cen[%d];" % (i, a, b), file=f) + print("", file=f) + print(" wire [%d:0] r;" % M, file=f) + print(" assign r[0] = d;", file=f) + print(" assign q = r[%d];" % M, file=f) + for i in range(M): + print(" layer_1_%d submod_%d(.clk(clk_int[%d +: 32]), .cen(cen_int), .d(r[%d]), .q(r[%d]));" % (i, i, 32 * i, i, i+1), file=f) + print("endmodule", file=f) + ccio = ["G23", "F23", "G21", "F22", "F11", "H11", "G10", "H9", "G15", "F17", "E15", "D15", "AH11", "AH12", "AJ9", "AJ10", "AG21", "AH22", "AJ21", "AJ20", "AF18", "AH18", "AJ16", "AJ17"] + np.random.shuffle(ccio) + with open(root + "/clkroute2/clkrb%d.xdc" % x, "w") as f: + for i in range(num_inputs): + if i >= len(ccio): + break + print("set_property PACKAGE_PIN %s [get_ports {clk[%d]}]" % (ccio[i], i), file=f) + print("set_property IOSTANDARD LVCMOS18 [get_ports {clk[%d]}]" % (i), file=f) + + with open(root + "/clkroute2/clkrb%d.tcl" % x, "w") as f: + print("add_files %s" % (root + ("/clkroute2/clkrb%d.v" % x)), file=f) + print("read_xdc %s" % (root + ("/clkroute2/clkrb%d.xdc" % x)), file=f) + print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) + print("opt_design", file=f) + print("place_design", file=f) + print("route_design", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) + print("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) + print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f) + print("write_checkpoint -force %s/specimen_clk/clkrb%d.dcp" % (root, x), file=f) + print("write_edif -force %s/specimen_clk/clkrb%d.edf" % (root, x), file=f) + print("write_bitstream -force %s/specimen_clk/clkrb%d.bit" % (root, x), file=f) +with open(root + "/clkroute2/run.sh", "w") as f: + print("#/usr/bin/env bash", file=f) + #print("set -ex", file=f) + for x in range(X): + print("vivado -mode batch -nolog -nojournal -source clkrb%d.tcl" % x, file=f) + print("if [ $? -eq 0 ]; then", file=f) + print(" ../../ultra/tools/dump_bitstream %s/specimen_clk/clkrb%d.bit %s/frames.txt > %s/specimen_clk/clkrb%d.dump" % (root, x, root, root, x), file=f) + print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/clkrb%d.dump > %s/specimen_clk/clkrb%d.tbits" % (root, root, x, root, x), file=f) + print("else", file=f) + print(" rm %s/specimen_clk/clkrb%d.dump" % (root, x), file=f) + print(" rm %s/specimen_clk/clkrb%d.tbits" % (root, x), file=f) + print(" rm %s/specimen_clk/clkrb%d.dcp" % (root, x), file=f) + print(" rm %s/specimen_clk/clkrb%d.bit" % (root, x), file=f) + print(" rm %s/specimen_clk/clkrb%d.features" % (root, x), file=f) + print("fi", file=f) \ No newline at end of file
diff --git a/spec/slice.v b/spec/slice.v new file mode 100644 index 0000000..ce33903 --- /dev/null +++ b/spec/slice.v
@@ -0,0 +1,218 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module ultra_slice_logic #( + parameter [1023:0] LOC = "", + parameter [63:0] ALUT_INIT = 64'h00C0FFEE, + parameter [63:0] BLUT_INIT = 64'h00C0FFEE, + parameter [63:0] CLUT_INIT = 64'h00C0FFEE, + parameter [63:0] DLUT_INIT = 64'h00C0FFEE, + parameter [63:0] ELUT_INIT = 64'h00C0FFEE, + parameter [63:0] FLUT_INIT = 64'h00C0FFEE, + parameter [63:0] GLUT_INIT = 64'h00C0FFEE, + parameter [63:0] HLUT_INIT = 64'h00C0FFEE, + + parameter [1023:0] AFF_TYPE = "NONE", + parameter [1023:0] AFF2_TYPE = "NONE", + parameter [1023:0] BFF_TYPE = "NONE", + parameter [1023:0] BFF2_TYPE = "NONE", + parameter [1023:0] CFF_TYPE = "NONE", + parameter [1023:0] CFF2_TYPE = "NONE", + parameter [1023:0] DFF_TYPE = "NONE", + parameter [1023:0] DFF2_TYPE = "NONE", + parameter [1023:0] EFF_TYPE = "NONE", + parameter [1023:0] EFF2_TYPE = "NONE", + parameter [1023:0] FFF_TYPE = "NONE", + parameter [1023:0] FFF2_TYPE = "NONE", + parameter [1023:0] GFF_TYPE = "NONE", + parameter [1023:0] GFF2_TYPE = "NONE", + parameter [1023:0] HFF_TYPE = "NONE", + parameter [1023:0] HFF2_TYPE = "NONE", + + parameter [15:0] FF_INIT = 16'h0000, + + parameter [1023:0] FFMUXA1 = "BYP", + parameter [1023:0] FFMUXA2 = "BYP", + parameter [1023:0] FFMUXB1 = "BYP", + parameter [1023:0] FFMUXB2 = "BYP", + parameter [1023:0] FFMUXC1 = "BYP", + parameter [1023:0] FFMUXC2 = "BYP", + parameter [1023:0] FFMUXD1 = "BYP", + parameter [1023:0] FFMUXD2 = "BYP", + parameter [1023:0] FFMUXE1 = "BYP", + parameter [1023:0] FFMUXE2 = "BYP", + parameter [1023:0] FFMUXF1 = "BYP", + parameter [1023:0] FFMUXF2 = "BYP", + parameter [1023:0] FFMUXG1 = "BYP", + parameter [1023:0] FFMUXG2 = "BYP", + parameter [1023:0] FFMUXH1 = "BYP", + parameter [1023:0] FFMUXH2 = "BYP", + + parameter [1023:0] OUTMUXA = "D5", + parameter [1023:0] OUTMUXB = "D5", + parameter [1023:0] OUTMUXC = "D5", + parameter [1023:0] OUTMUXD = "D5", + parameter [1023:0] OUTMUXE = "D5", + parameter [1023:0] OUTMUXF = "D5", + parameter [1023:0] OUTMUXG = "D5", + parameter [1023:0] OUTMUXH = "D5", + + parameter [1:0] CLKINV = 2'b00, SRINV = 2'b00 + +) ( + input [7:0] A1, A2, A3, A4, A5, A6, I, X, + input [1:0] CLK, SR, + input [3:0] CE, + output [7:0] O, Q, Q2, MUX +); + wire [7:0] out5; + (* BEL="A5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(ALUT_INIT[31:0])) a5lut (.I0(A1[0]), .I1(A2[0]), .I2(A3[0]), .I3(A4[0]), .I4(A5[0]), .O(out5[0])); + (* BEL="A6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(ALUT_INIT[63:32])) a6lut (.I0(A1[0]), .I1(A2[0]), .I2(A3[0]), .I3(A4[0]), .I4(A5[0]), .O(O[0])); + (* BEL="B5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(BLUT_INIT[31:0])) b5lut (.I0(A1[1]), .I1(A2[1]), .I2(A3[1]), .I3(A4[1]), .I4(A5[1]), .O(out5[1])); + (* BEL="B6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(BLUT_INIT[63:32])) b6lut (.I0(A1[1]), .I1(A2[1]), .I2(A3[1]), .I3(A4[1]), .I4(A5[1]), .O(O[1])); + (* BEL="C5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(CLUT_INIT[31:0])) c5lut (.I0(A1[2]), .I1(A2[2]), .I2(A3[2]), .I3(A4[2]), .I4(A5[2]), .O(out5[2])); + (* BEL="C6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(CLUT_INIT[63:32])) c6lut (.I0(A1[2]), .I1(A2[2]), .I2(A3[2]), .I3(A4[2]), .I4(A5[2]), .O(O[2])); + (* BEL="D5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(DLUT_INIT[31:0])) d5lut (.I0(A1[3]), .I1(A2[3]), .I2(A3[3]), .I3(A4[3]), .I4(A5[3]), .O(out5[3])); + (* BEL="D6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(DLUT_INIT[63:32])) d6lut (.I0(A1[3]), .I1(A2[3]), .I2(A3[3]), .I3(A4[3]), .I4(A5[3]), .O(O[3])); + + (* BEL="E5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(ELUT_INIT[31:0])) e5lut (.I0(A1[4]), .I1(A2[4]), .I2(A3[4]), .I3(A4[4]), .I4(A5[4]), .O(out5[4])); + (* BEL="E6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(ELUT_INIT[63:32])) e6lut (.I0(A1[4]), .I1(A2[4]), .I2(A3[4]), .I3(A4[4]), .I4(A5[4]), .O(O[4])); + (* BEL="F5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(FLUT_INIT[31:0])) f5lut (.I0(A1[5]), .I1(A2[5]), .I2(A3[5]), .I3(A4[5]), .I4(A5[5]), .O(out5[5])); + (* BEL="F6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(FLUT_INIT[63:32])) f6lut (.I0(A1[5]), .I1(A2[5]), .I2(A3[5]), .I3(A4[5]), .I4(A5[5]), .O(O[5])); + (* BEL="G5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(GLUT_INIT[31:0])) g5lut (.I0(A1[6]), .I1(A2[6]), .I2(A3[6]), .I3(A4[6]), .I4(A5[6]), .O(out5[6])); + (* BEL="G6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(GLUT_INIT[63:32])) g6lut (.I0(A1[6]), .I1(A2[6]), .I2(A3[6]), .I3(A4[6]), .I4(A5[6]), .O(O[6])); + (* BEL="H5LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(HLUT_INIT[31:0])) h5lut (.I0(A1[7]), .I1(A2[7]), .I2(A3[7]), .I3(A4[7]), .I4(A5[7]), .O(out5[7])); + (* BEL="H6LUT", LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(HLUT_INIT[63:32])) h6lut (.I0(A1[7]), .I1(A2[7]), .I2(A3[7]), .I3(A4[7]), .I4(A5[7]), .O(O[7])); + + wire [7:0] f7f8; + assign f7f8[0] = 1'b0; + (* BEL="F7MUX_AB", LOC=LOC, keep, dont_touch *) MUXF7 f7muxab_i (.I0(O[1]), .I1(O[0]), .S(X[0]), .O(f7f8[1])); + (* BEL="F7MUX_CD", LOC=LOC, keep, dont_touch *) MUXF7 f7muxcd_i (.I0(O[3]), .I1(O[2]), .S(X[2]), .O(f7f8[3])); + (* BEL="F7MUX_EF", LOC=LOC, keep, dont_touch *) MUXF7 f7muxef_i (.I0(O[5]), .I1(O[4]), .S(X[4]), .O(f7f8[5])); + (* BEL="F7MUX_GH", LOC=LOC, keep, dont_touch *) MUXF7 f7muxgh_i (.I0(O[7]), .I1(O[6]), .S(X[6]), .O(f7f8[7])); + + (* BEL="F8MUX_BOT", LOC=LOC, keep, dont_touch *) MUXF8 f8muxabcd_i (.I0(f7f8[3]), .I1(f7f8[1]), .S(X[1]), .O(f7f8[2])); + (* BEL="F8MUX_TOP", LOC=LOC, keep, dont_touch *) MUXF8 f8muxefgh_i (.I0(f7f8[7]), .I1(f7f8[5]), .S(X[5]), .O(f7f8[6])); + + (* BEL="F9MUX", LOC=LOC, keep, dont_touch *) MUXF9 f9_i (.I0(f7f8[6]), .I1(f7f8[2]), .S(X[3]), .O(f7f8[4])); + + wire [15:0] ffin; + ultra_slice_logic_ffmux #(.SEL(FFMUXA1)) ffmuxa1_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .BYP(X[0]), .OUT(ffin[0])); + ultra_slice_logic_ffmux #(.SEL(FFMUXA2)) ffmuxa2_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .BYP(I[0]), .OUT(ffin[1])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB1)) ffmuxb1_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .BYP(X[1]), .OUT(ffin[2])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB2)) ffmuxb2_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .BYP(I[1]), .OUT(ffin[3])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC1)) ffmuxc1_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .BYP(X[2]), .OUT(ffin[4])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC2)) ffmuxc2_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .BYP(I[2]), .OUT(ffin[5])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD1)) ffmuxd1_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .BYP(X[3]), .OUT(ffin[6])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD2)) ffmuxd2_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .BYP(I[3]), .OUT(ffin[7])); + + ultra_slice_logic_ffmux #(.SEL(FFMUXE1)) ffmuxe1_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .BYP(X[4]), .OUT(ffin[8])); + ultra_slice_logic_ffmux #(.SEL(FFMUXE2)) ffmuxe2_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .BYP(I[4]), .OUT(ffin[9])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF1)) ffmuxf1_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .BYP(X[5]), .OUT(ffin[10])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF2)) ffmuxf2_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .BYP(I[5]), .OUT(ffin[11])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG1)) ffmuxg1_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .BYP(X[6]), .OUT(ffin[12])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG2)) ffmuxg2_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .BYP(I[6]), .OUT(ffin[13])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH1)) ffmuxh1_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .BYP(X[7]), .OUT(ffin[14])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH2)) ffmuxh2_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .BYP(I[7]), .OUT(ffin[15])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF"), .TYPE(AFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[0])) aff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[0]), .Q(Q[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF2"), .TYPE(AFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[1])) aff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[1]), .Q(Q2[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF"), .TYPE(BFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[2])) bff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[2]), .Q(Q[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF2"), .TYPE(BFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[3])) bff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[3]), .Q(Q2[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF"), .TYPE(CFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[4])) cff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[4]), .Q(Q[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF2"), .TYPE(CFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[5])) cff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[5]), .Q(Q2[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF"), .TYPE(DFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[6])) dff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[6]), .Q(Q[3])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF2"), .TYPE(DFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[7])) dff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[7]), .Q(Q2[3])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF"), .TYPE(EFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[8])) eff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[8]), .Q(Q[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF2"), .TYPE(EFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[9])) eff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[9]), .Q(Q2[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF"), .TYPE(FFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[10])) fff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[10]), .Q(Q[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF2"), .TYPE(FFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[11])) fff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[11]), .Q(Q2[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF"), .TYPE(GFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[12])) gff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[12]), .Q(Q[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF2"), .TYPE(GFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[13])) gff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[13]), .Q(Q2[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF"), .TYPE(HFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[14])) hff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[14]), .Q(Q[7])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF2"), .TYPE(HFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[15])) hff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[15]), .Q(Q2[7])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXA)) outmuxa_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .OUT(MUX[0])); + ultra_slice_logic_outmux #(.SEL(OUTMUXB)) outmuxb_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .OUT(MUX[1])); + ultra_slice_logic_outmux #(.SEL(OUTMUXC)) outmuxc_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .OUT(MUX[2])); + ultra_slice_logic_outmux #(.SEL(OUTMUXD)) outmuxd_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .OUT(MUX[3])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXE)) outmuxe_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .OUT(MUX[4])); + ultra_slice_logic_outmux #(.SEL(OUTMUXF)) outmuxf_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .OUT(MUX[5])); + ultra_slice_logic_outmux #(.SEL(OUTMUXG)) outmuxg_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .OUT(MUX[6])); + ultra_slice_logic_outmux #(.SEL(OUTMUXH)) outmuxh_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .OUT(MUX[7])); + + +endmodule + +module ultra_slice_logic_ffmux #( + parameter [1023:0] SEL = "BYP" +) ( + input XORIN, F7F8, D6, D5, CY, BYP, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + "BYP": assign OUT = BYP; + endcase + endgenerate +endmodule + +module ultra_slice_logic_ffx #( + parameter [1023:0] LOC = "", + parameter [1023:0] BEL = "", + parameter [1023:0] TYPE = "", + parameter CLKINV = 1'b0, + parameter SRINV = 1'b0, + parameter INIT = 1'b0 +) ( + input C, CE, SR, D, + output Q +); + generate + case (TYPE) + "FDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDPE #(.IS_C_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .PRE(SR), .D(D), .Q(Q)); + "FDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDCE #(.IS_C_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .CLR(SR), .D(D), .Q(Q)); + "FDSE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDSE #(.IS_C_INVERTED(CLKINV), .IS_S_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .S(SR), .D(D), .Q(Q)); + "FDRE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDRE #(.IS_C_INVERTED(CLKINV), .IS_R_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .R(SR), .D(D), .Q(Q)); + + "LDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDPE #(.IS_G_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .PRE(SR), .D(D), .Q(Q)); + "LDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDCE #(.IS_G_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .CLR(SR), .D(D), .Q(Q)); + "NONE": assign Q = INIT; + endcase + endgenerate +endmodule + +module ultra_slice_logic_outmux #( + parameter SEL = "D5" +) ( + input XORIN, F7F8, D6, D5, CY, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + endcase + endgenerate +endmodule \ No newline at end of file
diff --git a/spec/slice_carry.py b/spec/slice_carry.py new file mode 100644 index 0000000..d095b75 --- /dev/null +++ b/spec/slice_carry.py
@@ -0,0 +1,111 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +print("module top(input [15:0] clk, sr, ce, input [15:0] d, output [31:0] q);") +N = 350 +D = ["d[%d]" % i for i in range(16)] + +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) + +np.random.shuffle(slices) + +for i in range(N): + sl = slices.pop() + ffmode = np.random.randint(3, size=2) + clk = tuple(np.random.randint(16, size=2)) + sr = tuple(["1'b1" if y >= 16 else "sr[%d]" % y for y in np.random.randint(25, size=2)]) + ce = tuple(["1'b1" if y >= 16 else "ce[%d]" % y for y in np.random.randint(25, size=4)]) + + def random_fftype(mode): + if mode == 0: + return np.random.choice(["FDSE", "FDRE"]) + elif mode == 1: + return np.random.choice(["FDPE", "FDCE"]) + elif mode == 2: + return np.random.choice(["LDPE", "LDCE"]) + + def random_bit(): + return np.random.choice(D) + + def random_data(width): + return "{%s}" % (", ".join([random_bit() for k in range(width)])) + + fftypes = [random_fftype(ffmode[j // 8]) for j in range(16)] + used_outroute = [np.random.choice(["FF", "FF2", "MUX"]) for k in range(8)] + for j in range(8): + if used_outroute[j] == "FF": + fftypes[2*j + 1] = "NONE" + elif used_outroute[j] == "FF2": + fftypes[2*j] = "NONE" + else: + fftypes[2*j] = "NONE" + fftypes[2*j + 1] = "NONE" + cmode = np.random.choice(["NONE", "SINGLE_CY8", "DUAL_CY4"], p=[0.1, 0.7, 0.2]) + + print(' wire [31:0] d%d;' % i) + print(' ultra_slice_carry #(') + print(' .LOC("%s"),' % sl) + for lut in "ABCDEFGH": + print(" .%sLUT_INIT(64'b%s)," % (lut, "".join(str(_) for _ in np.random.randint(2, size=64)))) + for j in range(16): + print(' .%sFF%s_TYPE("%s"),' % ("ABCDEFGH"[j//2], "2" if (j % 2) == 1 else "", fftypes[j])) + print(" .FF_INIT(16'b%s)," % "".join(str(_) for _ in np.random.randint(2, size=16))) + for j1 in "ABCDEFGH": + for j2 in ("1", "2"): + print(' .FFMUX%s%s("%s"),' % (j1, j2, np.random.choice(["XORIN", "CY"] if cmode != "NONE" else ["D6"]))) + for j in range(8): + print(' .OUTMUX%s("%s"),' % ("ABCDEFGH"[j], ("D6" if used_outroute[j] != "MUX" else np.random.choice(["D6", "XORIN", "CY"] if cmode != "NONE" else ["D6"])))) + print(" .CLKINV(2'd%d)," % np.random.randint(4)) + print(" .SRINV(2'd%d)," % np.random.randint(4)) + print(' .CARRY_TYPE("%s"),' % cmode) + for j in range (8): + print(' .DI%dMUX("%s"),' % (j, np.random.choice(["DI", "X"]))) + print(' .CIMUX("%s"),' % np.random.choice(["1", "0", "X"])) + print(' .CITOPMUX("%s")' % (np.random.choice(["1", "0", "X"]) if cmode == "DUAL_CY4" else "CI")) + print(' ) slice%d (' % i) + for j in range(1, 7): + print(" .A%d(%s)," % (j, random_data(8))) + print(" .I(%s)," % random_data(8)) + print(" .X(%s)," % random_data(8)) + print(" .CLK({clk[%d], clk[%d]})," % clk) + print(" .SR({%s, %s})," % sr) + print(" .CE({%s, %s, %s, %s})," % ce) + print(" .O(d%d[7:0])," % i) + print(" .Q(d%d[15:8])," % i) + print(" .Q2(d%d[23:16])," % i) + print(" .MUX(d%d[31:24])" % i) + print(' );') + print() + + D.clear() + for j in range(8): + D.append("d%d[%d]" % (i, j)) + D.append("d%d[%d]" % (i, 24 + j)) + if fftypes[2 * j] != "NONE": + D.append("d%d[%d]" % (i, 8 + j)) + if fftypes[2 * j + 1] != "NONE": + D.append("d%d[%d]" % (i, 16 + j)) +print(" assign q = d%d;" % (N-1)) +print("endmodule") \ No newline at end of file
diff --git a/spec/slice_carry.v b/spec/slice_carry.v new file mode 100644 index 0000000..4eaeaee --- /dev/null +++ b/spec/slice_carry.v
@@ -0,0 +1,286 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module ultra_slice_carry #( + parameter [1023:0] LOC = "", + parameter [63:0] ALUT_INIT = 64'h00C0FFEE, + parameter [63:0] BLUT_INIT = 64'h00C0FFEE, + parameter [63:0] CLUT_INIT = 64'h00C0FFEE, + parameter [63:0] DLUT_INIT = 64'h00C0FFEE, + parameter [63:0] ELUT_INIT = 64'h00C0FFEE, + parameter [63:0] FLUT_INIT = 64'h00C0FFEE, + parameter [63:0] GLUT_INIT = 64'h00C0FFEE, + parameter [63:0] HLUT_INIT = 64'h00C0FFEE, + + parameter [1023:0] AFF_TYPE = "NONE", + parameter [1023:0] AFF2_TYPE = "NONE", + parameter [1023:0] BFF_TYPE = "NONE", + parameter [1023:0] BFF2_TYPE = "NONE", + parameter [1023:0] CFF_TYPE = "NONE", + parameter [1023:0] CFF2_TYPE = "NONE", + parameter [1023:0] DFF_TYPE = "NONE", + parameter [1023:0] DFF2_TYPE = "NONE", + parameter [1023:0] EFF_TYPE = "NONE", + parameter [1023:0] EFF2_TYPE = "NONE", + parameter [1023:0] FFF_TYPE = "NONE", + parameter [1023:0] FFF2_TYPE = "NONE", + parameter [1023:0] GFF_TYPE = "NONE", + parameter [1023:0] GFF2_TYPE = "NONE", + parameter [1023:0] HFF_TYPE = "NONE", + parameter [1023:0] HFF2_TYPE = "NONE", + + parameter [15:0] FF_INIT = 16'h0000, + + parameter [1023:0] FFMUXA1 = "BYP", + parameter [1023:0] FFMUXA2 = "BYP", + parameter [1023:0] FFMUXB1 = "BYP", + parameter [1023:0] FFMUXB2 = "BYP", + parameter [1023:0] FFMUXC1 = "BYP", + parameter [1023:0] FFMUXC2 = "BYP", + parameter [1023:0] FFMUXD1 = "BYP", + parameter [1023:0] FFMUXD2 = "BYP", + parameter [1023:0] FFMUXE1 = "BYP", + parameter [1023:0] FFMUXE2 = "BYP", + parameter [1023:0] FFMUXF1 = "BYP", + parameter [1023:0] FFMUXF2 = "BYP", + parameter [1023:0] FFMUXG1 = "BYP", + parameter [1023:0] FFMUXG2 = "BYP", + parameter [1023:0] FFMUXH1 = "BYP", + parameter [1023:0] FFMUXH2 = "BYP", + + parameter [1023:0] OUTMUXA = "D5", + parameter [1023:0] OUTMUXB = "D5", + parameter [1023:0] OUTMUXC = "D5", + parameter [1023:0] OUTMUXD = "D5", + parameter [1023:0] OUTMUXE = "D5", + parameter [1023:0] OUTMUXF = "D5", + parameter [1023:0] OUTMUXG = "D5", + parameter [1023:0] OUTMUXH = "D5", + + parameter [1023:0] DI0MUX = "DI", + parameter [1023:0] DI1MUX = "DI", + parameter [1023:0] DI2MUX = "DI", + parameter [1023:0] DI3MUX = "DI", + parameter [1023:0] DI4MUX = "DI", + parameter [1023:0] DI5MUX = "DI", + parameter [1023:0] DI6MUX = "DI", + parameter [1023:0] DI7MUX = "DI", + + parameter [1023:0] CARRY_TYPE = "NONE", + + parameter [1023:0] CIMUX = "CI", + parameter [1023:0] CITOPMUX = "CI", + + parameter [1:0] CLKINV = 2'b00, SRINV = 2'b00 + +) ( + input [7:0] A1, A2, A3, A4, A5, A6, I, X, + input [1:0] CLK, SR, + input [3:0] CE, + output [7:0] O, Q, Q2, MUX +); + wire [7:0] out5; + generate + if (DI0MUX == "DI") (* BEL="A5LUT", LOC=LOC *) LUT4 #(.INIT(ALUT_INIT[15:0])) a5lut (.I0(A1[0]), .I1(A2[0]), .I2(A3[0]), .I3(A4[0]), .O(out5[0])); + (* BEL="A6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(ALUT_INIT[47:32])) a6lut (.I0(A1[0]), .I1(A2[0]), .I2(A3[0]), .I3(A4[0]), .O(O[0])); + if (DI1MUX == "DI") (* BEL="B5LUT", LOC=LOC *) LUT4 #(.INIT(BLUT_INIT[15:0])) b5lut (.I0(A1[1]), .I1(A2[1]), .I2(A3[1]), .I3(A4[1]), .O(out5[1])); + (* BEL="B6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(BLUT_INIT[47:32])) b6lut (.I0(A1[1]), .I1(A2[1]), .I2(A3[1]), .I3(A4[1]), .O(O[1])); + if (DI2MUX == "DI") (* BEL="C5LUT", LOC=LOC *) LUT4 #(.INIT(CLUT_INIT[15:0])) c5lut (.I0(A1[2]), .I1(A2[2]), .I2(A3[2]), .I3(A4[2]),.O(out5[2])); + (* BEL="C6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(CLUT_INIT[47:32])) c6lut (.I0(A1[2]), .I1(A2[2]), .I2(A3[2]), .I3(A4[2]), .O(O[2])); + if (DI3MUX == "DI") (* BEL="D5LUT", LOC=LOC *) LUT4 #(.INIT(DLUT_INIT[15:0])) d5lut (.I0(A1[3]), .I1(A2[3]), .I2(A3[3]), .I3(A4[3]), .O(out5[3])); + (* BEL="D6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(DLUT_INIT[47:32])) d6lut (.I0(A1[3]), .I1(A2[3]), .I2(A3[3]), .I3(A4[3]), .O(O[3])); + + if (DI4MUX == "DI") (* BEL="E5LUT", LOC=LOC *) LUT4 #(.INIT(ELUT_INIT[15:0])) e5lut (.I0(A1[4]), .I1(A2[4]), .I2(A3[4]), .I3(A4[4]), .O(out5[4])); + (* BEL="E6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(ELUT_INIT[47:32])) e6lut (.I0(A1[4]), .I1(A2[4]), .I2(A3[4]), .I3(A4[4]), .O(O[4])); + if (DI5MUX == "DI") (* BEL="F5LUT", LOC=LOC *) LUT4 #(.INIT(FLUT_INIT[15:0])) f5lut (.I0(A1[5]), .I1(A2[5]), .I2(A3[5]), .I3(A4[5]), .O(out5[5])); + (* BEL="F6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(FLUT_INIT[47:32])) f6lut (.I0(A1[5]), .I1(A2[5]), .I2(A3[5]), .I3(A4[5]), .O(O[5])); + if (DI6MUX == "DI") (* BEL="G5LUT", LOC=LOC *) LUT4 #(.INIT(GLUT_INIT[15:0])) g5lut (.I0(A1[6]), .I1(A2[6]), .I2(A3[6]), .I3(A4[6]), .O(out5[6])); + (* BEL="G6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(GLUT_INIT[47:32])) g6lut (.I0(A1[6]), .I1(A2[6]), .I2(A3[6]), .I3(A4[6]), .O(O[6])); + if (DI7MUX == "DI") (* BEL="H5LUT", LOC=LOC *) LUT4 #(.INIT(HLUT_INIT[15:0])) h5lut (.I0(A1[7]), .I1(A2[7]), .I2(A3[7]), .I3(A4[7]), .O(out5[7])); + (* BEL="H6LUT", LOC=LOC, keep, dont_touch *) LUT4 #(.INIT(HLUT_INIT[47:32])) h6lut (.I0(A1[7]), .I1(A2[7]), .I2(A3[7]), .I3(A4[7]), .O(O[7])); + endgenerate + + wire [7:0] f7f8; + assign f7f8 = 8'h55; +/* + (* BEL="F7MUX_AB", LOC=LOC, keep, dont_touch *) MUXF7 f7muxab_i (.I0(O[1]), .I1(O[0]), .S(X[0]), .O(f7f8[1])); + (* BEL="F7MUX_CD", LOC=LOC, keep, dont_touch *) MUXF7 f7muxcd_i (.I0(O[3]), .I1(O[2]), .S(X[2]), .O(f7f8[3])); + (* BEL="F7MUX_EF", LOC=LOC, keep, dont_touch *) MUXF7 f7muxef_i (.I0(O[5]), .I1(O[4]), .S(X[4]), .O(f7f8[5])); + (* BEL="F7MUX_GH", LOC=LOC, keep, dont_touch *) MUXF7 f7muxgh_i (.I0(O[7]), .I1(O[6]), .S(X[6]), .O(f7f8[7])); + + (* BEL="F8MUX_BOT", LOC=LOC, keep, dont_touch *) MUXF8 f8muxabcd_i (.I0(f7f8[3]), .I1(f7f8[1]), .S(X[1]), .O(f7f8[2])); + (* BEL="F8MUX_TOP", LOC=LOC, keep, dont_touch *) MUXF8 f8muxefgh_i (.I0(f7f8[7]), .I1(f7f8[5]), .S(X[5]), .O(f7f8[6])); + + (* BEL="F9MUX", LOC=LOC, keep, dont_touch *) MUXF9 f9_i (.I0(f7f8[6]), .I1(f7f8[2]), .S(X[3]), .O(f7f8[4])); +*/ + wire [7:0] di; + wire ci, ci_top; + ultra_slice_carry_dimux #(.SEL(DI0MUX)) di0mux_i (.DI(out5[0]), .X(X[0]), .OUT(di[0])); + ultra_slice_carry_dimux #(.SEL(DI1MUX)) di1mux_i (.DI(out5[1]), .X(X[1]), .OUT(di[1])); + ultra_slice_carry_dimux #(.SEL(DI2MUX)) di2mux_i (.DI(out5[2]), .X(X[2]), .OUT(di[2])); + ultra_slice_carry_dimux #(.SEL(DI3MUX)) di3mux_i (.DI(out5[3]), .X(X[3]), .OUT(di[3])); + ultra_slice_carry_dimux #(.SEL(DI4MUX)) di4mux_i (.DI(out5[4]), .X(X[4]), .OUT(di[4])); + ultra_slice_carry_dimux #(.SEL(DI5MUX)) di5mux_i (.DI(out5[5]), .X(X[5]), .OUT(di[5])); + ultra_slice_carry_dimux #(.SEL(DI6MUX)) di6mux_i (.DI(out5[6]), .X(X[6]), .OUT(di[6])); + ultra_slice_carry_dimux #(.SEL(DI7MUX)) di7mux_i (.DI(out5[7]), .X(X[7]), .OUT(di[7])); + + ultra_slice_carry_cimux #(.SEL(CIMUX)) cimux_i (.CI(), .X(X[0]), .OUT(ci)); + ultra_slice_carry_cimux #(.SEL(CITOPMUX)) citopmux_i (.CI(), .X(X[4]), .OUT(ci_top)); + + wire [7:0] xoro, cout; + + generate + if (CARRY_TYPE != "NONE") + (* BEL="CARRY8", LOC=LOC, keep, dont_touch *) CARRY8 #(.CARRY_TYPE(CARRY_TYPE)) c8_i(.CI(ci), .CI_TOP(ci_top), .DI(di), .S(O), .O(xoro), .CO(cout)); + endgenerate + + wire [15:0] ffin; + ultra_slice_logic_ffmux #(.SEL(FFMUXA1)) ffmuxa1_i (.XORIN(xoro[0]), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(cout[0]), .BYP(), .OUT(ffin[0])); + ultra_slice_logic_ffmux #(.SEL(FFMUXA2)) ffmuxa2_i (.XORIN(xoro[0]), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(cout[0]), .BYP(I[0]), .OUT(ffin[1])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB1)) ffmuxb1_i (.XORIN(xoro[1]), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(cout[1]), .BYP(), .OUT(ffin[2])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB2)) ffmuxb2_i (.XORIN(xoro[1]), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(cout[1]), .BYP(I[1]), .OUT(ffin[3])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC1)) ffmuxc1_i (.XORIN(xoro[2]), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(cout[2]), .BYP(), .OUT(ffin[4])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC2)) ffmuxc2_i (.XORIN(xoro[2]), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(cout[2]), .BYP(I[2]), .OUT(ffin[5])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD1)) ffmuxd1_i (.XORIN(xoro[3]), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(cout[3]), .BYP(), .OUT(ffin[6])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD2)) ffmuxd2_i (.XORIN(xoro[3]), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(cout[3]), .BYP(I[3]), .OUT(ffin[7])); + + ultra_slice_logic_ffmux #(.SEL(FFMUXE1)) ffmuxe1_i (.XORIN(xoro[4]), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(cout[4]), .BYP(), .OUT(ffin[8])); + ultra_slice_logic_ffmux #(.SEL(FFMUXE2)) ffmuxe2_i (.XORIN(xoro[4]), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(cout[4]), .BYP(I[4]), .OUT(ffin[9])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF1)) ffmuxf1_i (.XORIN(xoro[5]), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(cout[5]), .BYP(), .OUT(ffin[10])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF2)) ffmuxf2_i (.XORIN(xoro[5]), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(cout[5]), .BYP(I[5]), .OUT(ffin[11])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG1)) ffmuxg1_i (.XORIN(xoro[6]), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(cout[6]), .BYP(), .OUT(ffin[12])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG2)) ffmuxg2_i (.XORIN(xoro[6]), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(cout[6]), .BYP(I[6]), .OUT(ffin[13])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH1)) ffmuxh1_i (.XORIN(xoro[7]), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(cout[7]), .BYP(), .OUT(ffin[14])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH2)) ffmuxh2_i (.XORIN(xoro[7]), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(cout[7]), .BYP(I[7]), .OUT(ffin[15])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF"), .TYPE(AFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[0])) aff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[0]), .Q(Q[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF2"), .TYPE(AFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[1])) aff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[1]), .Q(Q2[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF"), .TYPE(BFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[2])) bff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[2]), .Q(Q[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF2"), .TYPE(BFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[3])) bff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[3]), .Q(Q2[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF"), .TYPE(CFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[4])) cff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[4]), .Q(Q[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF2"), .TYPE(CFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[5])) cff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[5]), .Q(Q2[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF"), .TYPE(DFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[6])) dff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[6]), .Q(Q[3])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF2"), .TYPE(DFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[7])) dff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[7]), .Q(Q2[3])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF"), .TYPE(EFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[8])) eff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[8]), .Q(Q[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF2"), .TYPE(EFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[9])) eff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[9]), .Q(Q2[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF"), .TYPE(FFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[10])) fff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[10]), .Q(Q[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF2"), .TYPE(FFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[11])) fff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[11]), .Q(Q2[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF"), .TYPE(GFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[12])) gff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[12]), .Q(Q[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF2"), .TYPE(GFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[13])) gff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[13]), .Q(Q2[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF"), .TYPE(HFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[14])) hff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[14]), .Q(Q[7])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF2"), .TYPE(HFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[15])) hff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[15]), .Q(Q2[7])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXA)) outmuxa_i (.XORIN(xoro[0]), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(cout[0]), .OUT(MUX[0])); + ultra_slice_logic_outmux #(.SEL(OUTMUXB)) outmuxb_i (.XORIN(xoro[1]), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(cout[1]), .OUT(MUX[1])); + ultra_slice_logic_outmux #(.SEL(OUTMUXC)) outmuxc_i (.XORIN(xoro[2]), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(cout[2]), .OUT(MUX[2])); + ultra_slice_logic_outmux #(.SEL(OUTMUXD)) outmuxd_i (.XORIN(xoro[3]), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(cout[3]), .OUT(MUX[3])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXE)) outmuxe_i (.XORIN(xoro[4]), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(cout[4]), .OUT(MUX[4])); + ultra_slice_logic_outmux #(.SEL(OUTMUXF)) outmuxf_i (.XORIN(xoro[5]), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(cout[5]), .OUT(MUX[5])); + ultra_slice_logic_outmux #(.SEL(OUTMUXG)) outmuxg_i (.XORIN(xoro[6]), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(cout[6]), .OUT(MUX[6])); + ultra_slice_logic_outmux #(.SEL(OUTMUXH)) outmuxh_i (.XORIN(xoro[7]), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(cout[7]), .OUT(MUX[7])); + + +endmodule + +module ultra_slice_logic_ffmux #( + parameter [1023:0] SEL = "BYP" +) ( + input XORIN, F7F8, D6, D5, CY, BYP, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + "BYP": assign OUT = BYP; + endcase + endgenerate +endmodule + +module ultra_slice_logic_ffx #( + parameter [1023:0] LOC = "", + parameter [1023:0] BEL = "", + parameter [1023:0] TYPE = "", + parameter CLKINV = 1'b0, + parameter SRINV = 1'b0, + parameter INIT = 1'b0 +) ( + input C, CE, SR, D, + output Q +); + generate + case (TYPE) + "FDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDPE #(.IS_C_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .PRE(SR), .D(D), .Q(Q)); + "FDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDCE #(.IS_C_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .CLR(SR), .D(D), .Q(Q)); + "FDSE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDSE #(.IS_C_INVERTED(CLKINV), .IS_S_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .S(SR), .D(D), .Q(Q)); + "FDRE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDRE #(.IS_C_INVERTED(CLKINV), .IS_R_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .R(SR), .D(D), .Q(Q)); + + "LDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDPE #(.IS_G_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .PRE(SR), .D(D), .Q(Q)); + "LDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDCE #(.IS_G_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .CLR(SR), .D(D), .Q(Q)); + "NONE": assign Q = INIT; + endcase + endgenerate +endmodule + +module ultra_slice_logic_outmux #( + parameter SEL = "D5" +) ( + input XORIN, F7F8, D6, D5, CY, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + endcase + endgenerate +endmodule + +module ultra_slice_carry_dimux #( + parameter SEL = "DI" +) ( + input DI, X, + output OUT +); + generate + case(SEL) + "DI": assign OUT = DI; + "X": assign OUT = X; + endcase + endgenerate +endmodule + +module ultra_slice_carry_cimux #( + parameter SEL = "CI" +) ( + input CI, X, + output OUT +); + generate + case(SEL) + "CI": assign OUT = CI; + "0": assign OUT = 1'b0; + "1": assign OUT = 1'b1; + "X": assign OUT = X; + endcase + endgenerate +endmodule \ No newline at end of file
diff --git a/spec/slice_logic.py b/spec/slice_logic.py new file mode 100644 index 0000000..ce6f46d --- /dev/null +++ b/spec/slice_logic.py
@@ -0,0 +1,95 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +print("module top(input [15:0] clk, sr, ce, input [7:0] d, output [31:0] q);") +N = 500 +D = ["d[%d]" % i for i in range(8)] + +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + for site in sl[4:]: + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) + +np.random.shuffle(slices) + +for i in range(N): + sl = slices.pop() + ffmode = np.random.randint(3, size=2) + clk = tuple(np.random.randint(16, size=2)) + sr = tuple(["1'b1" if y >= 16 else "sr[%d]" % y for y in np.random.randint(25, size=2)]) + ce = tuple(["1'b1" if y >= 16 else "ce[%d]" % y for y in np.random.randint(25, size=4)]) + + def random_fftype(mode): + if mode == 0: + return np.random.choice(["NONE", "FDSE", "FDRE"]) + elif mode == 1: + return np.random.choice(["NONE", "FDPE", "FDCE"]) + elif mode == 2: + return np.random.choice(["NONE", "LDPE", "LDCE"]) + + def random_bit(): + return np.random.choice(D) + + def random_data(width): + return "{%s}" % (", ".join([random_bit() for k in range(width)])) + + fftypes = [random_fftype(ffmode[j // 8]) for j in range(16)] + + print(' wire [31:0] d%d;' % i) + print(' ultra_slice_logic #(') + print(' .LOC("%s"),' % sl) + for lut in "ABCDEFGH": + print(" .%sLUT_INIT(64'b%s)," % (lut, "".join(str(_) for _ in np.random.randint(2, size=64)))) + for j in range(16): + print(' .%sFF%s_TYPE("%s"),' % ("ABCDEFGH"[j//2], "2" if (j % 2) == 1 else "", fftypes[j])) + print(" .FF_INIT(16'b%s)," % "".join(str(_) for _ in np.random.randint(2, size=16))) + for j1 in "ABCDEFGH": + for j2 in ("1", "2"): + print(' .FFMUX%s%s("%s"),' % (j1, j2, np.random.choice(["F7F8", "D6", "D5", "BYP"]))) + for j in "ABCDEFGH": + print(' .OUTMUX%s("%s"),' % (j, np.random.choice(["F7F8", "D6", "D5"]))) + print(" .CLKINV(2'd%d)," % np.random.randint(4)) + print(" .SRINV(2'd%d)" % np.random.randint(4)) + print(' ) slice%d (' % i) + for j in range(1, 7): + print(" .A%d(%s)," % (j, random_data(8))) + print(" .I(%s)," % random_data(8)) + print(" .X(%s)," % random_data(8)) + print(" .CLK({clk[%d], clk[%d]})," % clk) + print(" .SR({%s, %s})," % sr) + print(" .CE({%s, %s, %s, %s})," % ce) + print(" .O(d%d[7:0])," % i) + print(" .Q(d%d[15:8])," % i) + print(" .Q2(d%d[23:16])," % i) + print(" .MUX(d%d[31:24])" % i) + print(' );') + print() + D.clear() + for j in range(8): + D.append("d%d[%d]" % (i, j)) + D.append("d%d[%d]" % (i, 24 + j)) + if fftypes[2 * j] != "NONE": + D.append("d%d[%d]" % (i, 8 + j)) + if fftypes[2 * j + 1] != "NONE": + D.append("d%d[%d]" % (i, 16 + j)) +print(" assign q = d%d;" % (N-1)) +print("endmodule") \ No newline at end of file
diff --git a/spec/slice_memory.py b/spec/slice_memory.py new file mode 100644 index 0000000..06130cb --- /dev/null +++ b/spec/slice_memory.py
@@ -0,0 +1,143 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import sys + +print("module top(input [15:0] clk, sr, ce, input [7:0] d, output [31:0] q);") +N = 350 +D = ["d[%d]" % i for i in range(8)] + +slices = [] +with open(sys.argv[1], "r") as tf: + for line in tf: + sl = line.strip().split(",") + if len(sl) < 4: + continue + if "CLEM" not in sl[3]: + continue + for site in sl[4:]: + if "SLICEM" in site or "SLICEL" in site: + slices.append(site.split(":")[0]) + +np.random.shuffle(slices) + +for i in range(N): + sl = slices.pop() + ffmode = np.random.randint(3, size=2) + clk = tuple(np.random.randint(16, size=2)) + wclk = None + while wclk is None or wclk in clk: + wclk = np.random.randint(16) + sr = tuple(["1'b1" if y >= 16 else "sr[%d]" % y for y in np.random.randint(25, size=2)]) + ce = tuple(["1'b1" if y >= 16 else "ce[%d]" % y for y in np.random.randint(25, size=4)]) + we = np.random.randint(16) + def random_fftype(mode): + if mode == 0: + return np.random.choice(["NONE", "FDSE", "FDRE"]) + elif mode == 1: + return np.random.choice(["NONE", "FDPE", "FDCE"]) + elif mode == 2: + return np.random.choice(["NONE", "LDPE", "LDCE"]) + + def random_bit(): + return np.random.choice(D) + + def random_data(width): + return "{%s}" % (", ".join([random_bit() for k in range(width)])) + + #fftypes = [random_fftype(ffmode[j // 8]) for j in range(16)] + fftypes = ["NONE" for j in range(16)] + + dimux = [] + mode = [] + ram_legal = True + for lut in "HGFEDCBA": + choices = ["LOGIC"] + if lut == "H": + choices += ["RAMD64", "RAMS64", "RAMD32", "SRL16", "SRL32"] + else: + if mode[0][0:3] != "RAM": + choices += ["SRL16", "SRL32"] + if ram_legal: + choices.append(mode[0]) + p = [0.1] + for j in range(1, len(choices)): + p.append(0.9 / (len(choices) - 1)) + if len(choices) == 1: + p[0] = 1 + next_mode = np.random.choice(choices, p=p) + if len(mode) > 0 and mode[-1] == "SRL32" and next_mode == "SRL32": + dimux.append(np.random.choice(["DI", "SIN"], p=[0.2, 0.8])) + else: + dimux.append("DI") + if next_mode[0:3] != "RAM": + ram_legal = False + mode.append(next_mode) + + dimux = list(reversed(dimux)) + mode = list(reversed(mode)) + + print(' wire [31:0] d%d;' % i) + print(' ultra_slice_memory #(') + print(' .LOC("%s"),' % sl) + for j in range(8): + print(' .%s_MODE("%s"),' % ("ABCDEFGH"[j], mode[j])) + for lut in "ABCDEFGH": + print(" .%sLUT_INIT(64'b%s)," % (lut, "".join(str(_) for _ in np.random.randint(2, size=64)))) + for j in range(16): + print(' .%sFF%s_TYPE("%s"),' % ("ABCDEFGH"[j//2], "2" if (j % 2) == 1 else "", fftypes[j])) + print(" .FF_INIT(16'b%s)," % "".join(str(_) for _ in np.random.randint(2, size=16))) + for j1 in "ABCDEFGH": + for j2 in ("1", "2"): + print(' .FFMUX%s%s("%s"),' % (j1, j2, np.random.choice(["F7F8", "D6", "D5"]))) + for j in "ABCDEFGH": + print(' .OUTMUX%s("%s"),' % (j, np.random.choice(["F7F8", "D6", "D5"]))) + for j in range(7): + print(' .DIMUX%s("%s"),' % ("ABCDEFG"[j], dimux[j])) + print(" .WCLKINV(1'd%d)," % np.random.randint(2)) + + waused = np.random.randint(4) + + print(" .WA6USED(1'd%d)," % (1 if waused > 0 else 0)) + print(" .WA7USED(1'd%d)," % (1 if waused > 1 else 0)) + print(" .WA8USED(1'd%d)," % (1 if waused > 2 else 0)) + print(" .CLKINV(2'd%d)," % np.random.randint(4)) + print(" .SRINV(2'd%d)" % np.random.randint(4)) + print(' ) slice%d (' % i) + for j in range(1, 7): + print(" .A%d(%s)," % (j, random_data(8))) + print(" .I(%s)," % random_data(8)) + print(" .X(%s)," % random_data(8)) + print(" .CLK({clk[%d], clk[%d]})," % clk[0:2]) + print(" .WCLK(clk[%d])," % wclk) + print(" .SR({%s, %s})," % sr) + print(" .CE({%s, %s, %s, %s})," % ce[0:4]) + print(" .WE(ce[%d])," % we) + print(" .O(d%d[7:0])," % i) + print(" .Q(d%d[15:8])," % i) + print(" .Q2(d%d[23:16])," % i) + print(" .MUX(d%d[31:24])" % i) + print(' );') + print() + D.clear() + for j in range(8): + D.append("d%d[%d]" % (i, j)) + D.append("d%d[%d]" % (i, 24 + j)) + if fftypes[2 * j] != "NONE": + D.append("d%d[%d]" % (i, 8 + j)) + if fftypes[2 * j + 1] != "NONE": + D.append("d%d[%d]" % (i, 16 + j)) +print(" assign q = d%d;" % (N-1)) +print("endmodule") \ No newline at end of file
diff --git a/spec/slice_memory.v b/spec/slice_memory.v new file mode 100644 index 0000000..efe2fe7 --- /dev/null +++ b/spec/slice_memory.v
@@ -0,0 +1,384 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module ultra_slice_memory #( + parameter [1023:0] LOC = "", + parameter [63:0] ALUT_INIT = 64'h00C0FFEE, + parameter [63:0] BLUT_INIT = 64'h00C0FFEE, + parameter [63:0] CLUT_INIT = 64'h00C0FFEE, + parameter [63:0] DLUT_INIT = 64'h00C0FFEE, + parameter [63:0] ELUT_INIT = 64'h00C0FFEE, + parameter [63:0] FLUT_INIT = 64'h00C0FFEE, + parameter [63:0] GLUT_INIT = 64'h00C0FFEE, + parameter [63:0] HLUT_INIT = 64'h00C0FFEE, + + parameter [1023:0] A_MODE = "LOGIC", + parameter [1023:0] B_MODE = "LOGIC", + parameter [1023:0] C_MODE = "LOGIC", + parameter [1023:0] D_MODE = "LOGIC", + parameter [1023:0] E_MODE = "LOGIC", + parameter [1023:0] F_MODE = "LOGIC", + parameter [1023:0] G_MODE = "LOGIC", + parameter [1023:0] H_MODE = "LOGIC", + + + parameter [1023:0] AFF_TYPE = "NONE", + parameter [1023:0] AFF2_TYPE = "NONE", + parameter [1023:0] BFF_TYPE = "NONE", + parameter [1023:0] BFF2_TYPE = "NONE", + parameter [1023:0] CFF_TYPE = "NONE", + parameter [1023:0] CFF2_TYPE = "NONE", + parameter [1023:0] DFF_TYPE = "NONE", + parameter [1023:0] DFF2_TYPE = "NONE", + parameter [1023:0] EFF_TYPE = "NONE", + parameter [1023:0] EFF2_TYPE = "NONE", + parameter [1023:0] FFF_TYPE = "NONE", + parameter [1023:0] FFF2_TYPE = "NONE", + parameter [1023:0] GFF_TYPE = "NONE", + parameter [1023:0] GFF2_TYPE = "NONE", + parameter [1023:0] HFF_TYPE = "NONE", + parameter [1023:0] HFF2_TYPE = "NONE", + + parameter [15:0] FF_INIT = 16'h0000, + + parameter [1023:0] FFMUXA1 = "BYP", + parameter [1023:0] FFMUXA2 = "BYP", + parameter [1023:0] FFMUXB1 = "BYP", + parameter [1023:0] FFMUXB2 = "BYP", + parameter [1023:0] FFMUXC1 = "BYP", + parameter [1023:0] FFMUXC2 = "BYP", + parameter [1023:0] FFMUXD1 = "BYP", + parameter [1023:0] FFMUXD2 = "BYP", + parameter [1023:0] FFMUXE1 = "BYP", + parameter [1023:0] FFMUXE2 = "BYP", + parameter [1023:0] FFMUXF1 = "BYP", + parameter [1023:0] FFMUXF2 = "BYP", + parameter [1023:0] FFMUXG1 = "BYP", + parameter [1023:0] FFMUXG2 = "BYP", + parameter [1023:0] FFMUXH1 = "BYP", + parameter [1023:0] FFMUXH2 = "BYP", + + parameter [1023:0] OUTMUXA = "D5", + parameter [1023:0] OUTMUXB = "D5", + parameter [1023:0] OUTMUXC = "D5", + parameter [1023:0] OUTMUXD = "D5", + parameter [1023:0] OUTMUXE = "D5", + parameter [1023:0] OUTMUXF = "D5", + parameter [1023:0] OUTMUXG = "D5", + parameter [1023:0] OUTMUXH = "D5", + + parameter [1023:0] DIMUXA = "DI", + parameter [1023:0] DIMUXB = "DI", + parameter [1023:0] DIMUXC = "DI", + parameter [1023:0] DIMUXD = "DI", + parameter [1023:0] DIMUXE = "DI", + parameter [1023:0] DIMUXF = "DI", + parameter [1023:0] DIMUXG = "DI", + + parameter WA6USED = 0, WA7USED = 0, WA8USED = 0, WCLKINV = 0, + + parameter [1:0] CLKINV = 2'b00, SRINV = 2'b00 + +) ( + input [7:0] A1, A2, A3, A4, A5, A6, I, X, + input [1:0] CLK, SR, + input WCLK, WE, + input [3:0] CE, + output [7:0] O, Q, Q2, MUX +); + + wire [8:0] wa; + assign wa[5:0] = {A6[7], A5[7], A4[7], A3[7], A2[7], A1[7]}; + generate + if (WA6USED) assign wa[6] = X[6]; + if (WA7USED) assign wa[7] = X[5]; + if (WA8USED) assign wa[8] = X[3]; + endgenerate + + wire [7:0] di0; + wire [7:0] mc31; + + assign di0[7] = I[7]; + + ultra_slice_logic_dimux #(.SEL(DIMUXA)) dimuxa_i (.DI(I[0]), .SIN(mc31[1]), .OUT(di0[0])); + ultra_slice_logic_dimux #(.SEL(DIMUXB)) dimuxb_i (.DI(I[1]), .SIN(mc31[2]), .OUT(di0[1])); + ultra_slice_logic_dimux #(.SEL(DIMUXC)) dimuxc_i (.DI(I[2]), .SIN(mc31[3]), .OUT(di0[2])); + ultra_slice_logic_dimux #(.SEL(DIMUXD)) dimuxd_i (.DI(I[3]), .SIN(mc31[4]), .OUT(di0[3])); + ultra_slice_logic_dimux #(.SEL(DIMUXE)) dimuxe_i (.DI(I[4]), .SIN(mc31[5]), .OUT(di0[4])); + ultra_slice_logic_dimux #(.SEL(DIMUXF)) dimuxf_i (.DI(I[5]), .SIN(mc31[6]), .OUT(di0[5])); + ultra_slice_logic_dimux #(.SEL(DIMUXG)) dimuxg_i (.DI(I[6]), .SIN(mc31[7]), .OUT(di0[6])); + + wire [7:0] out5; + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("H5LUT"), .BEL6("H6LUT"), .MODE(H_MODE), .INIT(HLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) hlut_i (.CLK(WCLK), .CE(WE), .A({A6[7], A5[7], A4[7], A3[7], A2[7], A1[7]}), .WA(wa), .DI({X[7], di0[7]}), .DO({O[7], out5[7]}), .MC31(mc31[7])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("A5LUT"), .BEL6("A6LUT"), .MODE(A_MODE), .INIT(ALUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) alut_i (.CLK(WCLK), .CE(WE), .A({A6[0], A5[0], A4[0], A3[0], A2[0], A1[0]}), .WA(wa), .DI({X[0], di0[0]}), .DO({O[0], out5[0]}), .MC31(mc31[0])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("B5LUT"), .BEL6("B6LUT"), .MODE(B_MODE), .INIT(BLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) blut_i (.CLK(WCLK), .CE(WE), .A({A6[1], A5[1], A4[1], A3[1], A2[1], A1[1]}), .WA(wa), .DI({X[1], di0[1]}), .DO({O[1], out5[1]}), .MC31(mc31[1])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("C5LUT"), .BEL6("C6LUT"), .MODE(C_MODE), .INIT(CLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) clut_i (.CLK(WCLK), .CE(WE), .A({A6[2], A5[2], A4[2], A3[2], A2[2], A1[2]}), .WA(wa), .DI({X[2], di0[2]}), .DO({O[2], out5[2]}), .MC31(mc31[2])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("D5LUT"), .BEL6("D6LUT"), .MODE(D_MODE), .INIT(DLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) dlut_i (.CLK(WCLK), .CE(WE), .A({A6[3], A5[3], A4[3], A3[3], A2[3], A1[3]}), .WA(wa), .DI({X[3], di0[3]}), .DO({O[3], out5[3]}), .MC31(mc31[3])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("E5LUT"), .BEL6("E6LUT"), .MODE(E_MODE), .INIT(ELUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) elut_i (.CLK(WCLK), .CE(WE), .A({A6[4], A5[4], A4[4], A3[4], A2[4], A1[4]}), .WA(wa), .DI({X[4], di0[4]}), .DO({O[4], out5[4]}), .MC31(mc31[4])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("F5LUT"), .BEL6("F6LUT"), .MODE(F_MODE), .INIT(FLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) flut_i (.CLK(WCLK), .CE(WE), .A({A6[5], A5[5], A4[5], A3[5], A2[5], A1[5]}), .WA(wa), .DI({X[5], di0[5]}), .DO({O[5], out5[5]}), .MC31(mc31[5])); + ultra_slice_memory_lut #(.LOC(LOC), .BEL5("G5LUT"), .BEL6("G6LUT"), .MODE(G_MODE), .INIT(GLUT_INIT), .CLKINV(WCLKINV), .WA6USED(WA6USED), .WA7USED(WA7USED), .WA8USED(WA8USED)) glut_i (.CLK(WCLK), .CE(WE), .A({A6[6], A5[6], A4[6], A3[6], A2[6], A1[6]}), .WA(wa), .DI({X[6], di0[6]}), .DO({O[6], out5[6]}), .MC31(mc31[6])); + + wire [7:0] f7f8; + assign f7f8[0] = mc31[0]; +/* + (* BEL="F7MUX_AB", LOC=LOC, keep, dont_touch *) MUXF7 f7muxab_i (.I0(O[1]), .I1(O[0]), .S(X[0]), .O(f7f8[1])); + (* BEL="F7MUX_CD", LOC=LOC, keep, dont_touch *) MUXF7 f7muxcd_i (.I0(O[3]), .I1(O[2]), .S(X[2]), .O(f7f8[3])); + (* BEL="F7MUX_EF", LOC=LOC, keep, dont_touch *) MUXF7 f7muxef_i (.I0(O[5]), .I1(O[4]), .S(X[4]), .O(f7f8[5])); + (* BEL="F7MUX_GH", LOC=LOC, keep, dont_touch *) MUXF7 f7muxgh_i (.I0(O[7]), .I1(O[6]), .S(X[6]), .O(f7f8[7])); + + (* BEL="F8MUX_BOT", LOC=LOC, keep, dont_touch *) MUXF8 f8muxabcd_i (.I0(f7f8[3]), .I1(f7f8[1]), .S(X[1]), .O(f7f8[2])); + (* BEL="F8MUX_TOP", LOC=LOC, keep, dont_touch *) MUXF8 f8muxefgh_i (.I0(f7f8[7]), .I1(f7f8[5]), .S(X[5]), .O(f7f8[6])); + + (* BEL="F9MUX", LOC=LOC, keep, dont_touch *) MUXF9 f9_i (.I0(f7f8[6]), .I1(f7f8[2]), .S(X[3]), .O(f7f8[4])); +*/ + assign f7f8[7:1] = O[7:1]; + wire [15:0] ffin; + ultra_slice_logic_ffmux #(.SEL(FFMUXA1)) ffmuxa1_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .BYP(X[0]), .OUT(ffin[0])); + ultra_slice_logic_ffmux #(.SEL(FFMUXA2)) ffmuxa2_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .BYP(I[0]), .OUT(ffin[1])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB1)) ffmuxb1_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .BYP(X[1]), .OUT(ffin[2])); + ultra_slice_logic_ffmux #(.SEL(FFMUXB2)) ffmuxb2_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .BYP(I[1]), .OUT(ffin[3])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC1)) ffmuxc1_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .BYP(X[2]), .OUT(ffin[4])); + ultra_slice_logic_ffmux #(.SEL(FFMUXC2)) ffmuxc2_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .BYP(I[2]), .OUT(ffin[5])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD1)) ffmuxd1_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .BYP(X[3]), .OUT(ffin[6])); + ultra_slice_logic_ffmux #(.SEL(FFMUXD2)) ffmuxd2_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .BYP(I[3]), .OUT(ffin[7])); + + ultra_slice_logic_ffmux #(.SEL(FFMUXE1)) ffmuxe1_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .BYP(X[4]), .OUT(ffin[8])); + ultra_slice_logic_ffmux #(.SEL(FFMUXE2)) ffmuxe2_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .BYP(I[4]), .OUT(ffin[9])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF1)) ffmuxf1_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .BYP(X[5]), .OUT(ffin[10])); + ultra_slice_logic_ffmux #(.SEL(FFMUXF2)) ffmuxf2_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .BYP(I[5]), .OUT(ffin[11])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG1)) ffmuxg1_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .BYP(X[6]), .OUT(ffin[12])); + ultra_slice_logic_ffmux #(.SEL(FFMUXG2)) ffmuxg2_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .BYP(I[6]), .OUT(ffin[13])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH1)) ffmuxh1_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .BYP(X[7]), .OUT(ffin[14])); + ultra_slice_logic_ffmux #(.SEL(FFMUXH2)) ffmuxh2_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .BYP(I[7]), .OUT(ffin[15])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF"), .TYPE(AFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[0])) aff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[0]), .Q(Q[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("AFF2"), .TYPE(AFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[1])) aff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[1]), .Q(Q2[0])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF"), .TYPE(BFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[2])) bff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[2]), .Q(Q[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("BFF2"), .TYPE(BFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[3])) bff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[3]), .Q(Q2[1])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF"), .TYPE(CFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[4])) cff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[4]), .Q(Q[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("CFF2"), .TYPE(CFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[5])) cff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[5]), .Q(Q2[2])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF"), .TYPE(DFF_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[6])) dff_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[0]), .D(ffin[6]), .Q(Q[3])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("DFF2"), .TYPE(DFF2_TYPE), .CLKINV(CLKINV[0]), .SRINV(SRINV[0]), .INIT(FF_INIT[7])) dff2_i (.C(CLK[0]), .SR(SR[0]), .CE(CE[1]), .D(ffin[7]), .Q(Q2[3])); + + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF"), .TYPE(EFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[8])) eff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[8]), .Q(Q[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("EFF2"), .TYPE(EFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[9])) eff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[9]), .Q(Q2[4])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF"), .TYPE(FFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[10])) fff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[10]), .Q(Q[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("FFF2"), .TYPE(FFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[11])) fff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[11]), .Q(Q2[5])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF"), .TYPE(GFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[12])) gff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[12]), .Q(Q[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("GFF2"), .TYPE(GFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[13])) gff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[13]), .Q(Q2[6])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF"), .TYPE(HFF_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[14])) hff_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[2]), .D(ffin[14]), .Q(Q[7])); + ultra_slice_logic_ffx #(.LOC(LOC), .BEL("HFF2"), .TYPE(HFF2_TYPE), .CLKINV(CLKINV[1]), .SRINV(SRINV[1]), .INIT(FF_INIT[15])) hff2_i (.C(CLK[1]), .SR(SR[1]), .CE(CE[3]), .D(ffin[15]), .Q(Q2[7])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXA)) outmuxa_i (.XORIN(), .F7F8(f7f8[0]), .D6(O[0]), .D5(out5[0]), .CY(), .OUT(MUX[0])); + ultra_slice_logic_outmux #(.SEL(OUTMUXB)) outmuxb_i (.XORIN(), .F7F8(f7f8[1]), .D6(O[1]), .D5(out5[1]), .CY(), .OUT(MUX[1])); + ultra_slice_logic_outmux #(.SEL(OUTMUXC)) outmuxc_i (.XORIN(), .F7F8(f7f8[2]), .D6(O[2]), .D5(out5[2]), .CY(), .OUT(MUX[2])); + ultra_slice_logic_outmux #(.SEL(OUTMUXD)) outmuxd_i (.XORIN(), .F7F8(f7f8[3]), .D6(O[3]), .D5(out5[3]), .CY(), .OUT(MUX[3])); + + ultra_slice_logic_outmux #(.SEL(OUTMUXE)) outmuxe_i (.XORIN(), .F7F8(f7f8[4]), .D6(O[4]), .D5(out5[4]), .CY(), .OUT(MUX[4])); + ultra_slice_logic_outmux #(.SEL(OUTMUXF)) outmuxf_i (.XORIN(), .F7F8(f7f8[5]), .D6(O[5]), .D5(out5[5]), .CY(), .OUT(MUX[5])); + ultra_slice_logic_outmux #(.SEL(OUTMUXG)) outmuxg_i (.XORIN(), .F7F8(f7f8[6]), .D6(O[6]), .D5(out5[6]), .CY(), .OUT(MUX[6])); + ultra_slice_logic_outmux #(.SEL(OUTMUXH)) outmuxh_i (.XORIN(), .F7F8(f7f8[7]), .D6(O[7]), .D5(out5[7]), .CY(), .OUT(MUX[7])); + + +endmodule + +module ultra_slice_logic_ffmux #( + parameter [1023:0] SEL = "BYP" +) ( + input XORIN, F7F8, D6, D5, CY, BYP, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + "BYP": assign OUT = BYP; + endcase + endgenerate +endmodule + +module ultra_slice_logic_ffx #( + parameter [1023:0] LOC = "", + parameter [1023:0] BEL = "", + parameter [1023:0] TYPE = "", + parameter CLKINV = 1'b0, + parameter SRINV = 1'b0, + parameter INIT = 1'b0 +) ( + input C, CE, SR, D, + output Q +); + generate + case (TYPE) + "FDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDPE #(.IS_C_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .PRE(SR), .D(D), .Q(Q)); + "FDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDCE #(.IS_C_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .CLR(SR), .D(D), .Q(Q)); + "FDSE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDSE #(.IS_C_INVERTED(CLKINV), .IS_S_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .S(SR), .D(D), .Q(Q)); + "FDRE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) FDRE #(.IS_C_INVERTED(CLKINV), .IS_R_INVERTED(SRINV), .INIT(INIT)) ff_i (.C(C), .CE(CE), .R(SR), .D(D), .Q(Q)); + + "LDPE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDPE #(.IS_G_INVERTED(CLKINV), .IS_PRE_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .PRE(SR), .D(D), .Q(Q)); + "LDCE": (* LOC=LOC, BEL=BEL, keep, dont_touch *) LDCE #(.IS_G_INVERTED(CLKINV), .IS_CLR_INVERTED(SRINV), .INIT(INIT)) ff_i (.G(C), .GE(CE), .CLR(SR), .D(D), .Q(Q)); + "NONE": assign Q = INIT; + endcase + endgenerate +endmodule + +module ultra_slice_logic_outmux #( + parameter SEL = "D5" +) ( + input XORIN, F7F8, D6, D5, CY, + output OUT +); + generate + case(SEL) + "XORIN": assign OUT = XORIN; + "F7F8": assign OUT = F7F8; + "D6": assign OUT = D6; + "D5": assign OUT = D5; + "CY": assign OUT = CY; + endcase + endgenerate +endmodule + +module ultra_slice_logic_dimux #( + parameter [1023:0] SEL = "DI" +) ( + input DI, SIN, + output OUT +); + generate + case(SEL) + "DI": assign OUT = DI; + "SIN": assign OUT = SIN; + endcase + endgenerate +endmodule + +module ultra_slice_memory_lut #( + parameter [1023:0] LOC = "", + parameter [1023:0] BEL5 = "", + parameter [1023:0] BEL6 = "", + parameter [1023:0] MODE = "LOGIC", + parameter [63:0] INIT = 64'h0, + parameter CLKINV = 0, WA6USED = 0, WA7USED = 0, WA8USED = 0 +) ( + input CLK, CE, + input [5:0] A, + input [8:0] WA, + input [1:0] DI, + output [1:0] DO, + output MC31 +); + generate + if (MODE == "LOGIC") begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(INIT[63:32])) lut6 (.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]), .I4(A[4]), .O(DO[1])); + (* BEL=BEL5, LOC=LOC, keep, dont_touch *) LUT5 #(.INIT(INIT[31:0])) lut5 (.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]), .I4(A[4]), .O(DO[0])); + assign MC31 = DO[1]; + end else if (MODE == "SRL16") begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) SRL16E #(.INIT(INIT[63:32]), .IS_CLK_INVERTED(CLKINV)) srl6 (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .D(DI[1]), .CLK(CLK), .CE(CE), .Q(DO[1])); + (* BEL=BEL5, LOC=LOC, keep, dont_touch *) SRL16E #(.INIT(INIT[31:0]), .IS_CLK_INVERTED(CLKINV)) srl5 (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .D(DI[0]), .CLK(CLK), .CE(CE), .Q(DO[0])); + assign MC31 = DO[1]; + end else if (MODE == "SRL32") begin + (* BEL=BEL6, keep, dont_touch *) SRLC32E #(.INIT(INIT[31:0]), .IS_CLK_INVERTED(CLKINV)) srl6(.A(A[4:0]), .D(DI[0]), .CLK(CLK), .CE(CE), .Q(DO[1]), .Q31(MC31)); + assign DO[0] = DO[1]; + end else if (MODE == "RAMD64") begin + if (WA6USED && WA7USED) begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMD64E #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .RADR0(A[0]), .RADR1(A[1]), .RADR2(A[2]), .RADR3(A[3]), .RADR4(A[4]), .RADR5(A[5]), + .WADR0(WA[0]), .WADR1(WA[1]), .WADR2(WA[2]), .WADR3(WA[3]), .WADR4(WA[4]), .WADR5(WA[5]), .WADR6(WA[6]), .WADR7(WA[7]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + + end else if (WA6USED) begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMD64E #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .RADR0(A[0]), .RADR1(A[1]), .RADR2(A[2]), .RADR3(A[3]), .RADR4(A[4]), .RADR5(A[5]), + .WADR0(WA[0]), .WADR1(WA[1]), .WADR2(WA[2]), .WADR3(WA[3]), .WADR4(WA[4]), .WADR5(WA[5]), .WADR6(WA[6]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end else begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMD64E #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .RADR0(A[0]), .RADR1(A[1]), .RADR2(A[2]), .RADR3(A[3]), .RADR4(A[4]), .RADR5(A[5]), + .WADR0(WA[0]), .WADR1(WA[1]), .WADR2(WA[2]), .WADR3(WA[3]), .WADR4(WA[4]), .WADR5(WA[5]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end + assign DO[0] = DO[1]; + assign MC31 = DO[1]; + end else if (MODE == "RAMS64") begin + if (WA6USED && WA7USED && WA8USED) begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMS64E1 #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), .ADR5(WA[5]), + .WADR6(WA[6]), .WADR7(WA[7]), .WADR8(WA[8]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end else if (WA6USED && WA7USED) begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMS64E1 #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), .ADR5(WA[5]), + .WADR6(WA[6]), .WADR7(WA[7]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end else if (WA6USED) begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMS64E1 #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), .ADR5(WA[5]), + .WADR6(WA[6]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end else begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMS64E1 #(.INIT(INIT), .IS_CLK_INVERTED(CLKINV)) ram_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), .ADR5(WA[5]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[1]) + ); + end + assign DO[0] = DO[1]; + assign MC31 = DO[1]; + end else if (MODE == "RAMS32") begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMS32 #(.INIT(INIT[63:32]), .IS_CLK_INVERTED(CLKINV)) ram1_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), + .CLK(CLK), .WE(CE), + .I(DI[1]), .O(DO[1]) + ); + (* BEL=BEL5, LOC=LOC, keep, dont_touch *) RAMS32 #(.INIT(INIT[31:0]), .IS_CLK_INVERTED(CLKINV)) ram0_i ( + .ADR0(WA[0]), .ADR1(WA[1]), .ADR2(WA[2]), .ADR3(WA[3]), .ADR4(WA[4]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[0]) + ); + assign MC31 = DO[1]; + end else if (MODE == "RAMD32") begin + (* BEL=BEL6, LOC=LOC, keep, dont_touch *) RAMD32 #(.INIT(INIT[63:32]), .IS_CLK_INVERTED(CLKINV)) ram1_i ( + .WADR0(WA[0]), .WADR1(WA[1]), .WADR2(WA[2]), .WADR3(WA[3]), .WADR4(WA[4]), + .RADR0(A[0]), .RADR1(A[1]), .RADR2(A[2]), .RADR3(A[3]), .RADR4(A[4]), + .CLK(CLK), .WE(CE), + .I(DI[1]), .O(DO[1]) + ); + (* BEL=BEL5, LOC=LOC, keep, dont_touch *) RAMD32 #(.INIT(INIT[31:0]), .IS_CLK_INVERTED(CLKINV)) ram0_i ( + .WADR0(WA[0]), .WADR1(WA[1]), .WADR2(WA[2]), .WADR3(WA[3]), .WADR4(WA[4]), + .RADR0(A[0]), .RADR1(A[1]), .RADR2(A[2]), .RADR3(A[3]), .RADR4(A[4]), + .CLK(CLK), .WE(CE), + .I(DI[0]), .O(DO[0]) + ); + assign MC31 = DO[1]; + end else begin + $error("unsupported mode"); + end + endgenerate +endmodule \ No newline at end of file
diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..c18aed5 --- /dev/null +++ b/tools/.gitignore
@@ -0,0 +1,5 @@ +dump_bitstream +correlate +explain +stripdb +assemble
diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..de2ccde --- /dev/null +++ b/tools/Makefile
@@ -0,0 +1,20 @@ +all: dump_bitstream correlate explain stripdb assemble + +CXXFLAGS := -std=c++17 -O3 -g +LINK.o = $(LINK.cc) + +%.o: common.h + +dump_bitstream: dump_bitstream.o common.o + +correlate: correlate.o + +explain: explain.o common.o + +stripdb: stripdb.o + +assemble: assemble.o common.o + +clean: + rm *.o dump_bitstream correlate stripdb assemble +.PHONY: clean \ No newline at end of file
diff --git a/tools/assemble.cpp b/tools/assemble.cpp new file mode 100644 index 0000000..f86e494 --- /dev/null +++ b/tools/assemble.cpp
@@ -0,0 +1,347 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <iostream> +#include <fstream> +#include <string> +#include <unordered_set> +#include <unordered_map> +#include <map> +#include <set> +#include <cassert> +#include <stdexcept> +#include <stdarg.h> +#include "common.h" + +enum BitstreamRegister : uint16_t { + #define X(a, b) a = b, + #include "registers.inc" + #undef X +}; + + +ChipData chip; + +std::unordered_set<uint32_t> roi_frames; +std::map<uint32_t, std::vector<bool>> frames; +std::map<uint32_t, uint32_t> next_frame; +std::string db_root; + + +void set_tile_bit(const TileInstance &tile, int bit) { + int pos = 0; + for (auto &bm : tile.bits) { + if (bit >= pos && bit < (pos + bm.size)) { + frames.at(bm.frame_offset).at(bm.bit_offset + (bit - pos)) = true; + return; + } + pos += bm.size; + } + throw std::runtime_error("bad bit " + tile.name + "." + std::to_string(bit)); +} + + +void set_feature(const std::string &tile, const std::string &feature) { + auto &db = chip.load_tile_database(tile); + if (!db.features.count(feature)) { + throw std::runtime_error("unknown feature " + feature + " in tile " + tile); + } + const auto &fbits = db.features.at(feature); + auto &t = chip.tiles[tile]; + for (auto bit : fbits) + set_tile_bit(t, bit); +} + +void read_quasi_fasm(const std::string &filename) { + LineReader rd(filename); + std::vector<std::string> split; + for (auto &line : rd) { + split_str(line, split, ".", true, 1); + if (split.size() < 2) + continue; + set_feature(split.at(0), split.at(1)); + } +} + +// Add ECCs to frames +void add_frame_ecc() { + + auto get_ecc_value = [](int word, int bit) { + int nib = bit / 4; + int nibbit = bit % 4; + // ECC offset is expanded to 1 bit per nibble, + // and then shifted based on the bit index in nibble + // e.g. word 3, bit 9 + // offset: 0b10100110010 - concatenate (3 + (255 - 92)) [frame offset] and 9/4 [nibble offset] + // becomes: 0x10100110010 + // shifted by bit in nibble (9%4): 0x20200220020 + uint32_t offset = (word + (255 - 92)) << 3 | nib; + uint64_t exp_offset = 0; + // Odd parity + offset ^= (1 << 11); + for (int i = 0; i < 11; i++) + if (offset & (1 << i)) offset ^= (1 << 11); + // Expansion + for (int i = 0; i < 12; i++) + if (offset & (1 << i)) exp_offset |= (1ULL << (4 * i)); + return exp_offset << nibbit; + }; + + for (auto &fr : frames) { + auto &bits = fr.second; + uint64_t ecc = 0; + for (int word = 0; word < 93; word++) { + for (int i = 0; i < 32; i++) { + if (!bits.at(word * 32 + i)) + continue; + if ((word == 45) || ((word == 46 && (i < 16)))) { + bits.at(word * 32 + i) = false; + continue; + } + ecc ^= get_ecc_value(word, i); + } + } + for (int i = 0; i < 48; i++) + if (ecc & (1ULL << i)) + bits.at(45*32 + i) = true; + } +} + + +struct ByteStreamWriter { + std::vector<uint8_t> data; + + uint32_t curr_crc = 0; + uint32_t curr_addr = 0; + + void write_byte(uint8_t byte) { + data.push_back(byte); + } + void write_bytes(const std::vector<uint8_t> &bytes) { + data.insert(data.end(), bytes.begin(), bytes.end()); + } + void write_string(const std::string &str) { + int len = int(str.length()) + 1; + data.push_back((len >> 8) & 0xFF); + data.push_back(len & 0xFF); + for (char c : str) data.push_back(uint8_t(c)); + data.push_back(0x00); + } + void write_u32(uint32_t word, bool update_crc = false) { + data.push_back((word >> 24) & 0xFF); + data.push_back((word >> 16) & 0xFF); + data.push_back((word >> 8) & 0xFF); + data.push_back((word >> 0) & 0xFF); + if (update_crc) + curr_crc = icap_crc(curr_addr, word, curr_crc); + } + void write_short_packet(BitstreamOp op, BitstreamRegister reg = BitstreamRegister(0x00), const std::vector<uint32_t> &payload = {}) { + curr_addr = uint32_t(reg); + write_u32((0b001UL << 29) | ((uint32_t(op) & 0x03) << 27) | ((uint32_t(reg) & 0x3FFF) << 13) | (uint32_t(payload.size()) & 0x3FFF)); + for (uint32_t x : payload) + write_u32(x, true); + } + void write_long_packet(const std::vector<uint32_t> &payload) { + write_u32((0b010UL << 29) | (uint32_t(OP_READ) << 27) | (uint32_t(payload.size()) & 0x3FFFFFF)); + for (uint32_t x : payload) + write_u32(x, true); + } + void write_crc() { + write_short_packet(OP_WRITE, CRC, {curr_crc}); + curr_crc = 0; + } +}; + +void write_bitstream(std::ofstream &f) { +#if 0 + // FIXME - write an actual binary bitstream + for (auto &frame : frames) { + for (size_t i = 0; i < frame.second.size(); i++) { + if (frame.second.at(i)) + f << stringf("F%08xW%03dB%02d", frame.first, int(i / 32), int(i % 32)) << std::endl; + } + } +#else + + add_frame_ecc(); + + ByteStreamWriter bsw; + // Header + bsw.write_bytes({0x00, 0x09, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x01, 0x61}); + bsw.write_string("top;UserID=0XFFFFFFFF;Version=2019.1"); + bsw.write_byte(0x62); + bsw.write_string("xczu7ev-ffvc1156-2-e"); + bsw.write_byte(0x63); + bsw.write_string("2019/09/08"); + bsw.write_byte(0x64); + bsw.write_string("00:00:00"); + bsw.write_bytes({0x65, 0x01, 0x36, 0x6F, 0xB0}); + for (int i = 0; i < 64; i++) + bsw.write_byte(0xFF); + bsw.write_bytes({0x00, 0x00, 0x00, 0xBB, 0x11, 0x22, 0x00, 0x44}); + for (int i = 0; i < 8; i++) + bsw.write_byte(0xFF); + // Preamble + bsw.write_u32(0xAA995566); + // Initial commands + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, TIMER, {0x00000000}); + bsw.write_short_packet(OP_WRITE, WBSTAR, {0x00000000}); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000000}); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000007}); + bsw.curr_crc = 0; + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, FAR, {0x00000000}); + bsw.write_short_packet(OP_WRITE, BitstreamRegister(0x13), {0x00000000}); + bsw.write_short_packet(OP_WRITE, COR0, {0x38003fe5}); + bsw.write_short_packet(OP_WRITE, COR1, {0x00400000}); + bsw.write_short_packet(OP_WRITE, IDCODE, {0x04a5a093}); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000009}); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, MASK, {0x00000001}); + bsw.write_short_packet(OP_WRITE, CTL0, {0x00000101}); + bsw.write_short_packet(OP_WRITE, MASK, {0x00200000}); + bsw.write_short_packet(OP_WRITE, CTL1, {0x00200000}); + for (int i = 0; i < 8; i++) + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000001}); + bsw.write_short_packet(OP_NOP); + // Frame data + std::vector<uint32_t> fdata(93, 0x00000000); + bsw.write_short_packet(OP_WRITE, FAR, {frames.begin()->first}); + for (auto &fr : frames) { + for (int i = 0; i < 93; i++) { + fdata[i] = 0x00000000; + for (int j = 0; j < 32; j++) + if (fr.second.at(i * 32 + j)) + fdata[i] |= (1 << j); + } + bsw.write_short_packet(OP_WRITE, FDRI, fdata); + bsw.write_short_packet(OP_WRITE, FAR, {fr.first}); + bsw.write_crc(); + if (!next_frame.count(fr.first) || ((next_frame.at(fr.first) ^ fr.first) & 0xFFFC0000)) { + // Duplicate last frame in a row, but empty?? + for (int i = 0; i < 93; i++) + fdata[i] = 0; + bsw.write_short_packet(OP_WRITE, FDRI, fdata); + bsw.write_short_packet(OP_WRITE, FAR, {fr.first}); + bsw.write_crc(); + if (next_frame.count(fr.first)) { + // CMD 1 (WCFG) + bsw.write_short_packet(OP_WRITE, CMD, {0x00000001}); + bsw.write_short_packet(OP_NOP); + // Next frame address + bsw.write_short_packet(OP_WRITE, FAR, {next_frame.at(fr.first)}); + } + } + + //bsw.write_long_packet(fdata); + } + // End of bitstream + bsw.write_short_packet(OP_WRITE, CMD, {0x00000000}); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, MASK, {0x00200000}); + bsw.write_short_packet(OP_WRITE, CTL1, {0x00000000}); + bsw.write_crc(); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x0000000a}); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000003}); + for (int i = 0; i < 20; i++) + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x00000005}); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, FAR, {0x07FC0000}); + bsw.write_short_packet(OP_WRITE, MASK, {0x00000101}); + bsw.write_short_packet(OP_WRITE, CTL0, {0x00000101}); + bsw.write_crc(); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_NOP); + bsw.write_short_packet(OP_WRITE, CMD, {0x0000000d}); + for (int i = 0; i < 400; i++) + bsw.write_short_packet(OP_NOP); + f.write(reinterpret_cast<const char *>(&(bsw.data[0])), bsw.data.size()); +#endif +} + +void parse_harness(const std::string &filename) { + LineReader rd(filename); + for (auto &line : rd) { + assert(line.at(0) == 'F'); + const char *curr = line.c_str() + 1; + char *next = nullptr; + uint32_t frame = std::strtoul(curr, &next, 16); + if (roi_frames.count(frame)) + continue; + assert(*next == 'W'); + curr = next + 1; + int word = std::strtol(curr, &next, 10); + curr = next + 1; + assert(*next == 'B'); + int bit = std::strtol(curr, &next, 10); + frames[frame].at(word * 32 + bit) = true; + } +} + +void parse_frames(const std::string &filename, std::unordered_set<uint32_t> &dest_set) { + LineReader rd(filename); + for (auto &line : rd) { + const char *start = line.c_str(); + char *end = nullptr; + uint32_t addr = std::strtol(start, &end, 16); + if ((end == nullptr) || (end == start)) + continue; + dest_set.insert(addr); + frames[addr].clear(); + frames[addr].resize(93*32, false); + } +} + +void setup_base_frames() { + uint32_t last_frame = 0xFFFFFFFF; + for (auto addr : chip.all_frames) { + if (addr == 0x07FC0000) + continue; + frames[addr].clear(); + frames[addr].resize(93*32, false); + if (last_frame != 0xFFFFFFFF) + next_frame[last_frame] = addr; + last_frame = addr; + } +} + +int main(int argc, char *argv[]) { + if (argc < 6) { + std::cerr << "Usage: ./assemble dbdir roi_frames.txt harness.txt input.fasm out.bit" << std::endl; + return 2; + } + db_root = argv[1]; + chip.open(db_root); + setup_base_frames(); + parse_frames(argv[2], roi_frames); + parse_harness(argv[3]); + read_quasi_fasm(argv[4]); + std::ofstream obf(argv[5], std::ios::binary); + if (!obf) { + std::cerr << "failed to open " << argv[5] << std::endl; + return 1; + } + write_bitstream(obf); +} \ No newline at end of file
diff --git a/tools/bits.py b/tools/bits.py new file mode 100644 index 0000000..e493cc4 --- /dev/null +++ b/tools/bits.py
@@ -0,0 +1,81 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json +# Usage: frames.txt tiles.txt tilegrid.json + +frame_line_re = re.compile(r'0x([0-9A-Fa-f]+).*') + +frame_rc_height = {} + +with open(sys.argv[1], 'r') as f: + for line in f: + m = frame_line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + minor = frame & 0xFF + if bus != 0 or half != 0: + continue + if (row, col) not in frame_rc_height: + frame_rc_height[(row, col, frame & ~0xFF)] = minor + 1 + else: + frame_rc_height[(row, col, frame & ~0xFF)] = max(frame_rc_height[(row, col)], minor + 1) + +tiles_to_xy = {} +with open(sys.argv[2], 'r') as tilef: + for line in tilef: + sl = line.strip().split(",") + if len(sl) < 4: + continue + x = int(sl[0]) + y = int(sl[1]) + name = sl[2] + tiles_to_xy[name] = (x, y) + +with open(sys.argv[3]) as tb_f: + tbj = json.load(tb_f) + +frames_to_tiles = {} +for tilename, tiledata in tbj.items(): + tile_offset = 0 + for chunk in tiledata: + frame, start, size = chunk + if frame not in frames_to_tiles: + frames_to_tiles[frame] = [] + name = tilename.split(":")[0] + frames_to_tiles[frame].append((start, tiles_to_xy[name][1], tiles_to_xy[name][0], name)) + tile_offset += size + +for frame, tiles in frames_to_tiles.items(): + tiles.sort() + +for rc, height in sorted(frame_rc_height.items()): + row, col, frame = rc + line = "%08x %6d %6d %6d" % (frame, row, col, height) + print(line) + frame = (row << 18) | (col << 8) + last_start = 0; + if frame in frames_to_tiles and len(frames_to_tiles[frame]) > 0: + for tile in frames_to_tiles[frame]: + start, ty, tx, tname = tile + print(" %6d (%4d) %6d %6d %s" % (start, start - last_start, tx, ty, tname)) + last_start = start +
diff --git a/tools/bits_to_tiles.py b/tools/bits_to_tiles.py new file mode 100644 index 0000000..42a5928 --- /dev/null +++ b/tools/bits_to_tiles.py
@@ -0,0 +1,61 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json + +line_re = re.compile(r'F(0x[0-9A-Fa-f]+)W(\d+)B(\d+)') +frames_to_tiles = {} # (start, size, tile, tile offset) + +with open(sys.argv[1]) as tb_f: + tbj = json.load(tb_f) + +for tilename, tiledata in tbj.items(): + tile_offset = 0 + for chunk in tiledata: + frame, start, size = chunk + if frame not in frames_to_tiles: + frames_to_tiles[frame] = [] + frames_to_tiles[frame].append((start, size, tilename, tile_offset)) + tile_offset += size + +tile_bits = {} + +# Always write these tiles to avoid correlation issues +# (distinguishing between all/no bits) +for tilename, tiledata in tbj.items(): + if "INT_INTF_L_IO" in tilename: + tile_bits[tilename] = set() + +with open(sys.argv[2]) as df: + for line in df: + m = line_re.match(line) + if not m: + continue + frame = int(m[1], 16) + if frame not in frames_to_tiles: + continue + framebit = int(m[2]) * 32 + int(m[3]) + for fb in frames_to_tiles[frame]: + start, size, tile, toff = fb + if framebit >= start and framebit < (start + size): + if tile not in tile_bits: + tile_bits[tile] = set() + tile_bits[tile].add(toff + (framebit - start)) + +for tile, bits in sorted(tile_bits.items()): + print(".tile %s" % tile) + for b in sorted(bits): + print(b)
diff --git a/tools/columns.py b/tools/columns.py new file mode 100644 index 0000000..826cc04 --- /dev/null +++ b/tools/columns.py
@@ -0,0 +1,80 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json +# Usage: frames.txt tiles.txt tilegrid.json + +frame_line_re = re.compile(r'0x([0-9A-Fa-f]+).*') + +frame_rc_height = {} + +with open(sys.argv[1], 'r') as f: + for line in f: + m = frame_line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + minor = frame & 0xFF + if bus != 0 or half != 0: + continue + if (row, col) not in frame_rc_height: + frame_rc_height[(row, col)] = minor + 1 + else: + frame_rc_height[(row, col)] = max(frame_rc_height[(row, col)], minor + 1) + +tiles_to_xy = {} +with open(sys.argv[2], 'r') as tilef: + for line in tilef: + sl = line.strip().split(",") + if len(sl) < 4: + continue + x = int(sl[0]) + y = int(sl[1]) + name = sl[2] + tiles_to_xy[name] = (x, y) + +with open(sys.argv[3]) as tb_f: + tbj = json.load(tb_f) + +frames_to_tiles = {} +for tilename, tiledata in tbj.items(): + tile_offset = 0 + for chunk in tiledata: + frame, start, size = chunk + if frame not in frames_to_tiles: + frames_to_tiles[frame] = [] + name = tilename.split(":")[0] + frames_to_tiles[frame].append((tiles_to_xy[name][1], tiles_to_xy[name][0], name)) + tile_offset += size + +for frame, tiles in frames_to_tiles.items(): + tiles.sort() + +print("row col height tx ty tname") + +for rc, height in sorted(frame_rc_height.items()): + row, col = rc + line = "%6d %6d %6d" % (row, col, height) + frame = (row << 18) | (col << 8) + if frame in frames_to_tiles and len(frames_to_tiles[frame]) > 0: + ty, tx, tname = frames_to_tiles[frame][0] + line += " %6d %6d %s" % (tx, ty, tname) + print(line) +
diff --git a/tools/common.cpp b/tools/common.cpp new file mode 100644 index 0000000..01d80b0 --- /dev/null +++ b/tools/common.cpp
@@ -0,0 +1,80 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "common.h" + + +void ChipData::open(const std::string &root) { + this->root = root; + load_frames(); + load_tiles(); +} + +void ChipData::load_frames() { + LineReader rd(root + "/frames.txt"); + for (const std::string &line : rd) { + all_frames.insert(std::strtoul(line.c_str(), nullptr, 16)); + } +} + +void ChipData::load_tiletype_database(int type) { + auto &tt = tiletypes.at(type); + if (tt.loaded_db) + return; + LineReader rd(root + "/" + tt.type + ".bits"); + std::vector<std::string> split; + for (const std::string &line : rd) { + split_str(line, split); + if (split.size() < 1) + continue; + auto &feat = tt.features[split.at(0)]; + for (size_t i = 1; i < split.size(); i++) + feat.push_back(std::stoi(split.at(i))); + } + tt.loaded_db = true; +} + +void ChipData::load_tiles() { + LineReader rd(root + "/tiles.txt"); + std::vector<std::string> split; + TileInstance *curr = nullptr; + + for (const std::string &line : rd) { + split_str(line, split); + if (split.size() < 1) + continue; + if (split.at(0) == ".tile") { + curr = &(tiles[split.at(1)]); + curr->name = split.at(1); + if (!tiletype_by_name.count(split.at(2))) { + tiletype_by_name[split.at(2)] = int(tiletypes.size()); + curr->type = int(tiletypes.size()); + tiletypes.emplace_back(); + tiletypes.back().type = split.at(2); + } else { + curr->type = tiletype_by_name.at(split.at(2)); + } + curr->x = std::stoi(split.at(3)); + curr->y = std::stoi(split.at(4)); + } else if (split.at(0) == "frame") { + TileInstance::TileBitMapping tbm; + tbm.frame_offset = std::strtoul(split.at(1).c_str(), nullptr, 16); + tbm.bit_offset = std::stoi(split.at(3)); + tbm.size = std::stoi(split.at(5)); + curr->bits.push_back(tbm); + } + } +} + +
diff --git a/tools/common.h b/tools/common.h new file mode 100644 index 0000000..481e842 --- /dev/null +++ b/tools/common.h
@@ -0,0 +1,211 @@ +#ifndef COMMON_H +#define COMMON_H + +#include <stdint.h> +#include <string> +#include <vector> +#include <iostream> +#include <fstream> +#include <stdexcept> +#include <map> +#include <set> +#include <unordered_map> +#include <stdarg.h> +constexpr uint32_t kCrc32CastagnoliPolynomial = 0x82F63B78; + +// From prjxray +// The CRC is calculated from each written data word and the current +// register address the data is written to. + +// Extend the current CRC value with one register address (5bit) and +// frame data (32bit) pair and return the newly computed CRC value. + +inline uint32_t icap_crc(uint32_t addr, uint32_t data, uint32_t prev) { + constexpr int kAddressBitWidth = 5; + constexpr int kDataBitWidth = 32; + + uint64_t poly = static_cast<uint64_t>(kCrc32CastagnoliPolynomial) << 1; + uint64_t val = (static_cast<uint64_t>(addr) << 32) | data; + uint64_t crc = prev; + + for (int i = 0; i < kAddressBitWidth + kDataBitWidth; i++) { + if ((val & 1) != (crc & 1)) + crc ^= poly; + + val >>= 1; + crc >>= 1; + } + return crc; +} + +// From Yosys +inline std::string vstringf(const char *fmt, va_list ap) +{ + std::string string; + char *str = NULL; + +#if defined(_WIN32 )|| defined(__CYGWIN__) + int sz = 64, rc; + while (1) { + va_list apc; + va_copy(apc, ap); + str = (char*)realloc(str, sz); + rc = vsnprintf(str, sz, fmt, apc); + va_end(apc); + if (rc >= 0 && rc < sz) + break; + sz *= 2; + } +#else + if (vasprintf(&str, fmt, ap) < 0) + str = NULL; +#endif + + if (str != NULL) { + string = str; + free(str); + } + + return string; +} + +inline std::string stringf(const char *fmt, ...) +{ + std::string string; + va_list ap; + + va_start(ap, fmt); + string = vstringf(fmt, ap); + va_end(ap); + + return string; +} + +// Bitstream definitions + +enum BitstreamOp : uint8_t { + OP_NOP = 0, + OP_READ = 1, + OP_WRITE = 2 +}; + +// File and database convenience functions +// Line-by-line reader, skipping over blank lines and comments +struct LineReader { + LineReader(const std::string &filename) { + in.open(filename); + if (!in) { + throw std::runtime_error("failed to open " + filename); + } + } + std::ifstream in; + std::string linebuf; + bool at_sof = true; + + struct iterator { + LineReader *parent = nullptr; + bool at_end = false; + inline bool operator!=(const iterator &other) const { + return at_end != other.at_end; + }; + inline const std::string& operator*() const { + return parent->linebuf; + } + inline iterator &operator++() { + parent->next(); + at_end = parent->linebuf.empty(); + return *this; + } + }; + + void next() { + while (std::getline(in, linebuf)) { + auto cpos = linebuf.find('#'); + if (cpos != std::string::npos) + linebuf = linebuf.substr(0, cpos); + if (linebuf.empty()) + continue; + linebuf = linebuf.substr(linebuf.find_first_not_of(" \t")); + if (linebuf.empty()) + continue; + break; + } + at_sof = false; + } + + iterator begin() { + if (at_sof) + next(); + return iterator{this, linebuf.empty()}; + } + + iterator end() { + return iterator{this, true}; + } +}; + +struct TileInstance { + std::string name; + int type; + int x, y; + struct TileBitMapping { + int frame_offset; + int bit_offset; + int size; + }; + std::vector<TileBitMapping> bits; +}; + +struct TileType { + std::string type; + bool loaded_db = false; + std::unordered_map<std::string, std::vector<int>> features; +}; + +struct ChipData { + + std::string root; + void open(const std::string &root); + void load_frames(); + void load_tiles(); + void load_tiletype_database(int type); + + std::unordered_map<std::string, TileInstance> tiles; + inline TileInstance &get_tile_by_name(const std::string &name) { + return tiles.at(name); + } + + std::vector<TileType> tiletypes; + std::unordered_map<std::string, int> tiletype_by_name; + TileType &get_tiletype_by_name(const std::string &name) { + return tiletypes.at(tiletype_by_name.at(name)); + } + TileType &load_tile_database(const std::string &tile) { + int type = tiles.at(tile).type; + load_tiletype_database(type); + return tiletypes.at(type); + } + + std::set<uint32_t> all_frames; + +}; + +inline void split_str(const std::string &s, std::vector<std::string> &dest, const std::string &delim = " ", bool skip_empty = true, int lim = -1) { + dest.clear(); + std::string buf; + + for (char c : s) { + if (delim.find(c) != std::string::npos && (lim == -1 || int(dest.size()) < lim)) { + if (!buf.empty() || !skip_empty) + dest.push_back(buf); + buf.clear(); + } else { + buf += c; + } + } + + if (!buf.empty()) + dest.push_back(buf); +} + +#endif \ No newline at end of file
diff --git a/tools/correlate.cpp b/tools/correlate.cpp new file mode 100644 index 0000000..2c4676d --- /dev/null +++ b/tools/correlate.cpp
@@ -0,0 +1,254 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <vector> +#include <iostream> +#include <map> +#include <string> +#include <fstream> +#include <stdexcept> +#include <iterator> +#include <stdarg.h> +#include <unordered_set> +#include <unordered_map> +#include <set> +#include <sstream> +#include <algorithm> +#include <filesystem> +namespace fs = std::filesystem; + +struct FeatureData { + std::unordered_set<int> always_set_with_feature; + std::unordered_set<int> never_set_with_feature; + std::unordered_set<int> always_set_without_feature; + + std::vector<std::pair<int, bool>> featbits; + std::set<std::string> deps; + int count; +}; + +struct TileTypeData { + std::unordered_map<std::string, std::unordered_set<std::string>> inst_features; + std::unordered_map<std::string, std::unordered_set<int>> inst_bits; + std::unordered_set<int> settable_bits; + std::set<std::string> extant_features; + std::unordered_map<std::string, FeatureData> features; +}; + +std::map<std::string, TileTypeData> tiletypes; +std::set<std::string> include_tts; + +std::pair<std::string, std::string> split_tilename(const std::string &name) { + size_t idx = name.find(':'); + return std::make_pair(name.substr(0, idx), name.substr(idx+1)); +} + +void parse_bits(const std::string &prefix, std::istream &in) { + std::string line; + std::unordered_set<int> *bits = nullptr; + std::unordered_set<int> *settable_bits = nullptr; + bool skip = false; + + while (std::getline(in, line)) { + if (line.empty()) + continue; + std::istringstream iss(line); + if (line.front() == '.') { + std::string t, tn; + iss >> t >> tn; + auto spn = split_tilename(tn); + if (!include_tts.empty() && !include_tts.count(spn.second)) { + skip = true; + continue; + } else { + skip = false; + } + settable_bits = &(tiletypes[spn.second].settable_bits); + bits = &(tiletypes[spn.second].inst_bits[prefix + spn.first]); + } else { + int bit = -1; + iss >> bit; + if (!skip && bit != -1) { + bits->insert(bit); + settable_bits->insert(bit); + } + } + } +} + +void parse_features(const std::string &prefix, std::istream &in) { + std::string line; + std::unordered_set<std::string> *feats = nullptr; + std::set<std::string> *ext_feats = nullptr; + bool skip = false; + + while (std::getline(in, line)) { + if (line.empty()) + continue; + std::istringstream iss(line); + if (line.front() == '.') { + std::string t, tn; + iss >> t >> tn; + auto spn = split_tilename(tn); + if (!include_tts.empty() && !include_tts.count(spn.second)) { + skip = true; + continue; + } else { + skip = false; + } + ext_feats = &(tiletypes[spn.second].extant_features); + feats = &(tiletypes[spn.second].inst_features[prefix + spn.first]); + } else { + std::string feat; + iss >> feat; + if (!feat.empty() && !skip) { + feats->insert(feat); + ext_feats->insert(feat); + } + } + } +} + +template <typename Tc, typename Tv, typename Tf> void set_erase_if(Tc &target, std::vector<Tv> &temp, Tf pred) { + temp.clear(); + for (auto &entry : target) + if (pred(entry)) + temp.push_back(entry); + for (auto &toerase : temp) + target.erase(toerase); +} + +void find_feature_deps(TileTypeData &tt) { + for (auto &f : tt.extant_features) { + auto &fd = tt.features[f]; + fd.deps = tt.extant_features; + fd.deps.erase(f); + std::vector<std::string> temp; + for (auto &inst : tt.inst_features) { + if (!inst.second.count(f)) + continue; + set_erase_if(fd.deps, temp, [&](const std::string &ef){ return !inst.second.count(ef); }); + } + } +} + +void process_feature(TileTypeData &tt, const std::string &feature) { + + FeatureData &fd = tt.features[feature]; + + fd.always_set_with_feature = tt.settable_bits; + //fd.never_set_with_feature = tt.settable_bits; + fd.always_set_without_feature = tt.settable_bits; + + std::vector<int> temp; + fd.count = 0; + bool always_have_feature = true; + for (auto &inst : tt.inst_bits) { + if (!tt.inst_features.count(inst.first)) + continue; + auto &ib = inst.second; + bool has_feature = tt.inst_features.at(inst.first).count(feature); + if (!has_feature) + always_have_feature = false; + + if (has_feature) + ++fd.count; + + if (has_feature) + set_erase_if(fd.always_set_with_feature, temp, [&](int bit){ return !ib.count(bit); }); + //if (has_feature) + // set_erase_if(fd.never_set_with_feature, temp, [&](int bit){ return ib.count(bit); }); + if (!has_feature) + set_erase_if(fd.always_set_without_feature, temp, [&](int bit){ return !ib.count(bit); }); + } + for (int as : fd.always_set_with_feature) + if (always_have_feature || !fd.always_set_without_feature.count(as)) + if (std::all_of(fd.deps.begin(), fd.deps.end(), [&](const std::string &dep) { + auto &dd = tt.features[dep]; + return std::find(dd.featbits.begin(), dd.featbits.end(), std::make_pair(as, false)) == dd.featbits.end(); + })) + fd.featbits.emplace_back(as, false); + /*for (int nv : fd.never_set_with_feature) + if (fd.always_set_without_feature.count(nv)) + fd.featbits.emplace_back(nv, true);*/ + // FIXME: inverted feature bits? + std::sort(fd.featbits.begin(), fd.featbits.end()); +} + +int main(int argc, char *argv[]) { + if (argc < 3) { + std::cerr << "usage: correlate specfolder tiledata" << std::endl; + return 2; + } + + if (argc > 3) { + for (int i = 3; i < argc; i++) + include_tts.insert(argv[i]); + } + + for (const auto &entry : fs::directory_iterator(argv[1])) { + auto p = entry.path(); + if (p.extension() != ".features") + continue; + std::ifstream tilebits(p.parent_path().string() + "/" + p.stem().string() + ".tbits"); + if (!tilebits) { + std::cerr << "Failed to open " << (p.parent_path().string() + "/" + p.stem().string() + ".tbits") << std::endl; + return 1; + } + parse_bits(p.stem().string(), tilebits); + std::ifstream features(p.string()); + if (!features) { + std::cerr << "Failed to open " << p.string() << std::endl; + return 1; + } + parse_features(p.stem().string(), features); + } + + + + for (auto &tiletype : tiletypes) { + auto &t = tiletype.second; + std::ofstream td(std::string(argv[2]) + "/" + tiletype.first + ".bits"); + find_feature_deps(tiletype.second); + std::vector<std::string> ord_feats(t.extant_features.begin(), + t.extant_features.end()); + std::stable_sort(ord_feats.begin(), ord_feats.end(), [&](const std::string &a, const std::string &b) { + return t.features[a].deps.size() < t.features[b].deps.size(); + }); + + for (auto &feat : ord_feats) { + std::cerr << "Processing " << tiletype.first << "." << feat << std::endl; + FeatureData fd; + process_feature(t, feat); + } + + for (auto &feat : t.extant_features) { + auto &fd = t.features[feat]; + if (fd.count < 2) + continue; + td << feat; + for (auto &fb : fd.featbits) + td << " " << (fb.second ? "!" : "") << fb.first; + td << " # count: " << fd.count; + if (fd.deps.size() > 0) { + td << ", deps: "; + for (auto &d : fd.deps) + td << " " << d; + } + td << std::endl; + } + } + + return 0; +} \ No newline at end of file
diff --git a/tools/dump_bitstream.cpp b/tools/dump_bitstream.cpp new file mode 100644 index 0000000..c1b3689 --- /dev/null +++ b/tools/dump_bitstream.cpp
@@ -0,0 +1,278 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <vector> +#include <iostream> +#include <map> +#include <string> +#include <fstream> +#include <stdexcept> +#include <iterator> +#include <stdarg.h> +#include <iomanip> +#include "common.h" + +const uint32_t preamble = 0xAA995566; + +#define SKIP_CRC +#define SKIP_CHECKSUM +#define SKIP_COMMENT + +class dummy_ostream : public std::ostream { + +}; + +dummy_ostream dummy_out; + +bool verbose_flag = false; + +#define COMMENT(x) (verbose_flag ? std::cout : dummy_out) << x << std::endl + + +struct ByteStreamReader { + std::vector<uint8_t> data; + std::size_t ptr = 0; + void reset() { + ptr = 0; + } + bool done() { + return ptr >= (data.size() - 3); + } + uint32_t curr_crc = 0; + uint32_t curr_addr = 0; + + uint32_t next_u32(bool skip_crc = false) { + if (done()) + throw std::runtime_error("at end of bitstream"); + uint32_t val = data[ptr] << 24UL | data[ptr+1] << 16UL | data[ptr+2] << 8UL | data[ptr+3]; + ptr += 4; + if (!skip_crc) + curr_crc = icap_crc(curr_addr, val, curr_crc); + return val; + } + + uint32_t peek_u32() { + if (done()) + throw std::runtime_error("at end of bitstream"); + uint32_t val = data[ptr] << 24UL | data[ptr+1] << 16UL | data[ptr+2] << 8UL | data[ptr+3]; + return val; + } + void skip_till_preamble() { + while (peek_u32() != preamble) + ++ptr; + COMMENT("# found preamble at offset " << ptr); + ptr += 4; + } +}; + + + +enum BitstreamRegister : uint16_t { + #define X(a, b) a = b, + #include "registers.inc" + #undef X +}; + + + +std::string get_register_name(uint16_t val) { + BitstreamRegister r = (BitstreamRegister)val; + #define X(a, b) if (val == a) return #a; + #include "registers.inc" + #undef X + return stringf("reg%04x", val); +} + +std::map<uint32_t, uint32_t> next_frame; + +void parse_bitstream(ByteStreamReader &rd) { + rd.reset(); + rd.skip_till_preamble(); + uint32_t frame = 0; + uint16_t last_reg = 0; + uint64_t checksum = 0, exp_checksum = 0; + int word = 0; + auto is_checksum = [] (int w, int b) { + return ((w == 45 && b <= 31) || (w == 46 && b <= 15)); + }; + + auto get_ecc_value = [](int word, int bit) { + int nib = bit / 4; + int nibbit = bit % 4; + // ECC offset is expanded to 1 bit per nibble, + // and then shifted based on the bit index in nibble + // e.g. word 3, bit 9 + // offset: 0b10100110010 - concatenate (3 + (255 - 92)) [frame offset] and 9/4 [nibble offset] + // becomes: 0x10100110010 + // shifted by bit in nibble (9%4): 0x20200220020 + uint32_t offset = (word + (255 - 92)) << 3 | nib; + uint64_t exp_offset = 0; + // Odd parity + offset ^= (1 << 11); + for (int i = 0; i < 11; i++) + if (offset & (1 << i)) offset ^= (1 << 11); + // Expansion + for (int i = 0; i < 12; i++) + if (offset & (1 << i)) exp_offset |= (1ULL << (4 * i)); + return exp_offset << nibbit; + }; + + auto process_word = [&](uint32_t data) { + + + for (int i = 0; i < 32; i++) + if (data & (1 << i)) { + if (is_checksum(word, i)) { + checksum |= 1ULL << ((word - 45) * 32 + i); +#ifdef SKIP_CHECKSUM + continue; +#endif + } else { + exp_checksum ^= get_ecc_value(word, i); + } + std::cout << stringf("F0x%08xW%03dB%02d", frame, word, i) << std::endl; + } + ++word; + if (word >= 93 && next_frame.count(frame)) { + // 4 parity bits for each bit in nibbles +#if 0 + for (int i = 0; i < 4; i++) + for (int j = 0; j < 11; j++) + if (exp_checksum & (1ULL << (4 * j + i))) + exp_checksum ^= (1ULL << (44 + i)); +#endif + COMMENT(stringf("# checksum: 0x%012llX calc: 0x%012llX %s", checksum, exp_checksum, (checksum == exp_checksum) ? "" : "~~~~~")); + checksum = 0; + exp_checksum = 0; + frame = next_frame.at(frame); + } + }; + + while (!rd.done()) { + uint32_t hdr = rd.next_u32(true); + if (hdr == 0xFFFFFFFF) { + COMMENT("# desync"); + rd.skip_till_preamble(); + continue; + } + uint8_t type = (hdr >> 29) & 0x07; + if (type == 0b001) { + // Type 1 (short) packet + uint8_t op = (hdr >> 27) & 0x03; + switch(op) { + case 0x00: + COMMENT("# NOP "); + // NOP + break; + case 0x01: + // READ + break; + case 0x02: { + // WRITE + uint16_t reg = (hdr >> 13) & 0x3FFF; + rd.curr_addr = reg; + last_reg = reg; + int count = hdr & 0x3FF; + COMMENT("# write " << get_register_name(reg)); + if (reg == FAR) { + if (count != 1) + COMMENT("# bad FAR length " << count); + exp_checksum = 0; + checksum = 0; + frame = rd.next_u32(); + word = 0; + COMMENT(stringf("# frame 0x%08x", frame)); + } else if (reg == CRC) { + uint32_t crc = 0; + for(int i = 0; i < count; i++) + crc = rd.next_u32(true); + COMMENT(stringf("# CRC written=%08x calc=%08x %s", crc, rd.curr_crc, (crc == rd.curr_crc) ? "" : "*****")); + rd.curr_crc = 0; + } else if (reg == FDRI) { + for(int i = 0; i < count; i++) + process_word(rd.next_u32()); + } else if (reg == CMD) { + uint32_t cmd = 0; + for(int i = 0; i < count; i++) + cmd = rd.next_u32(); + COMMENT(stringf("# CMD %08x", cmd)); + if (cmd == 0x7) + rd.curr_crc = 0; + } else { + for(int i = 0; i < count; i++) + COMMENT(stringf("# data %08x", rd.next_u32())); + } + + if (reg == CRC && next_frame.count(frame)) { + exp_checksum = 0; + checksum = 0; + frame = next_frame.at(frame); + } + + } break; + } + } else if (type == 0b010) { + // Type 2 (long) packet + int count = hdr & 0x3FFFFFF; + if (last_reg == FDRI) { + for(int i = 0; i < count; i++) + process_word(rd.next_u32()); + } else { + for(int i = 0; i < count; i++) + COMMENT(stringf("# data %08x", rd.next_u32())); + } + } else { + std::cout << stringf("# unknown packet type %01x (header: %08x)", type, hdr) << std::endl; + return; + } + } +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + std::cerr << "Usage: dump_bitstream file.bit [frames.txt] [verbose]" << std::endl; + return 2; + } + + if (argc > 2) { + std::ifstream frame_db(argv[2]); + bool had_last = false; + uint32_t last; + uint32_t val; + frame_db.unsetf(std::ios::dec); + frame_db.unsetf(std::ios::hex); + frame_db.unsetf(std::ios::oct); + while (frame_db >> val) { + if (had_last) + next_frame[last] = val; + last = val; + had_last = true; + } + } + + if (argc > 3) { + if (std::string(argv[3]) == "verbose") + verbose_flag = true; + } + + ByteStreamReader rd; + std::ifstream file(argv[1], std::ios::binary); + file.unsetf(std::ios::skipws); + if (!file) { + std::cerr << "Failed to open input file" << std::endl; + return 2; + } + rd.data.insert(rd.data.begin(), std::istream_iterator<uint8_t>(file), std::istream_iterator<uint8_t>()); + parse_bitstream(rd); +} \ No newline at end of file
diff --git a/tools/explain.cpp b/tools/explain.cpp new file mode 100644 index 0000000..acc1d07 --- /dev/null +++ b/tools/explain.cpp
@@ -0,0 +1,146 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <vector> +#include <iostream> +#include <map> +#include <string> +#include <fstream> +#include <stdexcept> +#include <iterator> +#include <stdarg.h> +#include <iomanip> +#include <filesystem> +#include <map> +#include <set> +#include <cassert> +#include "common.h" + +ChipData chip; + +struct Tile { + std::string name, type; + TileInstance *data; + std::set<int> set_bits; + std::set<int> unknown_bits; + std::set<std::string> matched_features; +}; + +std::vector<Tile> tiles; +std::unordered_map<std::string, int> tile_by_name; + +struct InverseTileBitMap { + int tile; + int offset_in_frame; + int offset_in_tile; + int size; +}; + +std::unordered_map<uint32_t, std::vector<InverseTileBitMap>> tiles_by_frame; + +void parse_bits(const std::string &filename) { + LineReader rd(filename); + for (auto &line : rd) { + assert(line.at(0) == 'F'); + const char *curr = line.c_str() + 1; + char *next = nullptr; + uint32_t frame = std::strtoul(curr, &next, 16); + assert(*next == 'W'); + curr = next + 1; + int word = std::strtol(curr, &next, 10); + curr = next + 1; + assert(*next == 'B'); + int bit = std::strtol(curr, &next, 10); + if (tiles_by_frame.count(frame)) { + int fb = word * 32 + bit; + for (auto &t : tiles_by_frame.at(frame)) { + if (fb >= t.offset_in_frame && fb < (t.offset_in_frame + t.size)) { + int tilebit = (fb - t.offset_in_frame) + t.offset_in_tile; + tiles[t.tile].set_bits.insert(tilebit); + tiles[t.tile].unknown_bits.insert(tilebit); + } + } + } + } +} + +// Currently have poor quality DBs for these tiles, +// skip outputting them +std::set<std::string> skip_tiles = { + "CLEL_L", "CLEM_R", "RCLK_INT_R", +}; + + +void setup_tiles() { + for (auto &tile : chip.tiles) { + auto &ti = tile.second; + if (skip_tiles.count(chip.tiletypes[ti.type].type)) + continue; + Tile t; + t.name = ti.name; + t.type = chip.tiletypes[ti.type].type; + t.data = &ti; + tile_by_name[ti.name] = int(tiles.size()); + + int off = 0; + for (auto &b : ti.bits) { + tiles_by_frame[b.frame_offset].push_back(InverseTileBitMap{int(tiles.size()), b.bit_offset, off, b.size}); + off += b.size; + } + + tiles.push_back(t); + + } +} + + +void process_tile(Tile &t) { + if (t.set_bits.empty()) + return; + auto &td = chip.load_tile_database(t.name); + for (const auto &feat : td.features) { + if (feat.second.empty()) + continue; + bool matched = true; + for (auto bit : feat.second) + if (!t.set_bits.count(bit)) { + matched = false; + break; + } + if (!matched) + continue; + t.matched_features.insert(feat.first); + for (auto bit : feat.second) + t.unknown_bits.erase(bit); + } +} + +int main(int argc, char *argv[]) { + if (argc < 3) { + std::cerr << "usage: explain dbdir/ bitstream.dump" << std::endl; + return 2; + } + chip.open(argv[1]); + setup_tiles(); + parse_bits(argv[2]); + for (auto &t : tiles) { + process_tile(t); + for (auto &f : t.matched_features) + std::cout << t.name << "." << f << std::endl; + for (auto b : t.unknown_bits) + std::cout << t.name << ".?" << b << std::endl; + if (!t.matched_features.empty() || !t.unknown_bits.empty()) + std::cout << std::endl; + } +} \ No newline at end of file
diff --git a/tools/filter.py b/tools/filter.py new file mode 100644 index 0000000..8776311 --- /dev/null +++ b/tools/filter.py
@@ -0,0 +1,30 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json + +line_re = re.compile(r'F(0x[0-9A-Fa-f]+)W(\d+)B(\d+)') +frames_to_tiles = {} # (start, size, tile, tile offset) + +active = False + +with open(sys.argv[1]) as f: + for line in f: + sl = line.strip() + if sl[0] == '.': + active = sys.argv[2] in sl + if active: + print(sl) \ No newline at end of file
diff --git a/tools/frames.py b/tools/frames.py new file mode 100644 index 0000000..8265cb3 --- /dev/null +++ b/tools/frames.py
@@ -0,0 +1,37 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys + +line_re = re.compile(r'F(0x[0-9A-Fa-f]+).*') + +outlines = set() + +with open(sys.argv[1], 'r') as f: + for line in f: + m = line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + minor = frame & 0xFF + outlines.add("F=%08x B=%d H=%d R=%03d C=%04d M=%03d" + % (frame, bus, half, row, col, minor)) + +for o in sorted(outlines): + print(o)
diff --git a/tools/frames_2.py b/tools/frames_2.py new file mode 100644 index 0000000..0fe5890 --- /dev/null +++ b/tools/frames_2.py
@@ -0,0 +1,37 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys + +line_re = re.compile(r'0x([0-9A-Fa-f]+).*') + +outlines = set() + +with open(sys.argv[1], 'r') as f: + for line in f: + m = line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + minor = frame & 0xFF + outlines.add("F=%08x B=%d H=%d R=%03d C=%04d M=%03d" + % (frame, bus, half, row, col, minor)) + +for o in sorted(outlines): + print(o)
diff --git a/tools/ll.py b/tools/ll.py new file mode 100644 index 0000000..f65beb9 --- /dev/null +++ b/tools/ll.py
@@ -0,0 +1,38 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys + +line_re = re.compile(r'Bit\s+\d+\s+(0x[0-9A-Fa-f]+)\s+\d+\s+SLR\d\s+\d+\s+Block=([A-Za-z0-9_]+).*') + +outlines = set() + +with open(sys.argv[1], 'r') as f: + for line in f: + m = line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + site = m.group(2) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + minor = frame & 0xFF + outlines.add("F=%08x B=%d H=%d R=%03d C=%04d M=%03d %s" + % (frame, bus, half, row, col, minor, site)) + +for o in sorted(outlines): + print(o)
diff --git a/tools/oddtiles.py b/tools/oddtiles.py new file mode 100644 index 0000000..82451cf --- /dev/null +++ b/tools/oddtiles.py
@@ -0,0 +1,58 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json + +line_re = re.compile(r'F(0x[0-9A-Fa-f]+)W(\d+)B(\d+)') +frames_to_tiles = {} # (start, size, tile, tile offset) + +with open(sys.argv[1]) as tb_f: + tbj = json.load(tb_f) + +for tilename, tiledata in tbj.items(): + tile_offset = 0 + for chunk in tiledata: + frame, start, size = chunk + if frame not in frames_to_tiles: + frames_to_tiles[frame] = [] + frames_to_tiles[frame].append((start, size, tilename, tile_offset)) + tile_offset += size + +tile_bits = {} + +with open(sys.argv[2]) as df: + for line in df: + m = line_re.match(line) + if not m: + continue + frame = int(m[1], 16) + if frame not in frames_to_tiles: + continue + framebit = int(m[2]) * 32 + int(m[3]) + for fb in frames_to_tiles[frame]: + start, size, tile, toff = fb + if framebit > start and framebit < (start + size): + if tile not in tile_bits: + tile_bits[tile] = set() + tile_bits[tile].add(toff + (framebit - start)) + +for tile, bits in sorted(tile_bits.items()): + if "CLE" in tile: + if 152 not in bits: + print(tile) + if "INT" in tile: + if 3640 not in bits: + print(tile) \ No newline at end of file
diff --git a/tools/registers.inc b/tools/registers.inc new file mode 100644 index 0000000..0f0c8d8 --- /dev/null +++ b/tools/registers.inc
@@ -0,0 +1,20 @@ +X(CRC , 0b00000) +X(FAR , 0b00001) +X(FDRI , 0b00010) +X(FDRO , 0b00011) +X(CMD , 0b00100) +X(CTL0 , 0b00101) +X(MASK , 0b00110) +X(STAT , 0b00111) +X(LOUT , 0b01000) +X(COR0 , 0b01001) +X(MFWR , 0b01010) +X(CBC , 0b01011) +X(IDCODE , 0b01100) +X(AXSS , 0b01101) +X(COR1 , 0b01110) +X(WBSTAR , 0b10000) +X(TIMER , 0b10001) +X(BOOTSTS, 0b10110) +X(CTL1 , 0b11000) +X(BSPI , 0b11111) \ No newline at end of file
diff --git a/tools/roi.py b/tools/roi.py new file mode 100644 index 0000000..e1b217a --- /dev/null +++ b/tools/roi.py
@@ -0,0 +1,78 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json +# Usage: tilegrid.json +with open(sys.argv[1]) as tb_f: + tbj = json.load(tb_f) +tile_to_frames = {} +frame_to_tiles = {} +for tilename, tiledata in tbj.items(): + tn = tilename.split(":")[0] + tile_offset = 0 + tile_to_frames[tn] = [] + for chunk in tiledata: + frame, start, size = chunk + tile_to_frames[tn].append(frame) + if frame not in frame_to_tiles: + frame_to_tiles[frame] = [] + frame_to_tiles[frame].append(tn) +basis_tiles = [ + "CLEM_X41Y120", + "INT_X41Y120", + "CLEL_R_X41Y120", + "BRAM_X42Y120", + "INT_INTF_L_X42Y120", + "INT_X42Y120", + "CLEL_R_X42Y120", + "CLEM_X43Y120", + "INT_X43Y120", + "INT_INTF_R_X43Y120", + "DSP_X43Y120", + "CLEM_X44Y120", + "INT_X44Y120", + "CLEL_R_X44Y120", + "CLEM_X45Y120", + "INT_X45Y120", + "INT_INTF_R_X45Y120", + "DSP_X45Y120", + "CLEM_X46Y120", + "INT_X46Y120", + "CLEL_R_X46Y120", + "INT_X47Y120", + "CLEL_R_X47Y120" +] + +roi_frames = set() + +for tile in basis_tiles: + if tile not in tile_to_frames: + continue + for frame in tile_to_frames[tile]: + roi_frames.add(frame) + +roi_tiles = set() +for frame in roi_frames: + for tile in frame_to_tiles[frame]: + roi_tiles.add(tile) + +with open(sys.argv[2], "w") as frames_f: + for frame in sorted(roi_frames): + print("0x%08x" % frame, file=frames_f) + +with open(sys.argv[3], "w") as tiles_f: + for tile in sorted(roi_tiles): + print("tile %s" % tile, file=tiles_f) \ No newline at end of file
diff --git a/tools/stripdb.cpp b/tools/stripdb.cpp new file mode 100644 index 0000000..01ff1ab --- /dev/null +++ b/tools/stripdb.cpp
@@ -0,0 +1,104 @@ +// Copyright 2020 Project U-Ray Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <vector> +#include <iostream> +#include <map> +#include <string> +#include <fstream> +#include <stdexcept> +#include <iterator> +#include <stdarg.h> +#include <iomanip> +#include <filesystem> +#include <map> +#include <set> + +namespace fs = std::filesystem; + + +struct TileType { + std::map<std::string, std::vector<int>> features; +}; + +std::map<std::string, TileType> tiletypes; + + +void parse_database(const std::string &name, std::istream &in) { + std::string line; + while (std::getline(in, line)) { + auto cpos = line.find('#'); + if (cpos != std::string::npos) + line = line.substr(0, cpos); + if (line.empty()) + continue; + std::istringstream iss(line); + std::string featname; + iss >> featname; + if (featname.empty()) + continue; + tiletypes[name].features[featname]; + int bit = -1; + iss >> bit; + while (bit != -1) { + tiletypes[name].features[featname].push_back(bit); + bit = -1; + iss >> bit; + } + } +} + + +int main(int argc, char *argv[]) { + if (argc < 3) { + std::cerr << "usage: stripdb in/ out/" << std::endl; + return 2; + } + + // Currently have poor quality DBs for these tiles, + // skip outputting them + std::set<std::string> skip_tiles = { + "CLEL_L", "CLEM_R", "RCLK_INT_R", + }; + + for (const auto &entry : fs::directory_iterator(argv[1])) { + auto p = entry.path(); + if (p.extension() != ".bits") + continue; + std::ifstream tiledata(p.string()); + if (skip_tiles.count(p.stem())) + continue; + parse_database(p.stem(), tiledata); + } + + // Misc cleanups + for (auto &f : tiletypes["INT"].features) + if (f.first.find(".VCC_WIRE") != std::string::npos) + f.second.clear(); + + for (const auto &tt : tiletypes) { + if(tt.second.features.empty()) + continue; + std::string dbname = std::string(argv[2]) + "/" + tt.first + ".bits"; + std::ofstream out(dbname); + if (!out) + std::cerr << "failed to open " << dbname << " for writing." << std::endl; + for (auto &f : tt.second.features) { + out << f.first; + for (int bit : f.second) + out << " " << bit; + out << std::endl; + } + } +} \ No newline at end of file
diff --git a/tools/tilebits.py b/tools/tilebits.py new file mode 100644 index 0000000..57fbe2b --- /dev/null +++ b/tools/tilebits.py
@@ -0,0 +1,151 @@ +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import sys +import json + +tiles = {} +site_to_tile = {} +tile_to_bits = {} # (frame, bit start, bit size) + +with open(sys.argv[1], 'r') as tilef: + for line in tilef: + sl = line.strip().split(",") + if len(sl) < 4: + continue + x = int(sl[0]) + y = int(sl[1]) + name = sl[2] + ttype = sl[3] + tiles[(x, y)] = (name + ":" + ttype, ttype, []) + for site in sl[4:]: + sitename, sitetype = site.split(":") + tiles[(x, y)][2].append((sitename, sitetype)) + site_to_tile[sitename] = (x, y) + +ll_line_re = re.compile(r'Bit\s+\d+\s+(0x[0-9A-Fa-f]+)\s+(\d+)\s+SLR\d\s+\d+\s+Block=([A-Za-z0-9_]+).*') +site_re = re.compile(r'SLICE_X(\d+)Y(\d+)') +with open(sys.argv[2], 'r') as llf: + for line in llf: + m = ll_line_re.match(line) + if not m: + continue + frame = int(m.group(1), 16) + bit = int(m.group(2)) + start_bit = bit - 2 + site = m.group(3) + bus = (frame >> 24) & 0x7 + half = (frame >> 23) & 0x1 + row = (frame >> 18) & 0x1F + col = (frame >> 8) & 0x3FF + m = frame & 0xFF + + + sm = site_re.match(site) + site_x = int(sm.group(1)) + site_y = int(sm.group(2)) + frame_upper = frame & ~0xFF + + + if site not in site_to_tile: + continue + tx, ty = site_to_tile[site] + tiledata = tiles[tx, ty] + tile_to_bits[tiledata[0]] = [] + for m in range(16): + tile_to_bits[tiledata[0]].append((frame_upper | m, start_bit, 48)) + + def process_nonlogic(x, y, icol): + if (x, y) not in tiles: + return + itiledata = tiles[x, y] + if itiledata[1] == "INT": + if (x + 1, y) not in tiles: + return + + int_frame_base = (frame_upper & ~0x3FFFF) | (icol << 8) + tile_to_bits[itiledata[0]] = [] + for m in range(76): + tile_to_bits[itiledata[0]].append((int_frame_base | m, start_bit, 48)) + process_clock(x, y-1, int_frame_base, start_bit + 48, 76) + process_cmt(x-2, y, icol-2) + process_int_intf(x-1, y, icol-1) + elif itiledata[1] == "BRAM": + bram_frame_base = (frame_upper & ~0x3FFFF) | (icol << 8) + tile_to_bits[itiledata[0]] = [] + for m in range(6): + tile_to_bits[itiledata[0]].append((bram_frame_base | m, start_bit, 5 * 48)) + process_clock(x, y-5, bram_frame_base, start_bit + 5*48, 6) + elif itiledata[1] == "DSP": + dsp_frame_base = (frame_upper & ~0x3FFFF) | (icol << 8) + tile_to_bits[itiledata[0]] = [] + for m in range(8): + tile_to_bits[itiledata[0]].append((dsp_frame_base | m, start_bit, 5 * 48)) + process_clock(x, y-5, dsp_frame_base, start_bit + 5*48, 8) + + if (x - 1, y) in tiles and "INT_INTF" in tiles[x - 1, y][1]: + process_clock(x-1, y-5, dsp_frame_base, start_bit + 5*48, 8) + + def process_clock(cx, cy, frame_base, end_bit, height): + if (cx, cy) not in tiles: + return + if end_bit != (1392 + 48): + return + ctiledata = tiles[cx, cy] + if not ctiledata[1].startswith("RCLK"): + return + tile_to_bits[ctiledata[0]] = [] + for m in range(height): + tile_to_bits[ctiledata[0]].append((frame_base | m, end_bit + 48, 48)) + + def process_cmt(x, y, icol): + if (x, y) not in tiles: + return + ctiledata = tiles[x, y] + if not ctiledata[1] in ("CMT_L", "CMT_RIGHT"): + return + cmt_frame_base = (frame_upper & ~0x3FFFF) | (icol << 8) + tile_to_bits[ctiledata[0]] = [] + for m in range(12): + tile_to_bits[ctiledata[0]].append((cmt_frame_base | m, start_bit, 60 * 48)) + + def process_int_intf(x, y, icol): + if (x, y) not in tiles: + return + itiledata = tiles[x, y] + if not itiledata[1] in ("INT_INTF_L_IO", "INT_INTF_R_IO"): + return + int_frame_base = (frame_upper & ~0x3FFFF) | (icol << 8) + tile_to_bits[itiledata[0]] = [] + for m in range(4): + tile_to_bits[itiledata[0]].append((int_frame_base | m, start_bit, 48)) + + + process_nonlogic(tx-1, ty, col-1) + process_nonlogic(tx+1, ty, col+1) + process_clock(tx, ty-1, frame_upper, start_bit + 48, 16) +# Original JSON +with open(sys.argv[3], 'w') as tj: + tj.write(json.dumps(tile_to_bits, sort_keys=True, indent=4, separators=(',', ': '))) + tj.write("\n") +# New simplified text format +with open(sys.argv[4], 'w') as tf: + for loc, tiledata in sorted(tiles.items()): + print(".tile %s %s %d %d" % (tiledata[0].split(":")[0], tiledata[1], loc[0], loc[1]), file=tf) + for site in tiledata[2]: + print("site %s %s" % site, file=tf) + if tiledata[0] in tile_to_bits: + for frame, offset, size in tile_to_bits[tiledata[0]]: + print("frame 0x%08x bits %d +: %d" % (frame, offset, size), file=tf) \ No newline at end of file
diff --git a/tools/update_tilebits_all.sh b/tools/update_tilebits_all.sh new file mode 100644 index 0000000..0596c19 --- /dev/null +++ b/tools/update_tilebits_all.sh
@@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Copyright 2020 Project U-Ray Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +for x in $1/*.dump; do + python bits_to_tiles.py $2 $x > ${x%.*}.tbits +done