Commit 0b49e00e by Ravi Varadarajan

Merge branch 'main' of github.com:TILOS-AI-Institute/MacroPlacement into main

Signed-off-by: Ravi Varadarajan <rvaradarajan@ucsd.edu>
parents c4759ced 8d272bb1
Flows/*/*/run/*/
\ No newline at end of file
# Placement-guided hypergraph clustering (soft macro definition)
**Placement-guided hypergraph clustering (soft macro defintion)**
cluster millions of standard cells into a few thousand clusters.
It takes synthesized netlist and def file with placed IO pins as input,
then generates clustered netlist (in lef/def format) using hMETIS (1998 binary).
In default mode, it will also run RePlAce in GUI mode automatically to place
the clustered netlist. We implement the flow based on [**OpenROAD APIs**](https://github.com/The-OpenROAD-Project/OpenROAD).
Please refer to [**the OpenROAD repo**](https://github.com/The-OpenROAD-Project/OpenROAD) for explanation of each Tcl command.
We have provided the openroad exe in the [**utils**](./utils/) dir.
# **Hypergraph clustering (soft macro definition)**
**Hypergraph clustering** is, in our view, one of the most crucial undocumented
portions of Circuit Training.
## **I. Information provided by Google.**
The Methods section of the [Nature paper](https://www.nature.com/articles/s41586-021-03544-w.epdf?sharing_token=tYaxh2mR5EozfsSL0WHZLdRgN0jAjWel9jnR3ZoTv0PW0K0NmVrRsFPaMa9Y5We9O4Hqf_liatg-lvhiVcYpHL_YQpqkurA31sxqtmA-E1yNUWVMMVSBxWSp7ZFFIWawYQYnEXoBE4esRDSWqubhDFWUPyI5wK_5B_YIO-D_kS8%3D) provides the following information.
* “(1) We group millions of standard cells into a few thousand clusters using hMETIS, a partitioning technique based
on the minimum cut objective. Once all macros are placed, we use an FD method to place the standard cell clusters.
Doing so enables us to generate an approximate but fast standard cell placement that facilitates policy network optimization.”
* **“Clustering of standard cells.** To quickly place standard cells to provide a signal to our RL policy,
we first cluster millions of standard cells into a few thousand clusters.
There has been a large body of work on clustering for chip netlists.
As has been suggested in the literature, such clustering helps not only with reducing the problem size,
but also helps to ‘prevent mistakes’ (for example, prevents timing paths from being split apart).
We also provide the clustered netlist to each of the baseline methods with which we compare.
To perform this clustering, we employed a standard open-source library, hMETIS,
which is based on multilevel hypergraph partitioning schemes with two important phases:
(1) coarsening phase, and 2) uncoarsening and refinement phase.”
Therefore, at least one purpose of clustering is to enable fast placement of standard cells to
provide a signal to the RL policy. The Methods section subsequently explains how the clusters
are placed using a [force-directed](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/FDPlacement/README.md) approach:
* **“Placement of standard cells.** To place standard cell clusters, we use an approach similar to classic FD methods.
We represent the netlist as a system of springs that apply force to each node,
according to the weight×distance formula, causing tightly connected nodes to be attracted to one another.
We also introduce a repulsive force between overlapping nodes to reduce placement density.
After applying all forces, we move nodes in the direction of their force vector. To reduce oscillations, we set a maximum distance for each move.”
The [Circuit Training FAQ](https://github.com/google-research/circuit_training/blob/main/README.md) adds:
* **How do we perform clustering of standard cells?** In our Nature paper, we describe how to use hMETIS to cluster standard cells,
including all necessary settings. For detailed settings, please see Extended Data Table 3 from our [Nature article](https://www.nature.com/articles/s41586-021-03544-w.epdf?sharing_token=tYaxh2mR5EozfsSL0WHZLdRgN0jAjWel9jnR3ZoTv0PW0K0NmVrRsFPaMa9Y5We9O4Hqf_liatg-lvhiVcYpHL_YQpqkurA31sxqtmA-E1yNUWVMMVSBxWSp7ZFFIWawYQYnEXoBE4esRDSWqubhDFWUPyI5wK_5B_YIO-D_kS8%3D).
Internally, Google pays for a commercial license, but non-commercial entities are welcome to use a free open-source license.
Finally, the Methods section of the [Nature paper](https://www.nature.com/articles/s41586-021-03544-w.epdf?sharing_token=tYaxh2mR5EozfsSL0WHZLdRgN0jAjWel9jnR3ZoTv0PW0K0NmVrRsFPaMa9Y5We9O4Hqf_liatg-lvhiVcYpHL_YQpqkurA31sxqtmA-E1yNUWVMMVSBxWSp7ZFFIWawYQYnEXoBE4esRDSWqubhDFWUPyI5wK_5B_YIO-D_kS8%3D) also explains the provenance of the netlist hypergraph:
* **Synthesis of the input netlist.** We use a commercial tool to synthesize the netlist from RTL. Synthesis is physical-aware, in the sense that it has access to the floorplan size and the locations of the input/output pins, which were informed by inter- and intra-block-level information.
## **II. What *exactly* is the Hypergraph, and how is it partitioned?**
From the above information sources, the description of the [Grouping](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Grouping/README.md) process, and information provided by Google engineers, we are fairly certain of the following.
* (1) Clustering uses the hMETIS partitioner, which is run in “multiway” mode.
More specifically, hMETIS is **always** invoked with *nparts*=500, with unit vertex weights.
The hyperparameters given in Extended Data Table 3 of the [Nature paper](https://www.nature.com/articles/s41586-021-03544-w.epdf?sharing_token=tYaxh2mR5EozfsSL0WHZLdRgN0jAjWel9jnR3ZoTv0PW0K0NmVrRsFPaMa9Y5We9O4Hqf_liatg-lvhiVcYpHL_YQpqkurA31sxqtmA-E1yNUWVMMVSBxWSp7ZFFIWawYQYnEXoBE4esRDSWqubhDFWUPyI5wK_5B_YIO-D_kS8%3D) are used.
(Additionally, Circuit Training explicitly sets reconst=1 and dbglvl=0.)
* (2) The hypergraph that is fed to hMETIS consists **only** of standard cells and “fixed”
(i.e., specified as monolithic clusters of vertices, using the .fix input file mechanism of hMETIS) groups of standard cells.
Before going further, we provide a **concrete example** for (2).
* Suppose that we have a design with 200,000 standard cells, 100 macros, and 1,000 ports.
* Furthermore, using terms defined in [Grouping](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Grouping/README.md), suppose
that each of the 100 macros induces a *group* of 300 standard cells, and that the ports collectively induce 20 *clumps*,
each of which induces a group of 50 standard cells.
* Then, there will be 100 + 20 = 120 groups, each corresponding to an entry of the .fix file.
* The number of individual standard cells in the hypergraph that is actually partitioned by hMETIS is 200,000 - (100 * 300) - (20 * 50) = 169,000.
* Note: To our understanding, applying hMETIS with *nparts* = 500 to this hypergraph, with 120 entries in the .fix file,
will partition 169,000 standard cells into 500 - 120 = 380 clusters. All of the above understanding is in the process of being reconfirmed.
We call readers’ attention to the existence of significant aspects that are still pending clarification here.
While [Gridding](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Gridding/README.md) and
[Grouping](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Grouping/README.md) are hopefully well-understood,
we are still in the process of documenting and implementing such aspects as the following.
* ***Pending clarification #1: Is the output netlist from synthesis modified before it enters (hypergraph clustering and) placement?***
All methodologies that span synthesis and placement (of which we are aware) must make a fundamental decision with respect to the netlist that is produced by logic synthesis, as that netlist is passed on to placement: (A) delete buffers and inverters to avoid biasing the ensuing placement (spatial embedding) with the synthesis tool’s fanout clustering, or (B) leave these buffers and inverters in the netlist to maintain netlist area and electrical rules (load, fanout) sensibility. We do not yet know Google’s choice in this regard. Our experimental runscripts will therefore support both (A) and (B).
* ***Pending clarification #2: Are large nets ignored in hypergraph clustering (and hence placement)? If so, at what net size threshold?***
All hypergraph partitioning applications in physical design (of which we are aware) perform some kind of thresholding to ignore large hyperedges.
Our implementation of hypergraph clustering takes a parameter, *net_size_threshold*, and ignores all hyperedges of size greater
than or equal to *net_size_threshold*. The default value for this parameter is 300.
* ***Pending clarification #3: How does hMETIS with nparts = 500 and a nonempty .fix file create so many standard-cell clusters (soft macros)? What explains the variation in cluster area, given that hMETIS is run with UBfactor = 5?*** For example, the Ariane example data shown in Circuit Training’s [test_data](https://github.com/google-research/circuit_training/tree/main/circuit_training/environment/test_data/ariane) has 799 soft macros, although in practice Ariane synthesizes to only approximately (100K +/- 20K) standard cells along with its 133 hard macros. Furthermore, in the Circuit Training data, it is easy to see that all hard macros have identical dimensions 19.26(h) x 29.355(w), but that the 799 soft macros have dimensions in the range \[0.008 , 14.46\](h) x 10.18(w), implying areas that vary across a ~1500X range.
## **III. Our Implementation of Hypergraph Clustering.**
Our implementation of hypergraph clustering takes the synthesized netlist and a .def file with placed IO ports as input,
then generates the clustered netlist (in lef/def format) using hMETIS (1998 binary).
In default mode, our implementation will also run RePlAce in GUI mode automatically to place the clustered netlist.
We implement the entire flow based on [OpenROAD APIs](https://github.com/the-openroad-project).
**Please refer to [the OpenROAD repo](https://github.com/the-openroad-project) for explanation of each Tcl command.**
We have provided the openroad exe in the [utils](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Clustering/utils) dir. Please note that [The OpenROAD Project](https://github.com/the-openroad-project) does not
distribute any compiled binaries. While we build our implementation on top of the OpenROAD application, our effort is not associated with the OpenROAD project.
Input file: [setup.tcl](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Clustering/setup.tcl) (you can follow the example to set up your own design)
Output_files: clusters.lef and clustered_netlist.def
Example commands: python [generate_clustered_netlist.py](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Clustering/generate_clustered_netlist.py) ariane hmetis
You can use the command: python [generate_clustered_netlist.py](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Clustering/generate_clustered_netlist.py) -h for other options
Note that the [example](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Clustering/design) that we provide is the ariane design implemented in NanGate45. The netlist is synthesized by Yosys, and the floorplan def is generated by OpenROAD.
## **Thanks**
We thank Google engineers for Q&A in a shared document, as well as live discussions on May 19, 2022, that explained the hypergraph clustering method used in Circuit Training. All errors of understanding and implementation are the authors'. We will rectify such errors as soon as possible after being made aware of them.
Input file: [setup.tcl](./setup.tcl) (you can follow the example to set up your own design)
Output_files: clusters.lef and clustered_netlist.def
Example commands: python [generate_clustered_netlist.py](./generate_clustered_netlist.py) ariane hmetis
You can use command: python [generate_clustered_netlist.py](./generate_clustered_netlist.py) -h for other options
Note: In this example, we use the ariane design implemented in NanGate45.
The netlist is synthesized by Yosys, and the floorplan def is generated by
OpenROAD.
......@@ -22,6 +22,13 @@ The following cartoon was recently provided by a Google engineer to explain the
## **How Groups Are Used**
Each group is recorded in the “.fix file” that is part of the input to the hMETIS hypergraph partitioner when the gate-level netlist is clustered into soft macros.
## **How Grouping Scripts Are used**
We provide [(an example)](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Grouping/test/test.py) about the usage of our grouping scripts.
Basically our grouping scripts take follows as inputs: (i) [(setup_file)](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/Grouping/test/setup.tcl)
including enablement information (lefs/libs), synthesized gate-level netlist (*.v), def file with placed IOs (*.def); (ii) n_rows and n_cols determined by the [(Gridding)](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Gridding) step; (iii) K_in and K_out parameters; (iv) global_net_threshold for ignoring global nets. If a net has more than global_net_threshold instances, we ignore such net when we search "transitive" fanins and fanouts. After
running grouping scripts, you will get two files *.fix and *.fix.old. The ".fix.old" file contains the IOs or macros in the corresponding group while *.fix file only contains standard cells in each group.
# Thanks
We thank Google engineers for Q&A in a shared document, as well as live discussions on May 19, 2022, that explained the grouping method used in Circuit Training. All errors of understanding and implementation are the authors'. We will rectify such errors as soon as possible after being made aware of them.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
import os
import argparse
import time
import shutil
import sys
from math import floor
sys.path.append('./utils')
####################################################################################
#### Extract hypergraph, instance, IO ports and outline from netlist
####################################################################################
def GenerateHypergraph(openroad_exe, setup_file, extract_hypergraph_file):
temp_file = os.getcwd() + "/extract_hypergraph.tcl"
cmd = "cp " + setup_file + " " + temp_file
os.system(cmd)
with open(extract_hypergraph_file) as f:
content = f.read().splitlines()
f.close()
f = open(temp_file, "a")
f.write("\n")
for line in content:
f.write(line + "\n")
f.close()
cmd = openroad_exe + " " + temp_file
os.system(cmd)
cmd = "rm " + temp_file
os.system(cmd)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("design", help = "design name", type = str)
parser.add_argument("n_rows", help = "number of rows", type = int)
parser.add_argument("n_cols", help = "number of cols", type = int)
parser.add_argument("--setup_file", help = "setup file for openroad (default = setup.tcl)", type = str, default = "setup.tcl")
args = parser.parse_args()
design = args.design
n_rows = args.n_rows
n_cols = args.n_cols
setup_file = args.setup_file
pwd = os.getcwd()
# Specify the location of hmetis exe and openroad exe
openroad_exe = pwd + "/utils/openroad"
extract_hypergraph_file = pwd + "/utils/extract_hypergraph.tcl"
# Generate Hypergraph file
rpt_dir = pwd + "/rtl_mp"
hypergraph_file = rpt_dir + "/" + design + ".hgr"
io_name_file = hypergraph_file + ".io"
instance_name_file = hypergraph_file + ".instance"
outline_file = hypergraph_file + ".outline"
GenerateHypergraph(openroad_exe, setup_file, extract_hypergraph_file)
# Generate fix file
fix_file = design + ".fix"
print("[INFO] Generated fix file : ", fix_file)
# Step 1: Grouping bundled IOs based on n_rows and n_cols
with open(outline_file) as f:
content = f.read().splitlines()
f.close()
items = content[0].split()
floorplan_lx = float(items[0])
floorplan_ly = float(items[1])
floorplan_ux = float(items[2])
floorplan_uy = float(items[3])
width = (floorplan_ux - floorplan_lx) / n_cols
height = (floorplan_uy - floorplan_ly) / n_rows
group_map = { }
io_inst_map = { }
vertex_list = []
grid_row_max = 100000000
with open(io_name_file) as f:
content = f.read().splitlines()
f.close()
for line in content:
items = line.split()
io_name = items[0]
vertex_list.append(io_name)
x = (float(items[1]) + float(items[3])) / 2.0
y = (float(items[2]) + float(items[4])) / 2.0
hash_id = floor(y / height) * grid_row_max + floor(x / width)
io_inst_map[io_name] = hash_id
if hash_id not in group_map:
group_map[hash_id] = [io_name]
else:
group_map[hash_id].append(io_name)
hash_id = max(group_map.keys()) + 1
with open(instance_name_file) as f:
content = f.read().splitlines()
f.close()
for line in content:
items = line.split()
inst_name = items[0]
vertex_list.append(inst_name)
if (int(items[1]) == 1):
group_map[hash_id] = [inst_name]
io_inst_map[inst_name] = hash_id
hash_id += 1
glue_inst = { }
with open(hypergraph_file) as f:
content = f.read().splitlines()
f.close()
for i in range(1, len(content)):
items = [vertex_list[int(item) -1] for item in content[i].split()]
if(len(items) > 100):
continue
group_list = []
flag = False
for item in items:
if item in io_inst_map:
flag = True
group_list.append(item)
if (flag == True):
for item in items:
if item not in group_list:
for inst in group_list:
group_map[io_inst_map[inst]].append(item)
if item not in glue_inst:
glue_inst[item] = [inst]
else:
glue_inst[item].append(inst)
for key, value in glue_inst.items():
if(len(value) > 1):
print(value)
group_id = 0
f = open(fix_file, "w")
for key, value in group_map.items():
line = "group_" + str(group_id) + ": "
group_id += 1
for io in value:
line += io + " "
line += "\n"
f.write(line)
f.close()
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
clk_i 0 876.155 0.07 876.225
rst_ni 0 785.435 0.07 785.505
boot_addr_i[63] 0 1325.28 0.07 1325.34
boot_addr_i[62] 0 658.035 0.07 658.105
boot_addr_i[61] 0 1317.99 0.07 1318.06
boot_addr_i[60] 0 1167.07 0.07 1167.15
boot_addr_i[59] 0 1408.99 0.07 1409.06
boot_addr_i[58] 0 1041.64 0.07 1041.7
boot_addr_i[57] 0 705.355 0.07 705.425
boot_addr_i[56] 0 728.875 0.07 728.945
boot_addr_i[55] 0 1474.52 0.07 1474.58
boot_addr_i[54] 0 1370.92 0.07 1370.98
boot_addr_i[53] 0 825.475 0.07 825.545
boot_addr_i[52] 0 1210.76 0.07 1210.82
boot_addr_i[51] 0 1309.04 0.07 1309.1
boot_addr_i[50] 0 701.715 0.07 701.785
boot_addr_i[49] 0 945.315 0.07 945.385
boot_addr_i[48] 0 1272.64 0.07 1272.7
boot_addr_i[47] 0 1190.88 0.07 1190.94
boot_addr_i[46] 0 1121.71 0.07 1121.79
boot_addr_i[45] 0 1349.07 0.07 1349.15
boot_addr_i[44] 0 1103.52 0.07 1103.58
boot_addr_i[43] 0 1090.92 0.07 1090.98
boot_addr_i[42] 0 763.595 0.07 763.665
boot_addr_i[41] 0 1478.16 0.07 1478.22
boot_addr_i[40] 0 610.715 0.07 610.785
boot_addr_i[39] 0 947.275 0.07 947.345
boot_addr_i[38] 0 1179.95 0.07 1180.03
boot_addr_i[37] 0 832.755 0.07 832.825
boot_addr_i[36] 0 1219.99 0.07 1220.06
boot_addr_i[35] 0 867.195 0.07 867.265
boot_addr_i[34] 0 609.035 0.07 609.105
boot_addr_i[33] 0 1079.99 0.07 1080.06
boot_addr_i[32] 0 990.675 0.07 990.745
boot_addr_i[31] 0 856.275 0.07 856.345
boot_addr_i[30] 0 768.915 0.07 768.985
boot_addr_i[29] 0 1105.47 0.07 1105.55
boot_addr_i[28] 0 1365.31 0.07 1365.39
boot_addr_i[27] 0 1141.59 0.07 1141.67
boot_addr_i[26] 0 1468.92 0.07 1468.98
boot_addr_i[25] 0 840.035 0.07 840.105
boot_addr_i[24] 0 1277.95 0.07 1278.03
boot_addr_i[23] 0 923.475 0.07 923.545
boot_addr_i[22] 0 1236.23 0.07 1236.31
boot_addr_i[21] 0 992.635 0.07 992.705
boot_addr_i[20] 0 1316.31 0.07 1316.39
boot_addr_i[19] 0 941.675 0.07 941.745
boot_addr_i[18] 0 807.275 0.07 807.345
boot_addr_i[17] 0 681.835 0.07 681.905
boot_addr_i[16] 0 854.595 0.07 854.665
boot_addr_i[15] 0 1312.68 0.07 1312.74
boot_addr_i[14] 0 1096.23 0.07 1096.31
boot_addr_i[13] 0 641.795 0.07 641.865
boot_addr_i[12] 0 741.755 0.07 741.825
boot_addr_i[11] 0 1407.04 0.07 1407.1
boot_addr_i[10] 0 1305.4 0.07 1305.46
boot_addr_i[9] 0 1203.47 0.07 1203.55
boot_addr_i[8] 0 1267.04 0.07 1267.1
boot_addr_i[7] 0 1489.07 0.07 1489.15
boot_addr_i[6] 0 1425.23 0.07 1425.31
boot_addr_i[5] 0 983.675 0.07 983.745
boot_addr_i[4] 0 1012.52 0.07 1012.59
boot_addr_i[3] 0 897.995 0.07 898.065
boot_addr_i[2] 0 1439.8 0.07 1439.86
boot_addr_i[1] 0 1136.28 0.07 1136.34
boot_addr_i[0] 0 974.435 0.07 974.505
hart_id_i[63] 0 1107.16 0.07 1107.22
hart_id_i[62] 0 616.315 0.07 616.385
hart_id_i[61] 0 1412.64 0.07 1412.7
hart_id_i[60] 0 1449.04 0.07 1449.1
hart_id_i[59] 0 743.435 0.07 743.505
hart_id_i[58] 0 1209.07 0.07 1209.15
hart_id_i[57] 0 978.075 0.07 978.145
hart_id_i[56] 0 1376.23 0.07 1376.31
hart_id_i[55] 0 887.075 0.07 887.145
hart_id_i[54] 0 938.035 0.07 938.105
hart_id_i[53] 0 1483.47 0.07 1483.55
hart_id_i[52] 0 1452.68 0.07 1452.74
hart_id_i[51] 0 667.275 0.07 667.345
hart_id_i[50] 0 881.755 0.07 881.825
hart_id_i[49] 0 698.075 0.07 698.145
hart_id_i[48] 0 1319.95 0.07 1320.03
hart_id_i[47] 0 1499.71 0.07 1499.79
hart_id_i[46] 0 1347.11 0.07 1347.19
hart_id_i[45] 0 659.995 0.07 660.065
hart_id_i[44] 0 1345.44 0.07 1345.51
hart_id_i[43] 0 980.035 0.07 980.105
hart_id_i[42] 0 1245.19 0.07 1245.27
hart_id_i[41] 0 987.035 0.07 987.105
hart_id_i[40] 0 1061.8 0.07 1061.86
hart_id_i[39] 0 1139.92 0.07 1139.98
hart_id_i[38] 0 1481.8 0.07 1481.86
hart_id_i[37] 0 1258.07 0.07 1258.15
hart_id_i[36] 0 1065.44 0.07 1065.51
hart_id_i[35] 0 994.315 0.07 994.385
hart_id_i[34] 0 1170.71 0.07 1170.79
hart_id_i[33] 0 1385.19 0.07 1385.27
hart_id_i[32] 0 1461.64 0.07 1461.7
hart_id_i[31] 0 1261.71 0.07 1261.79
hart_id_i[30] 0 703.675 0.07 703.745
hart_id_i[29] 0 1310.71 0.07 1310.79
hart_id_i[28] 0 1130.68 0.07 1130.74
hart_id_i[27] 0 1427.19 0.07 1427.27
hart_id_i[26] 0 865.235 0.07 865.305
hart_id_i[25] 0 1001.59 0.07 1001.66
hart_id_i[24] 0 1339.83 0.07 1339.91
hart_id_i[23] 0 1192.56 0.07 1192.62
hart_id_i[22] 0 1088.95 0.07 1089.03
hart_id_i[21] 0 714.595 0.07 714.665
hart_id_i[20] 0 1027.07 0.07 1027.15
hart_id_i[19] 0 1463.59 0.07 1463.67
hart_id_i[18] 0 819.875 0.07 819.945
hart_id_i[17] 0 1019.79 0.07 1019.86
hart_id_i[16] 0 963.515 0.07 963.585
hart_id_i[15] 0 1367.28 0.07 1367.34
hart_id_i[14] 0 1147.19 0.07 1147.27
hart_id_i[13] 0 623.595 0.07 623.665
hart_id_i[12] 0 1490.76 0.07 1490.82
hart_id_i[11] 0 759.955 0.07 760.025
hart_id_i[10] 0 767.235 0.07 767.305
hart_id_i[9] 0 805.315 0.07 805.385
hart_id_i[8] 0 969.115 0.07 969.185
hart_id_i[7] 0 970.795 0.07 970.865
hart_id_i[6] 0 1363.64 0.07 1363.7
hart_id_i[5] 0 1098.19 0.07 1098.27
hart_id_i[4] 0 787.115 0.07 787.185
hart_id_i[3] 0 1494.4 0.07 1494.46
hart_id_i[2] 0 1201.8 0.07 1201.86
hart_id_i[1] 0 1128.99 0.07 1129.06
hart_id_i[0] 0 750.715 0.07 750.785
irq_i[1] 0 649.075 0.07 649.145
irq_i[0] 0 1336.19 0.07 1336.27
ipi_i 0 847.315 0.07 847.385
time_irq_i 0 1163.44 0.07 1163.51
debug_req_i 0 672.595 0.07 672.665
axi_req_o[277] 0 689.115 0.07 689.185
axi_req_o[276] 0 1050.88 0.07 1050.94
axi_req_o[275] 0 1177.99 0.07 1178.06
axi_req_o[274] 0 1132.64 0.07 1132.7
axi_req_o[273] 0 1416.28 0.07 1416.34
axi_req_o[272] 0 959.875 0.07 959.945
axi_req_o[271] 0 934.395 0.07 934.465
axi_req_o[270] 0 814.555 0.07 814.625
axi_req_o[269] 0 652.715 0.07 652.785
axi_req_o[268] 0 1165.4 0.07 1165.46
axi_req_o[267] 0 1314.35 0.07 1314.43
axi_req_o[266] 0 1005.23 0.07 1005.3
axi_req_o[265] 0 899.955 0.07 900.025
axi_req_o[264] 0 1148.88 0.07 1148.94
axi_req_o[263] 0 765.275 0.07 765.345
axi_req_o[262] 0 1250.8 0.07 1250.86
axi_req_o[261] 0 1379.88 0.07 1379.94
axi_req_o[260] 0 1423.56 0.07 1423.62
axi_req_o[259] 0 954.555 0.07 954.625
axi_req_o[258] 0 1243.52 0.07 1243.58
axi_req_o[257] 0 1383.52 0.07 1383.58
axi_req_o[256] 0 1352.71 0.07 1352.79
axi_req_o[255] 0 627.235 0.07 627.305
axi_req_o[254] 0 1016.16 0.07 1016.22
axi_req_o[253] 0 1029.04 0.07 1029.1
axi_req_o[252] 0 1145.23 0.07 1145.31
axi_req_o[251] 0 607.075 0.07 607.145
axi_req_o[250] 0 1172.68 0.07 1172.74
axi_req_o[249] 0 1259.76 0.07 1259.82
axi_req_o[248] 0 1196.19 0.07 1196.27
axi_req_o[247] 0 1456.31 0.07 1456.39
axi_req_o[246] 0 1112.76 0.07 1112.82
axi_req_o[245] 0 1137.95 0.07 1138.03
axi_req_o[244] 0 1063.47 0.07 1063.55
axi_req_o[243] 0 1298.11 0.07 1298.19
axi_req_o[242] 0 1134.31 0.07 1134.39
axi_req_o[241] 0 1254.44 0.07 1254.51
axi_req_o[240] 0 1158.11 0.07 1158.19
axi_req_o[239] 0 910.875 0.07 910.945
axi_req_o[238] 0 956.235 0.07 956.305
axi_req_o[237] 0 1496.35 0.07 1496.43
axi_req_o[236] 0 770.875 0.07 770.945
axi_req_o[235] 0 1085.31 0.07 1085.39
axi_req_o[234] 0 943.635 0.07 943.705
axi_req_o[233] 0 1221.68 0.07 1221.74
axi_req_o[232] 0 1078.04 0.07 1078.1
axi_req_o[231] 0 1328.92 0.07 1328.98
axi_req_o[230] 0 676.235 0.07 676.305
axi_req_o[229] 0 1214.4 0.07 1214.46
axi_req_o[228] 0 1074.4 0.07 1074.46
axi_req_o[227] 0 872.515 0.07 872.585
axi_req_o[226] 0 1143.56 0.07 1143.62
axi_req_o[225] 0 1092.59 0.07 1092.67
axi_req_o[224] 0 1152.52 0.07 1152.58
axi_req_o[223] 0 836.395 0.07 836.465
axi_req_o[222] 0 1467.23 0.07 1467.31
axi_req_o[221] 0 972.755 0.07 972.825
axi_req_o[220] 0 1150.83 0.07 1150.91
axi_req_o[219] 0 1198.16 0.07 1198.22
axi_req_o[218] 0 1003.55 0.07 1003.62
axi_req_o[217] 0 1119.76 0.07 1119.82
axi_req_o[216] 0 852.635 0.07 852.705
axi_req_o[215] 0 1076.35 0.07 1076.43
axi_req_o[214] 0 1008.88 0.07 1008.95
axi_req_o[213] 0 961.835 0.07 961.905
axi_req_o[212] 0 1018.11 0.07 1018.18
axi_req_o[211] 0 1207.11 0.07 1207.19
axi_req_o[210] 0 997.955 0.07 998.025
axi_req_o[209] 0 1283.56 0.07 1283.62
axi_req_o[208] 0 921.795 0.07 921.865
axi_req_o[207] 0 1083.64 0.07 1083.7
axi_req_o[206] 0 674.555 0.07 674.625
axi_req_o[205] 0 1030.71 0.07 1030.79
axi_req_o[204] 0 803.635 0.07 803.705
axi_req_o[203] 0 685.475 0.07 685.545
axi_req_o[202] 0 1059.83 0.07 1059.91
axi_req_o[201] 0 1299.8 0.07 1299.86
axi_req_o[200] 0 630.875 0.07 630.945
axi_req_o[199] 0 1323.59 0.07 1323.67
axi_req_o[198] 0 868.875 0.07 868.945
axi_req_o[197] 0 903.595 0.07 903.665
axi_req_o[196] 0 1434.47 0.07 1434.55
axi_req_o[195] 0 1447.07 0.07 1447.15
axi_req_o[194] 0 1307.07 0.07 1307.15
axi_req_o[193] 0 857.955 0.07 858.025
axi_req_o[192] 0 808.955 0.07 809.025
axi_req_o[191] 0 1343.47 0.07 1343.55
axi_req_o[190] 0 1010.84 0.07 1010.91
axi_req_o[189] 0 919.835 0.07 919.905
axi_req_o[188] 0 1069.07 0.07 1069.15
axi_req_o[187] 0 619.955 0.07 620.025
axi_req_o[186] 0 789.075 0.07 789.145
axi_req_o[185] 0 1390.8 0.07 1390.86
axi_req_o[184] 0 908.915 0.07 908.985
axi_req_o[183] 0 918.155 0.07 918.225
axi_req_o[182] 0 1296.16 0.07 1296.22
axi_req_o[181] 0 708.995 0.07 709.065
axi_req_o[180] 0 1265.35 0.07 1265.43
axi_req_o[179] 0 1047.23 0.07 1047.31
axi_req_o[178] 0 1205.44 0.07 1205.51
axi_req_o[177] 0 636.195 0.07 636.265
axi_req_o[176] 0 1058.16 0.07 1058.22
axi_req_o[175] 0 1039.95 0.07 1040.03
axi_req_o[174] 0 1485.44 0.07 1485.51
axi_req_o[173] 0 645.435 0.07 645.505
axi_req_o[172] 0 799.995 0.07 800.065
axi_req_o[171] 0 939.995 0.07 940.065
axi_req_o[170] 0 1159.8 0.07 1159.86
axi_req_o[169] 0 948.955 0.07 949.025
axi_req_o[168] 0 1457.99 0.07 1458.06
axi_req_o[167] 0 736.155 0.07 736.225
axi_req_o[166] 0 1436.16 0.07 1436.22
axi_req_o[165] 0 634.515 0.07 634.585
axi_req_o[164] 0 914.515 0.07 914.585
axi_req_o[163] 0 1256.11 0.07 1256.19
axi_req_o[162] 0 1225.31 0.07 1225.39
axi_req_o[161] 0 999.915 0.07 999.985
axi_req_o[160] 0 1479.83 0.07 1479.91
axi_req_o[159] 0 1067.11 0.07 1067.19
axi_req_o[158] 0 632.555 0.07 632.625
axi_req_o[157] 0 1036.31 0.07 1036.39
axi_req_o[156] 0 843.675 0.07 843.745
axi_req_o[155] 0 967.155 0.07 967.225
axi_req_o[154] 0 1417.95 0.07 1418.03
axi_req_o[153] 0 1169.04 0.07 1169.1
axi_req_o[152] 0 778.155 0.07 778.225
axi_req_o[151] 0 716.275 0.07 716.345
axi_req_o[150] 0 739.795 0.07 739.865
axi_req_o[149] 0 617.995 0.07 618.065
axi_req_o[148] 0 1470.88 0.07 1470.94
axi_req_o[147] 0 1287.19 0.07 1287.27
axi_req_o[146] 0 661.675 0.07 661.745
axi_req_o[145] 0 692.755 0.07 692.825
axi_req_o[144] 0 1238.19 0.07 1238.27
axi_req_o[143] 0 1252.47 0.07 1252.55
axi_req_o[142] 0 1239.88 0.07 1239.94
axi_req_o[141] 0 1361.68 0.07 1361.74
axi_req_o[140] 0 1034.35 0.07 1034.43
axi_req_o[139] 0 1327.23 0.07 1327.31
axi_req_o[138] 0 601.755 0.07 601.825
axi_req_o[137] 0 818.195 0.07 818.265
axi_req_o[136] 0 1354.4 0.07 1354.46
axi_req_o[135] 0 1465.28 0.07 1465.34
axi_req_o[134] 0 1438.11 0.07 1438.19
axi_req_o[133] 0 670.915 0.07 670.985
axi_req_o[132] 0 738.115 0.07 738.185
axi_req_o[131] 0 1183.59 0.07 1183.67
axi_req_o[130] 0 830.795 0.07 830.865
axi_req_o[129] 0 1032.68 0.07 1032.74
axi_req_o[128] 0 870.835 0.07 870.905
axi_req_o[127] 0 812.595 0.07 812.665
axi_req_o[126] 0 1285.23 0.07 1285.31
axi_req_o[125] 0 816.235 0.07 816.305
axi_req_o[124] 0 892.675 0.07 892.745
axi_req_o[123] 0 850.955 0.07 851.025
axi_req_o[122] 0 848.995 0.07 849.065
axi_req_o[121] 0 1181.64 0.07 1181.7
axi_req_o[120] 0 1230.92 0.07 1230.98
axi_req_o[119] 0 1268.99 0.07 1269.06
axi_req_o[118] 0 930.755 0.07 930.825
axi_req_o[117] 0 752.675 0.07 752.745
axi_req_o[116] 0 712.635 0.07 712.705
axi_req_o[115] 0 792.715 0.07 792.785
axi_req_o[114] 0 665.315 0.07 665.385
axi_req_o[113] 0 1187.23 0.07 1187.31
axi_req_o[112] 0 996.275 0.07 996.345
axi_req_o[111] 0 1101.83 0.07 1101.91
axi_req_o[110] 0 883.435 0.07 883.505
axi_req_o[109] 0 612.675 0.07 612.745
axi_req_o[108] 0 1274.31 0.07 1274.39
axi_req_o[107] 0 654.395 0.07 654.465
axi_req_o[106] 0 1025.4 0.07 1025.46
axi_req_o[105] 0 1174.35 0.07 1174.43
axi_req_o[104] 0 1216.35 0.07 1216.43
axi_req_o[103] 0 861.595 0.07 861.665
axi_req_o[102] 0 1381.56 0.07 1381.62
axi_req_o[101] 0 965.475 0.07 965.545
axi_req_o[100] 0 988.995 0.07 989.065
axi_req_o[99] 0 679.875 0.07 679.945
axi_req_o[98] 0 1199.83 0.07 1199.91
axi_req_o[97] 0 1356.35 0.07 1356.43
axi_req_o[96] 0 916.195 0.07 916.265
axi_req_o[95] 0 1419.92 0.07 1419.98
axi_req_o[94] 0 727.195 0.07 727.265
axi_req_o[93] 0 874.475 0.07 874.545
axi_req_o[92] 0 1194.52 0.07 1194.58
axi_req_o[91] 0 829.115 0.07 829.185
axi_req_o[90] 0 801.675 0.07 801.745
axi_req_o[89] 0 718.235 0.07 718.305
axi_req_o[88] 0 1081.68 0.07 1081.74
axi_req_o[87] 0 1281.59 0.07 1281.67
axi_req_o[86] 0 1116.11 0.07 1116.19
axi_req_o[85] 0 1396.11 0.07 1396.19
axi_req_o[84] 0 621.635 0.07 621.705
axi_req_o[83] 0 1303.44 0.07 1303.51
axi_req_o[82] 0 798.035 0.07 798.105
axi_req_o[81] 0 1087.28 0.07 1087.34
axi_req_o[80] 0 614.355 0.07 614.425
axi_req_o[79] 0 1127.04 0.07 1127.1
axi_req_o[78] 0 901.635 0.07 901.705
axi_req_o[77] 0 700.035 0.07 700.105
axi_req_o[76] 0 1338.16 0.07 1338.22
axi_req_o[75] 0 1014.47 0.07 1014.54
axi_req_o[74] 0 749.035 0.07 749.105
axi_req_o[73] 0 1450.71 0.07 1450.79
axi_req_o[72] 0 1377.92 0.07 1377.98
axi_req_o[71] 0 821.835 0.07 821.905
axi_req_o[70] 0 721.875 0.07 721.945
axi_req_o[69] 0 650.755 0.07 650.825
axi_req_o[68] 0 838.075 0.07 838.145
axi_req_o[67] 0 656.355 0.07 656.425
axi_req_o[66] 0 896.315 0.07 896.385
axi_req_o[65] 0 779.835 0.07 779.905
axi_req_o[64] 0 863.555 0.07 863.625
axi_req_o[63] 0 981.715 0.07 981.785
axi_req_o[62] 0 927.115 0.07 927.185
axi_req_o[61] 0 1270.68 0.07 1270.74
axi_req_o[60] 0 1321.64 0.07 1321.7
axi_req_o[59] 0 841.715 0.07 841.785
axi_req_o[58] 0 628.915 0.07 628.985
axi_req_o[57] 0 1048.92 0.07 1048.98
axi_req_o[56] 0 1388.83 0.07 1388.91
axi_req_o[55] 0 1359.99 0.07 1360.06
axi_req_o[54] 0 1399.76 0.07 1399.82
axi_req_o[53] 0 952.595 0.07 952.665
axi_req_o[52] 0 1430.83 0.07 1430.91
axi_req_o[51] 0 890.715 0.07 890.785
axi_req_o[50] 0 1410.68 0.07 1410.74
axi_req_o[49] 0 1276.28 0.07 1276.34
axi_req_o[48] 0 1218.04 0.07 1218.1
axi_req_o[47] 0 696.395 0.07 696.465
axi_req_o[46] 0 1045.28 0.07 1045.34
axi_req_o[45] 0 754.355 0.07 754.425
axi_req_o[44] 0 1118.07 0.07 1118.15
axi_req_o[43] 0 1401.71 0.07 1401.79
axi_req_o[42] 0 1125.35 0.07 1125.43
axi_req_o[41] 0 1405.35 0.07 1405.43
axi_req_o[40] 0 1403.4 0.07 1403.46
axi_req_o[39] 0 1056.19 0.07 1056.27
axi_req_o[38] 0 925.435 0.07 925.505
axi_req_o[37] 0 1387.16 0.07 1387.22
axi_req_o[36] 0 1445.4 0.07 1445.46
axi_req_o[35] 0 1394.44 0.07 1394.51
axi_req_o[34] 0 1037.99 0.07 1038.06
axi_req_o[33] 0 958.195 0.07 958.265
axi_req_o[32] 0 912.555 0.07 912.625
axi_req_o[31] 0 625.275 0.07 625.345
axi_req_o[30] 0 810.915 0.07 810.985
axi_req_o[29] 0 1350.76 0.07 1350.82
axi_req_o[28] 0 668.955 0.07 669.025
axi_req_o[27] 0 734.475 0.07 734.545
axi_req_o[26] 0 1332.56 0.07 1332.62
axi_req_o[25] 0 1421.59 0.07 1421.67
axi_req_o[24] 0 1472.56 0.07 1472.62
axi_req_o[23] 0 747.075 0.07 747.145
axi_req_o[22] 0 643.475 0.07 643.545
axi_req_o[21] 0 1241.83 0.07 1241.91
axi_req_o[20] 0 1156.16 0.07 1156.22
axi_req_o[19] 0 605.395 0.07 605.465
axi_req_o[18] 0 663.635 0.07 663.705
axi_req_o[17] 0 1330.88 0.07 1330.94
axi_req_o[16] 0 1459.95 0.07 1460.03
axi_req_o[15] 0 1414.31 0.07 1414.39
axi_req_o[14] 0 690.795 0.07 690.865
axi_req_o[13] 0 1292.52 0.07 1292.58
axi_req_o[12] 0 976.395 0.07 976.465
axi_req_o[11] 0 950.915 0.07 950.985
axi_req_o[10] 0 794.395 0.07 794.465
axi_req_o[9] 0 1023.43 0.07 1023.51
axi_req_o[8] 0 647.115 0.07 647.185
axi_req_o[7] 0 774.515 0.07 774.585
axi_req_o[6] 0 687.155 0.07 687.225
axi_req_o[5] 0 1294.47 0.07 1294.55
axi_req_o[4] 0 1290.83 0.07 1290.91
axi_req_o[3] 0 1232.59 0.07 1232.67
axi_req_o[2] 0 907.235 0.07 907.305
axi_req_o[1] 0 772.555 0.07 772.625
axi_req_o[0] 0 1476.19 0.07 1476.27
axi_resp_i[81] 0 719.915 0.07 719.985
axi_resp_i[80] 0 859.915 0.07 859.985
axi_resp_i[79] 0 694.435 0.07 694.505
axi_resp_i[78] 0 1247.16 0.07 1247.22
axi_resp_i[77] 0 1372.59 0.07 1372.67
axi_resp_i[76] 0 834.435 0.07 834.505
axi_resp_i[75] 0 1498.04 0.07 1498.1
axi_resp_i[74] 0 1492.71 0.07 1492.79
axi_resp_i[73] 0 745.395 0.07 745.465
axi_resp_i[72] 0 1374.28 0.07 1374.34
axi_resp_i[71] 0 1054.52 0.07 1054.58
axi_resp_i[70] 0 1052.56 0.07 1052.62
axi_resp_i[69] 0 1007.2 0.07 1007.27
axi_resp_i[68] 0 710.955 0.07 711.025
axi_resp_i[67] 0 1123.4 0.07 1123.46
axi_resp_i[66] 0 1454.35 0.07 1454.43
axi_resp_i[65] 0 929.075 0.07 929.145
axi_resp_i[64] 0 1279.92 0.07 1279.98
axi_resp_i[63] 0 1099.88 0.07 1099.94
axi_resp_i[62] 0 1428.88 0.07 1428.94
axi_resp_i[61] 0 827.155 0.07 827.225
axi_resp_i[60] 0 845.355 0.07 845.425
axi_resp_i[59] 0 879.795 0.07 879.865
axi_resp_i[58] 0 1228.95 0.07 1229.03
axi_resp_i[57] 0 1301.76 0.07 1301.82
axi_resp_i[56] 0 1443.44 0.07 1443.51
axi_resp_i[55] 0 707.315 0.07 707.385
axi_resp_i[54] 0 885.395 0.07 885.465
axi_resp_i[53] 0 823.515 0.07 823.585
axi_resp_i[52] 0 776.195 0.07 776.265
axi_resp_i[51] 0 761.635 0.07 761.705
axi_resp_i[50] 0 1109.11 0.07 1109.19
axi_resp_i[49] 0 1154.47 0.07 1154.55
axi_resp_i[48] 0 725.515 0.07 725.585
axi_resp_i[47] 0 1341.8 0.07 1341.86
axi_resp_i[46] 0 894.355 0.07 894.425
axi_resp_i[45] 0 1176.31 0.07 1176.39
axi_resp_i[44] 0 603.435 0.07 603.505
axi_resp_i[43] 0 905.275 0.07 905.345
axi_resp_i[42] 0 1432.52 0.07 1432.58
axi_resp_i[41] 0 723.555 0.07 723.625
axi_resp_i[40] 0 1094.56 0.07 1094.62
axi_resp_i[39] 0 1070.76 0.07 1070.82
axi_resp_i[38] 0 932.715 0.07 932.785
axi_resp_i[37] 0 1185.28 0.07 1185.34
axi_resp_i[36] 0 1368.95 0.07 1369.03
axi_resp_i[35] 0 936.355 0.07 936.425
axi_resp_i[34] 0 1358.04 0.07 1358.1
axi_resp_i[33] 0 790.755 0.07 790.825
axi_resp_i[32] 0 781.795 0.07 781.865
axi_resp_i[31] 0 1212.71 0.07 1212.79
axi_resp_i[30] 0 1110.8 0.07 1110.86
axi_resp_i[29] 0 783.475 0.07 783.545
axi_resp_i[28] 0 1487.11 0.07 1487.19
axi_resp_i[27] 0 1263.4 0.07 1263.46
axi_resp_i[26] 0 1441.76 0.07 1441.82
axi_resp_i[25] 0 796.355 0.07 796.425
axi_resp_i[24] 0 638.155 0.07 638.225
axi_resp_i[23] 0 1021.76 0.07 1021.83
axi_resp_i[22] 0 1161.76 0.07 1161.82
axi_resp_i[21] 0 1248.83 0.07 1248.91
axi_resp_i[20] 0 1334.52 0.07 1334.58
axi_resp_i[19] 0 1234.56 0.07 1234.62
axi_resp_i[18] 0 757.995 0.07 758.065
axi_resp_i[17] 0 683.515 0.07 683.585
axi_resp_i[16] 0 889.035 0.07 889.105
axi_resp_i[15] 0 756.315 0.07 756.385
axi_resp_i[14] 0 1188.92 0.07 1188.98
axi_resp_i[13] 0 1288.88 0.07 1288.94
axi_resp_i[12] 0 1223.64 0.07 1223.7
axi_resp_i[11] 0 1114.44 0.07 1114.51
axi_resp_i[10] 0 1398.07 0.07 1398.15
axi_resp_i[9] 0 1392.47 0.07 1392.55
axi_resp_i[8] 0 639.835 0.07 639.905
axi_resp_i[7] 0 1227.28 0.07 1227.34
axi_resp_i[6] 0 1043.59 0.07 1043.67
axi_resp_i[5] 0 985.355 0.07 985.425
axi_resp_i[4] 0 1072.71 0.07 1072.79
axi_resp_i[3] 0 878.115 0.07 878.185
axi_resp_i[2] 0 732.515 0.07 732.585
axi_resp_i[1] 0 730.835 0.07 730.905
axi_resp_i[0] 0 678.195 0.07 678.265
This source diff could not be displayed because it is too large. You can view the blob instead.
import os
import argparse
import time
import shutil
import sys
from math import floor
####################################################################################
#### Extract hypergraph, instance, IO ports and outline from netlist
####################################################################################
def GenerateHypergraph(openroad_exe, setup_file, extract_hypergraph_file):
temp_file = os.getcwd() + "/extract_hypergraph.tcl"
cmd = "cp " + setup_file + " " + temp_file
os.system(cmd)
with open(extract_hypergraph_file) as f:
content = f.read().splitlines()
f.close()
f = open(temp_file, "a")
f.write("\n")
for line in content:
f.write(line + "\n")
f.close()
cmd = openroad_exe + " " + temp_file
os.system(cmd)
cmd = "rm " + temp_file
os.system(cmd)
####################################################################################
#### TraverseFanout in BFS manner
####################################################################################
def TraverseFanout(vertices_list, hyperedges_list, vertex_hash, seed_id, root_id, K_out):
# update the root vertex
vertex_hash[root_id] = [seed_id, 0]
visited = []
wavefront = []
wavefront.append(root_id)
while (len(wavefront) > 0):
vertex_id = wavefront.pop(0)
visited.append(vertex_id)
level_id = vertex_hash[vertex_id][1] + 1
if (level_id <= K_out):
for hyperedge_id in vertices_list[vertex_id]:
hyperedge = hyperedges_list[hyperedge_id]
# This hyperedge is driven by current edge
if (hyperedge[0] == vertex_id):
for i in range(1, len(hyperedge)):
if hyperedge[i] in visited:
pass
else:
if (vertex_hash[hyperedge[i]][1] > level_id):
vertex_hash[hyperedge[i]] = [seed_id, level_id]
wavefront.append(hyperedge[i])
elif (vertex_hash[hyperedge[i]][1] == level_id and vertex_hash[hyperedge[i]][1] > seed_id):
vertex_hash[hyperedge[i]] = [seed_id, level_id]
wavefront.append(hyperedge[i])
####################################################################################
#### TraverseFanin in BFS manner
####################################################################################
def TraverseFanin(vertices_list, hyperedges_list, vertex_hash, seed_id, root_id, K_in):
# update the root vertex
vertex_hash[root_id] = [seed_id, 0]
visited = []
wavefront = []
wavefront.append(root_id)
while (len(wavefront) > 0):
vertex_id = wavefront.pop(0)
visited.append(vertex_id)
level_id = vertex_hash[vertex_id][1] + 1
if (level_id <= K_in):
for hyperedge_id in vertices_list[vertex_id]:
hyperedge = hyperedges_list[hyperedge_id]
# This hyperedge is not driven by vertex_id
if (hyperedge[0] != vertex_id):
driver_id = hyperedge[0]
if driver_id in visited:
pass
else:
if (vertex_hash[driver_id][1] > level_id):
vertex_hash[driver_id] = [seed_id, level_id]
wavefront.append(driver_id)
elif (vertex_hash[driver_id][1] == level_id and vertex_hash[driver_id][1] > seed_id):
vertex_hash[driver_id] = [seed_id, level_id]
wavefront.append(driver_id)
def Grouping(design, n_rows, n_cols, K_in, K_out, setup_file, global_net_threshold, src_dir):
pwd = os.getcwd()
# Specify the location of hmetis exe and openroad exe
openroad_exe = src_dir + "/utils/openroad"
extract_hypergraph_file = src_dir + "/utils/extract_hypergraph.tcl"
# Generate Hypergraph file
rpt_dir = pwd + "/rtl_mp"
hypergraph_file = rpt_dir + "/" + design + ".hgr"
io_name_file = hypergraph_file + ".io"
instance_name_file = hypergraph_file + ".instance"
outline_file = hypergraph_file + ".outline"
fix_file = pwd + "/" + design + ".fix"
original_fix_file = pwd + "/" + design + ".fix.old"
GenerateHypergraph(openroad_exe, setup_file, extract_hypergraph_file)
# read hypergraph
# Each vertex corresponds to the hyperedge_id incident to it
# Each hyperedge corresponds to the vertices in it
with open (hypergraph_file) as f:
content = f.read().splitlines()
f.close()
items = content[0].split()
num_hyperedges = int(items[0])
num_vertices = int(items[1])
vertices_list = [[] for i in range(num_vertices)]
hyperedges_list = []
hyperedge_id = 0
for i in range(num_hyperedges):
items = content[i+1].split()
# ignore all the global nets
if (len(items) > global_net_threshold):
pass
hyperedge = [int(item) - 1 for item in items]
hyperedges_list.append(hyperedge)
for vertex in hyperedge:
vertices_list[vertex].append(hyperedge_id)
hyperedge_id += 1
# sort all the macros and IOs based on lexicographically smallest macro name
# get all the IOs and macros as seeds
seed_list = []
vertex_map = { }
vertex_name_list = []
# read all the IOs
io_pos_map = { }
with open(io_name_file) as f:
content = f.read().splitlines()
f.close()
vertex_id = 0
for line in content:
items = line.split()
io_name = items[0]
x = (float(items[1]) + float(items[3])) / 2.0
y = (float(items[2]) + float(items[4])) / 2.0
io_pos_map[io_name] = (x, y)
seed_list.append(io_name)
vertex_map[io_name] = vertex_id
vertex_name_list.append(io_name)
vertex_id += 1
# read all the instances (including macros)
with open(instance_name_file) as f:
content = f.read().splitlines()
f.close()
for line in content:
items = line.split()
inst_name = items[0]
vertex_map[inst_name] = vertex_id
vertex_name_list.append(inst_name)
vertex_id += 1
if (int(items[1]) == 1):
seed_list.append(inst_name)
# sort the seed
seed_list.sort()
# grouping all the directly K_in fanins and K_out fanouts respect to
# ios and instances.
vertex_hash = [[len(seed_list), max(K_in, K_out) + 1] for i in range(len(vertex_map))]
for i in range(len(seed_list)):
TraverseFanout(vertices_list, hyperedges_list, vertex_hash, i, vertex_map[seed_list[i]], K_out)
TraverseFanin(vertices_list, hyperedges_list, vertex_hash, i, vertex_map[seed_list[i]], K_in)
# group IOs to bundled pins based on their position
with open(outline_file) as f:
content = f.read().splitlines()
f.close()
items = content[0].split()
floorplan_lx = float(items[0])
floorplan_ly = float(items[1])
floorplan_ux = float(items[2])
floorplan_uy = float(items[3])
# get the vertical distance and horizontal distance
width = (floorplan_ux - floorplan_lx) / n_cols
height = (floorplan_uy - floorplan_ly) / n_rows
initial_group_map = { }
grid_row_max = 100000000
for io_name, pos in io_pos_map.items():
hash_id = floor( pos[1] / height) * grid_row_max + floor( pos[0] / width)
if hash_id not in initial_group_map:
initial_group_map[hash_id] = [io_name]
else:
initial_group_map[hash_id].append(io_name)
# final group list
group_list = [ ]
for hash_id, ios in initial_group_map.items():
group_list.append(ios)
for seed in seed_list:
if seed not in io_pos_map:
group_list.append([seed])
group_id_map = { }
for i in range(len(group_list)):
for vertex in group_list[i]:
group_id_map[vertex] = i
for i in range(len(vertex_hash)):
seed_id = vertex_hash[i][0]
if (seed_id < len(seed_list)):
vertex_name = vertex_name_list[i]
seed_name = seed_list[seed_id]
if vertex_name not in group_list[group_id_map[seed_name]]:
group_list[group_id_map[seed_name]].append(vertex_name)
f = open(original_fix_file, "w")
for group in group_list:
line = ""
for vertex in group:
line += vertex + ","
line = line[0:-1]
f.write(line + '\n')
f.close()
f = open(fix_file, "w")
for group in group_list:
line = ""
for vertex in group:
if vertex not in seed_list:
line += vertex + ","
if (len(line) > 0):
line = line[0:-1]
f.write(line + '\n')
f.close()
shutil.rmtree(rpt_dir)
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
import os
import sys
import argparse
# Load the src files
sys.path.append('../src')
from grouping import Grouping
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--design", help = "design name", type = str, default = "ariane")
parser.add_argument("--n_rows", help = "number of rows", type = int, default = "128")
parser.add_argument("--n_cols", help = "number of cols", type = int, default = "128")
parser.add_argument("--K_in", help = "K_in", type = int, default = "1")
parser.add_argument("--K_out", help = "K_out", type = int, default = "1")
parser.add_argument("--setup_file", help = "setup file for openroad (default = setup.tcl)", type = str, default = "setup.tcl")
parser.add_argument("--global_net_threshold", help = "global net threshold", type = int, default = 100)
args = parser.parse_args()
design = args.design
n_rows = args.n_rows
n_cols = args.n_cols
K_in = args.K_in
K_out = args.K_out
setup_file = args.setup_file
global_net_threshold = args.global_net_threshold
# To use the grouping function, you need to specify the directory of src file
src_dir = "../src"
Grouping(design, n_rows, n_cols, K_in, K_out, setup_file, global_net_threshold, src_dir)
# MacroPlacement
**MacroPlacement** is an open, transparent effort to provide a public, baseline implementation of [Google Brain's Circuit Training](https://github.com/google-research/circuit_training) (Morpheus) deep RL-based placement method. We provide (1) testcases in open enablements, along with multiple EDA tool flows; (2) implementations of missing or binarized elements of Circuit Training; (3) reproducible example macro placement solutions produced by our implementation; and (4) post-routing results obtained by full completion of the place-and-route flow using both proprietary and open-source tools.
### List of Testcases
- [Ariane](https://github.com/lowRISC/ariane)
- [136-macro version](./Testcases/ariane136/)
- [133-macro version](./Testcases/ariane133/)
- MemPool ("[tile](./Testcases/mempool_tile/)" and "group")
# **MacroPlacement**
**MacroPlacement** is an open, transparent effort to provide a public, baseline implementation of [Google Brain's Circuit Training](https://github.com/google-research/circuit_training) (Morpheus) deep RL-based placement method. We will provide (1) testcases in open enablements, along with multiple EDA tool flows; (2) implementations of missing or binarized elements of Circuit Training; (3) reproducible example macro placement solutions produced by our implementation; and (4) post-routing results obtained by full completion of the place-and-route flow using both proprietary and open-source tools.
### List of Flows
Synthesis, placement and routing flows in
- [OpenROAD](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts)
- Ariane
- [136-macro version](./Flows/NanGate45/ariane136/)
- [133-macro version](./Flows/NanGate45/ariane133/)
- MemPool
- [tile](./Flows/NanGate45/mempool_tile/)
- Cadence (Genus 21.1 for synthesis and Innovus 21.1 for P&R)
- Ariane
- [136-macro version](./Flows/NanGate45/ariane136/scripts/cadence/)
- [133-macro version](./Flows/NanGate45/ariane133/scripts/cadence/)
- MemPool
- [tile](./Flows/NanGate45/mempool_tile/scripts/cadence/)
- group
### List of Enablements
- [NanGate45 (FreePDK45, 45nm Open Cell Library, bsg-FakeRAM memory generation)](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/Enablements/NanGate45)
- [ASAP7 (7.5T cell library (RVT only), FakeRAM2.0 memory generation)](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/Enablements/ASAP7)
## **Table of Content**
<!-- - [Reproducible Example Solutions](#reproducible-example-solutions) -->
- [Testcases](#testcases)
- [Enablements](#enablements)
- [Flows](#flows)
- [Code Elements](#code-elements)
- [FAQ](#faq)
- [Related Links](#related-links)
## **Testcases**
The list of avaialbe test cases
- Ariane (RTL)
- [RTL files for Ariane design with 136 macros](./Testcases/ariane136/), which are generated by instantiating 16-bit memories in Ariane netlist availabe in [lowRISC](https://github.com/lowRISC/ariane) GitHub repository.
- [RTL files for Ariane designs with 133 macros](./Testcases/ariane133/), which are generated by updating the memory connection of 136 macro version.
- MemPool (RTL)
- [RTL files for Mempool tile design](./Testcases/mempool_tile/)
- RTL files for Mempool group design
In this [Nature Paper](https://www.nature.com/articles/s41586-021-03544-w), authors have used Ariane design with 133 memory (256x16, single ported SRAM) macros as one of the test cases. We noticed synthesizing the available Ariane netlist in [lowRISC](https://github.com/lowRISC/ariane) GitHub repository with 256x16 memory results in Ariane design with 136 memory macros ([Here](./Testcases/ariane136/) we show how we instantiate memories for Ariane 136). [Here](./Testcases/ariane133/) we show how we convert the Ariane 136 design to Ariane 133 design. So, we added these two versions to our testcase list.
MemPool tile design is another testcase and we will be adding MemPool group in this list.
Here we provide the detailed steps to generate the netlist for each test case. This netlist is used for the SP&R runs. The directory structure is as follows *./Testcases/\<testcase\>/<rtl\|sv2v>/*.
- *rtl* directory contains all the required rtl files to synthesize the test case.
- If the main repository contains only the SystemVerilog files, we add the converted Verilog file to the sv2v directory.
## **Enablements**
The list of available enablements
- [NanGate45 Enablements](./Enablements/NanGate45/)
- [ASAP7 Enablements](./Enablements/ASAP7/)
### List of Code Elements
- [Gridding](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Gridding) <br />
- [Grouping](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Grouping) <br />
- [Placement-guided hypergraph clustering (soft macro definition)](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/Clustering) <br />
- [Force-directed placement](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/FDPlacement) <br />
- [Simulated annealing](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/SimulatedAnnealing) <br />
- [LEF/DEF and Bookshelf (OpenDB, RosettaStone) translators](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/FormatTranslators) <br />
### Reproducible Example Solutions
Open-source enablements NanGate45 and ASAP7 (will be adding) are utilized in our SP&R flow. The directory structure is *./Enablements/\<enablement\>/<lib\|lef>/*. Here
- *lib* directory contains all the required liberty files.
- *lef* directory contains all the required lef files.
Also, we provide steps to generate the fakerams.
## **Flows**
Synthesis, place and route (SP&R) flow is available for each test case on each enablement. Here is the list
- NanGate45
- [SP&R flows for Ariane design with 136 macros](./Flows/NanGate45/ariane136/)
- [SP&R flows for Ariane design with 133 macros](./Flows/NanGate45/ariane133/)
- [SP&R flows for MemPool tile design](./Flows/NanGate45/mempool_tile/)
- MemPool group
Here we provide detailed information to run SP&R for each test case using the open-source tools Yosys (synthesis) and OpenROAD (P&R), and the commercial tools Cadence Genus (synthesis) and Innovus (P&R).
The directory structure is as follows *./FLows/\<enablement\>/\<testcase\>/<constraint\|def\|netlist\|scripts\|run>/*. Here
- *constraint* directory contains the *.sdc* file.
- *def* directory contains the def file with pin placement and die area information.
- *scripts* directory contains required scripts to run SP&R using the Cadence and OpenROAD tools.
- *netlist* directory contains the synthesized netlist. We provide a synthesized netlist that can be used to run P&R.
- Also, we provide the *run* directory to run the scripts provided in the *scripts* directory.
## **Code Elements**
The code elements below are most crucial undocumented portions of Circuit Training. We thank Google
engineers for Q&A in a shared document, as well as live discussions on May 19, 2022,
that explained the following code elements used in Circuit Training.
All errors of understanding and implementation are the authors'.
We will rectify such errors as soon as possible after being made aware of them.
- [Gridding](./CodeElements/Gridding/) determines a dissection of the layout canvas into some number of rows (n_rows) and some number of columns (n_cols) of gridcells. In Circuit Training, the purpose of gridding is to control the size of the macro placement solution space,
thus allowing RL to train within reasonable runtimes. Gridding enables hard macros to find locations consistent with high solution quality,
while allowing soft macros (standard-cell clusters) to also find good locations.
- [Grouping](./CodeElements/Grouping/) ensures that closely-related logic is kept close to hard macros and to clumps of IOs. The clumps of IOs are induced by IO locations with respect to the row and column coordinates in the gridded layout canvas.
- [Hypergraph clustering](./CodeElements/Clustering/) clusters millions of standard cells into a few thousand clusters. In Circuit Training, the purpose of clustering is to generate an approximate but fast standard cell placement that facilitates policy networks.
- [Force-directed placement](./CodeElements/FDPlacement/) places the center of each standard cell cluster onto centers of gridcells generated by [Gridding](./CodeElements/Gridding/).
- [Simulated annealing](./CodeElements/SimulatedAnnealing/) places the center of each macro onto centers of gridcells generated by [Gridding](./CodeElements/Gridding/). In Circuit Training, simulated annealing is used as a baseline to show the relative sample efficiency of RL.
- [LEF/DEF and Bookshelf (OpenDB, RosettaStone) translators](./CodeElements/FormatTranslators/) ease the translation between different representations of the same netlist.
<!--## **Reproducible Example Solutions** -->
## **FAQ**
**Why are you doing this?**
- The challenges of data and benchmarking in EDA research have, in our view, been contributing factors in the controversy regarding the Nature work. The mission of the TILOS AI Institute includes finding solutions to these challenges -- in high-stakes applied optimization domains (such as IC EDA), and at community-scale. We hope that our effort will become an existence proof for transparency, reproducibility, and democratization of research in EDA. [We applaud and thank Cadence Design Systems for allowing their tool runscripts to be shared openly by researchers, enabling reproducibility of results obtained via use of Cadence tools.]
- We do understand that Google has been working hard to complete the open-sourcing of Morpheus, and that this effort continues today. However, as pointed out in [this Doc](https://docs.google.com/document/d/1vkPRgJEiLIyT22AkQNAxO8JtIKiL95diVdJ_O4AFtJ8/edit?usp=sharing), it has been more than a year since "Data and Code Availability" was committed with publication of the [Nature paper](https://www.nature.com/articles/s41586-021-03544-w). We consider our work a "backstop" or "safety net" for Google's internal efforts, and a platform for researchers to build on.
**What can others contribute?**
- Our shopping list includes the following. Please join in!
- force-directed placement (and API): documentation and implementation
- adjacency matrix generation: documentation and implementation
- simulated annealing on the gridded canvas: documentation and implementation
- donated cloud resources (credits) for experimental studies
- relevant testcases with reference implementations and implementation flows (Cadence, OpenROAD preferred since scripts can be shared)
- protobuf, lef/def, Bookshelf: detailed and confirmed documentation, plus translators
- "fakeram" generator for the ASAP7 research PDK
- qrctechfile for NanGate45
**What is your timeline?**
- We hope to show significant progress at the [DAC-2022 Birds-of-a-Feather](https://59dac.conference-program.com/session/?sess=sess294) meeting (Open-Source EDA and Benchmarking Summit) on July 12, 2022, 7-10pm in Room 3000 of Moscone West in San Francisco.
## **Related Links**
- R. Cheng and J. Yan, "On joint learning for solving placement and routing in chip design",
*Proc. NeurIPS*, 2021. \[[paper](https://arxiv.org/pdf/2111.00234v1.pdf)\] \[[code](https://github.com/Thinklab-SJTU/EDA-AI)\]
- F. -C. Chang, Y. -W. Tseng, Y. -W. Yu, S. -R. Lee, A. Cioba, et al.,
"Flexible multiple-objective reinforcement learning for chip placement",
*arXiv:2204.06407*, 2022. \[[paper](https://arxiv.org/pdf/2204.06407.pdf)\]
- S. Guadarrama, S. Yue, T. Boyd, J. Jiang, E. Songhori, et al.,
"Circuit training: an open-source framework for generating chip floor plans with distributed deep reinforcement learning", 2021. \[[code](https://github.com/google-research/circuit_training)\]
- A. Mirhoseini, A. Goldie, M. Yazgan, J. Jiang, E. Songhori, et al.,
"A graph placement methodology for fast chip design", *Nature*, 594(7862) (2021), pp. 207-212.
\[[paper](https://www.nature.com/articles/s41586-021-03544-w)\]
- A. Mirhoseini, A. Goldie, M. Yazgan, J. Jiang, E. Songhori, et al.,
"Chip Placement with Deep Reinforcement Learning",
*arXiv:2004.10746*, 2020. \[[paper](https://arxiv.org/pdf/2004.10746.pdf)\]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment