Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hierarchical Placement Injection fails with a high number of variants #1083

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PlaceRouteHierFlow/PnR-pybind11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ PYBIND11_MODULE(PnR, m) {
.def( "ReadPrimitiveOffsetPitch", &PnRdatabase::ReadPrimitiveOffsetPitch)
.def_readwrite("hierTree", &PnRdatabase::hierTree)
.def_readwrite("topidx", &PnRdatabase::topidx)
.def_readwrite("use_external_placement_info", &PnRdatabase::use_external_placement_info)
.def_readwrite("gdsData2", &PnRdatabase::gdsData2)
.def_readwrite("lefData", &PnRdatabase::lefData)
.def_readwrite("DRC_info", &PnRdatabase::DRC_info)
Expand Down
12 changes: 5 additions & 7 deletions PlaceRouteHierFlow/PnRDB/PnRdatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ PnRDB::hierNode PnRdatabase::CheckoutHierNode(int nodeID, int sel) {

void PnRdatabase::AppendToHierTree(const PnRDB::hierNode& hN) { hierTree.push_back(hN); }


static void updateContact(PnRDB::contact& c) {
c.originBox = c.placedBox;
c.originCenter = c.placedCenter;
Expand Down Expand Up @@ -272,7 +271,6 @@ void PnRdatabase::TransformContact(PnRDB::contact& contact, PnRDB::point transla
TransformPoint(contact.originCenter, translate, width, height, ort, transform_type);
}


void PnRdatabase::TransformBbox(PnRDB::bbox& box, PnRDB::point translate, int width, int height, PnRDB::Omark ort, PnRDB::TransformType transform_type) {
int WW = width;
int HH = height;
Expand Down Expand Up @@ -502,7 +500,6 @@ void PnRdatabase::TransformNets(std::vector<PnRDB::net>& nets, PnRDB::point tran
}
}


PnRDB::Omark PnRdatabase::RelOrt2AbsOrt(PnRDB::Omark current_node_ort, PnRDB::Omark childnode_ort) {
/*
Inputs:
Expand Down Expand Up @@ -852,7 +849,10 @@ for(unsigned int i=0;i<hierTree[nodeID].Nets.size();i++){

lhs.instNum++;
b.gdsFile = updatedNode.gdsFile;
b.lefmaster = b.master + "_" + std::to_string(lhs.instNum - 1);
if (!use_external_placement_info)
b.lefmaster = b.master + "_" + std::to_string(lhs.instNum - 1);
else
b.lefmaster = b.master;
// update terminal to pin information

b.HPWL_extend_wo_terminal = updatedNode.HPWL_extend_wo_terminal;
Expand Down Expand Up @@ -1412,8 +1412,6 @@ void PnRdatabase::WriteGcellGlobalRoute(const PnRDB::hierNode& node, const strin
jsonStream.close();
}



// [RA] need confirmation -wbxu
void PnRdatabase::AddingPowerPins(PnRDB::hierNode& node) {
for (unsigned int i = 0; i < node.PowerNets.size(); i++) {
Expand Down Expand Up @@ -1722,7 +1720,7 @@ void PnRdatabase::semantic2() {
hierTree[i].Nets[k].upperBound = temp_LinearConst.upperBound;
for (unsigned int h = 0; h < hierTree[i].Nets[k].connected.size(); h++) {
// logger->debug("Connected {0} {1} {2}", hierTree[i].Nets[k].connected[h].type, hierTree[i].Nets[k].connected[h].iter,
// hierTree[i].Nets[k].connected[h].iter2);
// hierTree[i].Nets[k].connected[h].iter2);
for (unsigned int l = 0; l < temp_LinearConst.pins.size(); l++) {
// logger->debug("LinearConst cont {0} {1} {2}", temp_LinearConst.pins[l].first, temp_LinearConst.pins[l].second, temp_LinearConst.alpha[l]);
if (hierTree[i].Nets[k].connected[h].type == PnRDB::Block && hierTree[i].Nets[k].connected[h].iter2 == temp_LinearConst.pins[l].first &&
Expand Down
5 changes: 3 additions & 2 deletions PlaceRouteHierFlow/PnRDB/PnRdatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class PnRdatabase {

public:
int topidx;
bool use_external_placement_info = false;
PnRDB::Drc_info DRC_info;
vector<PnRDB::hierNode> hierTree; // each module in verilog file is a node
int ScaleFactor = 1;
Expand All @@ -96,7 +97,7 @@ class PnRdatabase {
PnRDB::hierNode CheckoutHierNode(int nodeID, int sel = -1); // check out data of specific hierarchical node
void AppendToHierTree(const PnRDB::hierNode &updatedNode); // append node to end of hierTree
void CheckinHierNode(int nodeID, const PnRDB::hierNode &updatedNode); // check out data of specific hierarchical node
std::vector<int> UsedInstancesIdx(int nodeID); // indices of used instances of a hiernode
std::vector<int> UsedInstancesIdx(int nodeID); // indices of used instances of a hiernode
void CheckinChildnodetoBlock(PnRDB::hierNode &parent, int blockID, const PnRDB::hierNode &updatedNode, PnRDB::Omark ort);
void updatePowerPins(PnRDB::pin &temp_pin);

Expand Down Expand Up @@ -171,7 +172,7 @@ class PnRdatabase {
void Write_Router_Report(PnRDB::hierNode &node, const string &opath);
void Write_Power_Mesh_Conf(std::string outputfile);
void Write_Current_Workload(PnRDB::hierNode &node, double total_current, int current_number, std::string outputfile);
PnRDB::Metal Find_Top_Middle_Metal(PnRDB::hierNode& node, const PnRDB::Drc_info& drc_info, int index);
PnRDB::Metal Find_Top_Middle_Metal(PnRDB::hierNode &node, const PnRDB::Drc_info &drc_info, int index);
};

#endif
8 changes: 5 additions & 3 deletions PlaceRouteHierFlow/placer/Placer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void Placer::setPlacementInfoFromJson(std::vector<PnRDB::hierNode>& nodeVec, str
design designData(nodeVec.back(), drcInfo);
int idx = 0;
//pad nodeVec to match the number of concretes in JSON file
for (const auto& m : modules) {
/**for (const auto& m : modules) {
if (m["abstract_name"] == designData.name) {
string concrete_template_name = m["concrete_name"];
unsigned int start = 0;
Expand All @@ -83,7 +83,7 @@ void Placer::setPlacementInfoFromJson(std::vector<PnRDB::hierNode>& nodeVec, str
idx = atoi(concrete_template_name.substr(start, end - start).c_str());
if (idx >= nodeVec.size()) nodeVec.insert(nodeVec.end(), idx + 1 - nodeVec.size(), nodeVec.back());
}
}
}**/
int nodeSize = nodeVec.size();
int mode = 0;
// Read design netlist and constraints
Expand All @@ -95,12 +95,14 @@ void Placer::setPlacementInfoFromJson(std::vector<PnRDB::hierNode>& nodeVec, str
std::vector<std::pair<SeqPair, ILP_solver>> spVec(nodeSize, make_pair(curr_sp, curr_sol));
for (const auto& m : modules) {
if (m["abstract_name"] == designData.name) {
if (m["concrete_name"] != designData.concrete_name) continue;
string concrete_template_name = m["concrete_name"];
unsigned int start = 0;
unsigned int slash = concrete_template_name.find_last_of('_');
if (slash != string::npos) start = slash + 1;
unsigned int end = concrete_template_name.size();
idx = atoi(concrete_template_name.substr(start, end - start).c_str());
//idx = atoi(concrete_template_name.substr(start, end - start).c_str());
idx = 0;
if (idx >= nodeSize) continue;
auto& sol = spVec[idx].second;
auto& sp = spVec[idx].first;
Expand Down
1 change: 1 addition & 0 deletions PlaceRouteHierFlow/placer/design.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ design::design(PnRDB::hierNode& node, PnRDB::Drc_info& drcInfo, const int seed)
_rng.seed(seed);
is_first_ILP = node.isFirstILP;
name = node.name;
concrete_name = node.concrete_name;
placement_id = node.placement_id;
bias_Vgraph = node.bias_Vgraph; // from node
bias_Hgraph = node.bias_Hgraph; // from node
Expand Down
1 change: 1 addition & 0 deletions PlaceRouteHierFlow/placer/design.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class design {
double maxBlockAreaSum = 0.;
double maxBlockHPWLSum = 0.;
string name = "";
string concrete_name = "";

// added by ya

Expand Down
1 change: 1 addition & 0 deletions align/pnr/build_pnr_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def _ReadVerilogJson( DB, j, add_placement_info=False):

temp_node = PnR.hierNode()
temp_node.name = module['name'] if 'name' in module else module['abstract_name']
temp_node.concrete_name = module['concrete_name'] if 'concrete_name' in module else module['name']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hiernode needs concrete name, so that the placer can match placement json file to each hiernode

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevenmburns It seems the PnRDB is build in this function, not in C++ code. Is it possible to parse the concrete name in this function?

temp_node.isCompleted = 0

Terminals = []
Expand Down
50 changes: 26 additions & 24 deletions align/pnr/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from ..schema import constraint, types
from ..cell_fabric import transformation
import json
import copy
import pathlib
import more_itertools
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -94,60 +95,60 @@ def _transform_leaf(module, instance, leaf):
flat_leaf['concrete_name'] = leaf['concrete_name']
flat_leaf['name'] = instance['instance_name'] + '/' + name
flat_leaf['transformation'] = transformation.Transformation.mult(tr_inst, tr_leaf).toDict()
module['leaves'].append(flat_leaf)
module['flat_leaves'].append(flat_leaf)


def _flatten_leaves(placement, concrete_name):
""" transform leaf coordinates to top level """
module = placement['modules'][concrete_name]
module['leaves'] = []
module['flat_leaves'] = []
for instance in module['instances']:
leaf = placement['leaves'].get(instance['concrete_template_name'], False)
leaf = placement['flat_leaves'].get(instance['concrete_template_name'], False)
if leaf:
_transform_leaf(module, instance, leaf)
else:
leaves = _flatten_leaves(placement, instance['concrete_template_name'])
for leaf in leaves:
_transform_leaf(module, instance, leaf)
return module['leaves']
return module['flat_leaves']


def _check_place_on_grid(leaf, constraints):
def _check_place_on_grid(flat_leaf, constraints):
for const in constraints:
if const['direction'] == 'H':
o, s = leaf['transformation']['oY'], leaf['transformation']['sY']
o, s = flat_leaf['transformation']['oY'], flat_leaf['transformation']['sY']
else:
o, s = leaf['transformation']['oX'], leaf['transformation']['sX']
o, s = flat_leaf['transformation']['oX'], flat_leaf['transformation']['sX']

is_satisfied = False
for term in const['ored_terms']:
for offset in term['offsets']:
if (o - offset) % const['pitch'] == 0 and s in term['scalings']:
is_satisfied = True
logger.debug(f'{leaf["name"]} satisfied {term} in {const}')
logger.debug(f'{flat_leaf["name"]} satisfied {term} in {const}')
break
if is_satisfied:
break
assert is_satisfied, f'{leaf} does not satisfy {const}'
assert is_satisfied, f'{flat_leaf} does not satisfy {const}'


def check_place_on_grid(placement_verilog_d, concrete_name, opath):

if False:
# Load JSON file for easier debug
filename = (pathlib.Path(opath) / f'{concrete_name}.scaled_placement_verilog.json')
with (filename).open('rt') as fp:
placement_dict = json.load(fp)
else:
placement_dict = placement_verilog_d
# If we don't do the copy, then we get the 'flat_leaves" field filled in placement_verilog_d (can be large)
# We might want to use an auxillary data structure instead

placement_verilog_d_copy = copy.deepcopy(placement_verilog_d)

placement = dict()
placement['leaves'] = {x['concrete_name']: x for x in placement_dict['leaves']}
placement['modules'] = {x['concrete_name']: x for x in placement_dict['modules']}
leaves = _flatten_leaves(placement, concrete_name)
placement['flat_leaves'] = {x['concrete_name']: x for x in placement_verilog_d_copy['leaves']}
placement['modules'] = {x['concrete_name']: x for x in placement_verilog_d_copy['modules']}

print(placement)

flat_leaves = _flatten_leaves(placement, concrete_name)

constrained_cns = dict()
all_cns = {x['concrete_name'] for x in leaves}
all_cns = {x['concrete_name'] for x in flat_leaves}
for cn in all_cns:
filename = pathlib.Path(opath) / '../inputs' / f'{cn}.json'
if filename.exists() and filename.is_file():
Expand All @@ -158,7 +159,8 @@ def check_place_on_grid(placement_verilog_d, concrete_name, opath):
if place_on_grids:
constrained_cns[cn] = place_on_grids

if constrained_cns:
for leaf in leaves:
if leaf['concrete_name'] in constrained_cns:
_check_place_on_grid(leaf, constrained_cns[leaf['concrete_name']])
for flat_leaf in flat_leaves:
if flat_leaf['concrete_name'] in constrained_cns:
_check_place_on_grid(flat_leaf, constrained_cns[flat_leaf['concrete_name']])


15 changes: 11 additions & 4 deletions align/pnr/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,11 @@ def generate_pnr(topology_dir, primitive_dir, pdk_dir, output_dir, subckt, *, pr
toplevel_args_d=toplevel_args_d, results_dir=None,
placer_sa_iterations=placer_sa_iterations)

with open("__placer_dump__.json", "wt") as fp:
os.chdir(current_working_dir)

with (working_dir / "__placer_dump__.json").open('wt') as fp:
json.dump((top_level, leaf_map, [(nm, verilog_d.dict()) for nm, verilog_d in placement_verilog_alternatives.items()],metrics), fp=fp, indent=2)

os.chdir(current_working_dir)

elif '3_pnr:gui' in steps_to_run or '3_pnr:route' in steps_to_run:
with (working_dir / "__placer_dump__.json").open('rt') as fp:
Expand All @@ -360,11 +361,11 @@ def generate_pnr(topology_dir, primitive_dir, pdk_dir, output_dir, subckt, *, pr
else:
placements_to_run = None

with open("__placements_to_run__.json", "wt") as fp:
with (working_dir / "__placements_to_run__.json").open("wt") as fp:
json.dump(placements_to_run, fp=fp, indent=2)

elif '3_pnr:route' in steps_to_run:
with open("__placements_to_run__.json", "rt") as fp:
with (working_dir / "__placements_to_run__.json").open("rt") as fp:
placements_to_run = json.load(fp)

variants = defaultdict(defaultdict)
Expand Down Expand Up @@ -401,6 +402,8 @@ def generate_pnr(topology_dir, primitive_dir, pdk_dir, output_dir, subckt, *, pr
verilog_ds_to_run=verilog_ds_to_run)


print(results_name_map)

os.chdir(current_working_dir)

for variant, (path_name, layout_idx, DB) in results_name_map.items():
Expand All @@ -417,6 +420,8 @@ def generate_pnr(topology_dir, primitive_dir, pdk_dir, output_dir, subckt, *, pr
toplevel=hN.isTop,
pnr_const_ds=pnr_const_ds)

print(variant)

if hN.isTop:
variants[variant].update(result)

Expand All @@ -427,4 +432,6 @@ def generate_pnr(topology_dir, primitive_dir, pdk_dir, output_dir, subckt, *, pr
variants[variant][tag] = path


print(variants)

return variants
24 changes: 19 additions & 5 deletions align/pnr/manipulate_hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def manipulate_hierarchy(verilog_d, subckt):
clean_if_extra(verilog_d, subckt)
check_modules(verilog_d)

def change_concrete_names_for_routing(scaled_placement_verilog_d):
def change_abstract_and_concrete_names_for_routing(scaled_placement_verilog_d):
leaf_ctns = [leaf['concrete_name'] for leaf in scaled_placement_verilog_d['leaves']]

p = re.compile(r'^(.+)_(\d+)$')
Expand All @@ -133,8 +133,14 @@ def change_concrete_names_for_routing(scaled_placement_verilog_d):

logger.debug(f'change_concrete_names_for_routing: {tr_tbl}')

an_cn_pairs = []

for module in scaled_placement_verilog_d['modules']:
module['concrete_name'] = tr_tbl[module['concrete_name']]
cn = module['concrete_name']
module['concrete_name'] = tr_tbl[cn]
an_cn_pairs.append((module['abstract_name'], module['concrete_name']))
module['abstract_name'] = module['concrete_name']

for instance in module['instances']:
ctn = instance['concrete_template_name']
if ctn in leaf_ctns:
Expand All @@ -143,17 +149,22 @@ def change_concrete_names_for_routing(scaled_placement_verilog_d):
else:
assert ctn in tr_tbl
instance['concrete_template_name'] = tr_tbl[ctn]
instance['abstract_template_name'] = tr_tbl[ctn]

if 'flat_leaves' in module:
del module['flat_leaves']


for leaf in scaled_placement_verilog_d['leaves']:
leaf['abstract_name'] =leaf['concrete_name']
leaf['abstract_name'] = leaf['concrete_name']

return tr_tbl
return tr_tbl, an_cn_pairs

def gen_abstract_verilog_d( verilog_d):
new_verilog_d = copy.deepcopy(verilog_d)

if 'leaves' in new_verilog_d:
new_verilog_d['leaves'] = None
del new_verilog_d['leaves']

for module in new_verilog_d['modules']:
assert 'concrete_name' in module
Expand All @@ -169,9 +180,12 @@ def gen_abstract_verilog_d( verilog_d):
for instance in module['instances']:
assert 'concrete_template_name' in instance
del instance['concrete_template_name']

assert 'transformation' in instance
del instance['transformation']

assert 'flat_leaves' not in module

return new_verilog_d

def connectivity_change_for_partial_routing(scaled_placement_verilog_d, primitives):
Expand Down
7 changes: 5 additions & 2 deletions align/pnr/placer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ def place( *, DB, opath, fpath, numLayout, effort, idx, lambda_coeff, select_in_

if modules_d is not None:
hyper.use_external_placement_info = True
DB.use_external_placement_info = True
hyper.placement_info_json = json.dumps(modules_d, indent=2)
print(hyper.placement_info_json)
else:
logger.info(f'Starting bottom-up placement on {DB.hierTree[idx].name} {idx}')

Expand Down Expand Up @@ -275,7 +277,7 @@ def update_grid_constraints(grid_constraints, DB, idx, verilog_d, primitives, sc
if 'constraints' not in leaf:
leaf['constraints'] = []

leaf['constraints'].extend(constraint for constraint in primitive['metadata']['constraints'])
leaf['constraints'].extend(primitive['metadata']['constraints'])

top_name = f'{hN.name}_{sel}'
gen_constraints(scaled_placement_verilog_d, top_name)
Expand Down Expand Up @@ -326,7 +328,8 @@ def hierarchical_place(*, DB, opath, fpath, numLayout, effort, verilog_d,


top_level, leaf_map, placement_verilog_alternatives, metrics = process_placements(DB=DB, verilog_d=verilog_d,
lambda_coeff=lambda_coeff, scale_factor=scale_factor,
lambda_coeff=lambda_coeff,
scale_factor=scale_factor,
opath=opath)

return top_level, leaf_map, placement_verilog_alternatives, metrics
Expand Down
Loading