Commit 944bc1f7 by sakundu

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

parents 496bf120 60e8c9d9
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.
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.
# Force-directed placement
**Force-directed placement** is used to place center of standard cell clusters onto
the center of the grid cells.
## **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.”
* “We discretize the grid to a few thousand grid cells and place the centre of macros and standard cell clusters onto the centre of the grid cells.”
* **“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.”
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.
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.
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.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -20,6 +20,7 @@ def print_placeholder(key, value):
return line
def print_float(key, value):
value = round(value, 6)
line = " attr {\n"
line += f' key: "{key}"\n'
line += ' value {\n'
......@@ -66,7 +67,7 @@ class Port:
else:
name += char
self.str += ' name: "' + name + '"\n'
for sink in self.sinks:
sink_new = ''
for char in sink:
......@@ -76,7 +77,7 @@ class Port:
sink_new += char
sink = sink_new
self.str += ' input: "' + sink + '"\n'
self.str += print_placeholder('type', 'PORT')
self.str += print_placeholder('side', self.side)
self.str += print_float('x', self.x)
......@@ -135,7 +136,7 @@ class StandardCell:
sink_new += char
sink = sink_new
self.str += ' input: "' + sink + '"\n'
self.str += print_placeholder('type', 'STDCELL')
self.str += print_float('height', self.height)
self.str += print_float('width', self.width)
......@@ -264,7 +265,7 @@ class MacroPin:
sink_new += char
sink = sink_new
self.str += ' input: "' + sink + '"\n'
macro_name = ''
for char in self.macro_name:
if char == '\\':
......@@ -278,7 +279,7 @@ class MacroPin:
self.str += print_placeholder('type', 'macro_pin')
if (self.weight > 1):
self.str += print_float('weight', self.weight)
self.str += print_float('x_offset', self.x_offset)
self.str += print_float('y_offset', self.y_offset)
self.str += print_float('x', self.x)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
###############################################################################################
# This script is used to visualize the placement results for macros and standard-cell clusters
# The input is protocol buffer netlist and plc file
# All the hard macros are in blue color
# All the standard-cell clusters are in red color
###############################################################################################
import os
import time
import shutil
import sys
import argparse
import matplotlib.pyplot as plt
from math import log
import json
# ***************************************************************
# Define basic classes
# ***************************************************************
# Define the orientation map
OrientMap = {
"N" : "R0",
"S" : "R180",
"W" : "R90",
"E" : "R270",
"FN" : "MY",
"FS" : "MX",
"FW" : "MX90",
"FE" : "MY90"
}
# Define the plc object
# This is a superset of attributes for different types of plc objects
# A plc object can only have some or all the attributes
# Please check Circuit Training repo (https://github.com/google-research/circuit_training/blob/main/docs/NETLIST_FORMAT.md) for detailed explanation
class PlcObject:
def __init__(self, id):
self.name = None
self.node_id = id
self.height = 0
self.width = 0
self.weight = 0
self.x = -1
self.x_offset = 0
self.y = -1
self.y_offset = 0
self.m_name = None # for macro name
self.pb_type = None
self.side = None
self.orientation = None
def IsHardMacro(self):
if (self.pb_type == '"MACRO"'):
return True
else:
return False
def IsSoftMacro(self):
if (self.pb_type == '"macro"'):
return True
else:
return False
def IsPort(self):
if (self.pb_type == '"PORT"'):
return True
else:
return False
def GetLocation(self):
return self.x - self.width / 2.0 , self.y - self.height / 2.0
def GetWidth(self):
return self.width
def GetHeight(self):
return self.height
def VisualPlacement(netlist_file, plc_file):
n_rows = -1
n_cols = -1
width = 0.0
height = 0.0
plc_object_list = [] # store all the plc objects
# read protocol buffer netlist
float_values = ['"height"', '"weight"', '"width"', '"x"', '"x_offset"', '"y"', '"y_offset"']
placeholders = ['"macro_name"', '"orientation"', '"side"', '"type"']
with open(netlist_file) as f:
content = f.read().splitlines()
f.close()
object_id = 0
key = ""
for line in content:
words = line.split()
if words[0] == 'node':
if len(plc_object_list) > 0 and plc_object_list[-1].name == '"__metadata__"':
plc_object_list.pop(-1)
plc_object_list.append(PlcObject(object_id)) # add object
object_id += 1
elif words[0] == 'name:':
plc_object_list[-1].name = words[1]
elif words[0] == 'key:' :
key = words[1] # the attribute name
elif words[0] == 'placeholder:' :
if key == placeholders[0]:
plc_object_list[-1].m_name = words[1]
elif key == placeholders[1]:
plc_object_list[-1].orientation = words[1]
elif key == placeholders[2]:
plc_object_list[-1].side = words[1]
elif key == placeholders[3]:
plc_object_list[-1].pb_type = words[1]
elif words[0] == 'f:' :
if key == float_values[0]:
plc_object_list[-1].height = round(float(words[1]), 6)
elif key == float_values[1]:
plc_object_list[-1].weight = round(float(words[1]), 6)
elif key == float_values[2]:
plc_object_list[-1].width = round(float(words[1]), 6)
elif key == float_values[3]:
plc_object_list[-1].x = round(float(words[1]),6)
elif key == float_values[4]:
plc_object_list[-1].x_offset = round(float(words[1]), 6)
elif key == float_values[5]:
plc_object_list[-1].y = round(float(words[1]),6)
elif key == float_values[6]:
plc_object_list[-1].y_offset = round(float(words[1]), 6)
# read plc file for all the plc objects
with open(plc_file) as f:
content = f.read().splitlines()
f.close()
# read the canvas and grid information
for line in content:
items = line.split()
if (len(items) > 2 and items[0] == "#" and items[1] == "Columns"):
n_cols = int(items[3])
n_rows = int(items[6])
elif (len(items) > 2 and items[0] == "#" and items[1] == "Width"):
canvas_width = float(items[3])
canvas_height = float(items[6])
print("***************************************************")
print("canvas_width = ", canvas_width)
print("canvas_height = ", canvas_height)
print("n_cols = ", n_cols)
print("n_rows = ", n_rows)
print("\n\n")
# Plot the hard macros and standard-cell clusters
plt.figure()
for plc_object in plc_object_list:
if (plc_object.IsHardMacro() == True or plc_object.IsSoftMacro() == True):
color = "blue"
if (plc_object.IsSoftMacro() == True):
color = "red"
lx, ly = plc_object.GetLocation()
width = plc_object.GetWidth()
height = plc_object.GetHeight()
rectangle = plt.Rectangle((lx, ly), width, height, fc = color, ec = "black")
plt.gca().add_patch(rectangle)
# Add boundries
lx = 0.0
ly = 0.0
ux = lx + canvas_width
uy = ly + canvas_height
lw = 5.0
x = []
y = []
x.append(lx)
y.append(ly)
x.append(ux)
y.append(ly)
plt.plot(x,y, '-k', lw = lw)
x = []
y = []
x.append(lx)
y.append(uy)
x.append(ux)
y.append(uy)
plt.plot(x,y, '-k', lw = lw)
x = []
y = []
x.append(lx)
y.append(ly)
x.append(lx)
y.append(uy)
plt.plot(x,y, '-k', lw = lw)
x = []
y = []
x.append(ux)
y.append(ly)
x.append(ux)
y.append(uy)
plt.plot(x,y, '-k', lw = lw)
plt.xlim(lx, ux)
plt.ylim(ly, uy)
plt.axis("scaled")
plt.show()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--netlist", help="protocol buffer netlist", type = str, default = "./test/ariane.pb.txt")
parser.add_argument("--plc", help="plc_file", type = str, default = "./test/ariane.plc")
args = parser.parse_args()
netlist_file = args.netlist
plc_file = args.plc
VisualPlacement(netlist_file, plc_file)
......@@ -4027,8 +4027,8 @@ In the following table we report the Kendall rank correlation coefficient for pr
</tbody>
</table>
- Kendall rank correlation coefficient indicates poor correlation between proxy cost and postPlaceOpt metrics. Similarly, we see a poor correlation between proxy cost and postRouteOpt metrics.
- We see the proxy costs for RUN3 and RUN7 are 0.8861 and 0.8675 respectively, which is much higher than the best proxy cost 0.8285 (corresponding to RUN15), but the total power and TNS for RUN3 and RUN7 is better than RUN15.
- Kendall rank correlation coefficients indicate poor correlation between proxy cost and postPlaceOpt metrics. Similarly, we see a poor correlation between proxy cost and postRouteOpt metrics.
- We see the proxy costs of RUN3 and RUN7 are 0.8861 and 0.8675 respectively, which is much higher than the best proxy cost of 0.8285 (corresponding to RUN15), but the total power and TNS for RUN3 and RUN7 are better than RUN15.
<a id="MemPoolGroup_NG45_68"></a>
......@@ -4221,4 +4221,4 @@ We have trained CT to generate a macro placement for the [MemPool Group design](
**<span style="color:blue">[Question 7](#Question7).</span>** What happens if we skip CT and continue directly to standard-cell P&R (i.e., the Innovus 21.1 flow) once we have a macro placement from the commercial tool?
**<span style="color:blue">[Question 8](#Question8).</span>** How does the tightness of timing constraints affect the (relative) performance of CT?
**<span style="color:blue">[Question 9](#Question9).</span>** Are CT results stable? If not, how much does the outcome vary?
**<span style="color:blue">[Question 10](#Question10).</span>** What is the correlation between proxy cost and the postRouteOpt Table 1 metrics?
\ No newline at end of file
**<span style="color:blue">[Question 10](#Question10).</span>** What is the correlation between proxy cost and the postRouteOpt Table 1 metrics?
......@@ -11,7 +11,7 @@
- [Testcases](#testcases) contains open-source designs such as Ariane, MemPool and NVDLA.
- [Enablements](#enablements) contains PDKs for open-source enablements such as NanGate45, ASAP7 and SKY130HD with FakeStack. Memories required by the designs are also included.
- [Flows](#flows) contains tool setups and runscripts for both proprietary and open-source SP&R tools such as Cadence Genus/Innovus and OpenROAD.
- [Code Elements](#code-elements) contains implementation of engines such as Clustering, Grouping, Gridding, Format translators required by Circuit Training flow.
- [Code Elements](#code-elements) contains implementation of engines such as Clustering, Grouping, Gridding as well as Format translators required by Circuit Training flow.
- [Baseline for Circuit Training](#baseline-for-circuit-training) provides a baseline for [Google Brain's Circuit Training](https://github.com/google-research/circuit_training).
- [FAQ](#faq)
- [Related Links](#related-links)
......@@ -57,7 +57,7 @@ We provide flop count, macro type and macro count for all the testcases in the t
<td class="tg-0lax">(256x32-bit SRAM) x 16 + (64x64-bit SRAM) x 4</td>
</tr>
<tr>
<td class="tg-0lax"><a href="./Testcases/mempool">MemPool Group</a></td>
<td class="tg-0lax"><a href="./Testcases/mempool">MemPool group</a></td>
<td class="tg-0lax">360724</td>
<td class="tg-0lax">(256x32-bit SRAM) x 256 + (64x64-bit SRAM) x 64 + (128x256-bit SRAM) x 2 + (128x32-bit SRAM) x 2</td>
</tr>
......@@ -67,7 +67,7 @@ We provide flop count, macro type and macro count for all the testcases in the t
<td class="tg-0lax">(256x64-bit SRAM) x 128</td>
</tr>
<tr>
<td class="tg-0lax"><a href="./Testcases/bp_quad">BlackParror</a></td>
<td class="tg-0lax"><a href="./Testcases/bp_quad">BlackParrot</a></td>
<td class="tg-0lax">214441</td>
<td class="tg-0lax">(512x64-bit SRAM) x 128 + (64x62-bit SRAM) x 32 + (32x32-bit SRAM) x 32 + (64x124-bit SRAM) x 16 + (128x16-bit SRAM) x 8 + (256x48-bit SRAM) x 4</td>
</tr>
......@@ -177,7 +177,7 @@ In the following table, we provide the status details of each testcase on each o
<td class="tg-0lax"><a href="./Flows/SKY130HD/mempool_tile">Link</a></td>
</tr>
<tr>
<td class="tg-0lax">MemPool Group</td>
<td class="tg-0lax">MemPool group</td>
<td class="tg-0lax"><a href="./Flows/NanGate45/mempool_group">Link</a></td>
<td class="tg-0lax"><a href="./Flows/NanGate45/mempool_group">Link</a></td>
<td class="tg-0lax">N/A</td>
......
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