-
Notifications
You must be signed in to change notification settings - Fork 69
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
Generate primitives with multiple aspect ratios and then use the placer to decide which to choose. #671
Generate primitives with multiple aspect ratios and then use the placer to decide which to choose. #671
Changes from all commits
00271d9
879165b
20e4fc2
26982b0
6efc6c2
2776f1c
dd78c8f
b2f8221
ce9ec32
9f01d19
e95a4e7
20ec0c0
1cd6ac4
aba8237
7f614c3
60ec256
fb1d0f8
540990e
16dcf73
d3c7a60
a14d809
5354470
f90889a
6b07cf1
8480ad1
b749441
a61f323
599a5d3
da60b3b
2106354
39ab7d9
b2be114
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,7 +82,7 @@ class PnRdatabase | |
int unitScale; | ||
map<string, vector<PnRDB::lefMacro> > lefData; //map from Macro name to Macro Instance | ||
public: | ||
map<string, string> gdsData; //map from gds name to gds file | ||
map<string, vector<string> > gdsData2; //map from gds name to multiple gds file (abstract to multiple concrete) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @854768750 I added this as the C++ data structure of the new mapping. |
||
private: | ||
PnRDB::designRule drData; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ | |
import shutil | ||
import os | ||
import json | ||
import re | ||
import copy | ||
from collections import defaultdict | ||
|
||
from .compiler import generate_hierarchy | ||
from .primitive import generate_primitive | ||
|
@@ -33,6 +36,59 @@ def build_steps( flow_start, flow_stop): | |
return steps_to_run | ||
|
||
|
||
def gen_more_primitives( primitives, topology_dir, subckt): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kkunal1408 @arvuce22 This is the code that needs to be moved upstream in the flow, either topology, or primitives or both. |
||
"""primitives dictiionary updated in place""" | ||
|
||
map_d = defaultdict(list) | ||
|
||
# As a hack, add more primitives if it matches this pattern | ||
p = re.compile( r'^(\S+)_nfin(\d+)_n(\d+)_X(\d+)_Y(\d+)(|_\S+)$') | ||
|
||
more_primitives = {} | ||
|
||
for k,v in primitives.items(): | ||
m = p.match(k) | ||
if m: | ||
logger.info( f'Matched primitive {k}') | ||
nfin,n,X,Y = tuple(int(x) for x in m.groups()[1:5]) | ||
abstract_name = f'{m.groups()[0]}_nfin{nfin}{m.groups()[5]}' | ||
map_d[abstract_name].append( k) | ||
if X != Y: | ||
concrete_name = f'{m.groups()[0]}_nfin{nfin}_n{n}_X{Y}_Y{X}{m.groups()[5]}' | ||
map_d[abstract_name].append( concrete_name) | ||
if concrete_name not in primitives and \ | ||
concrete_name not in more_primitives: | ||
more_primitives[concrete_name] = copy.deepcopy(v) | ||
more_primitives[concrete_name]['x_cells'] = Y | ||
more_primitives[concrete_name]['y_cells'] = X | ||
else: | ||
logger.warning( f'Didn\'t match primitive {k}') | ||
map_d[k].append( k) | ||
|
||
primitives.update( more_primitives) | ||
|
||
concrete2abstract = { vv:k for k,v in map_d.items() for vv in v} | ||
|
||
for k,v in primitives.items(): | ||
v['abstract_template_name'] = concrete2abstract[k] | ||
v['concrete_template_name'] = k | ||
|
||
# now hack the netlist to replace the template names using the concrete2abstract mapping | ||
|
||
with (topology_dir / f'{subckt}.verilog.json').open( 'rt') as fp: | ||
verilog_json_d = json.load(fp) | ||
|
||
for module in verilog_json_d['modules']: | ||
for instance in module['instances']: | ||
t = instance['template_name'] | ||
if t in concrete2abstract: | ||
del instance['template_name'] | ||
instance['abstract_template_name'] = concrete2abstract[t] | ||
|
||
with (topology_dir / f'{subckt}.verilog.json').open( 'wt') as fp: | ||
json.dump( verilog_json_d, fp=fp, indent=2) | ||
|
||
|
||
def schematic2layout(netlist_dir, pdk_dir, netlist_file=None, subckt=None, working_dir=None, flatten=False, unit_size_mos=10, unit_size_cap=10, nvariants=1, effort=0, check=False, extract=False, log_level=None, verbosity=None, generate=False, python_gds_json=True, regression=False, uniform_height=False, render_placements=False, PDN_mode=False, flow_start=None, flow_stop=None): | ||
|
||
steps_to_run = build_steps( flow_start, flow_stop) | ||
|
@@ -92,6 +148,9 @@ def schematic2layout(netlist_dir, pdk_dir, netlist_file=None, subckt=None, worki | |
if '1_topology' in steps_to_run: | ||
topology_dir.mkdir(exist_ok=True) | ||
primitives = generate_hierarchy(netlist, subckt, topology_dir, flatten, pdk_dir, uniform_height) | ||
|
||
gen_more_primitives( primitives, topology_dir, subckt) | ||
|
||
with (topology_dir / 'primitives.json').open( 'wt') as fp: | ||
json.dump( primitives, fp=fp, indent=2) | ||
else: | ||
|
@@ -111,7 +170,7 @@ def schematic2layout(netlist_dir, pdk_dir, netlist_file=None, subckt=None, worki | |
pnr_dir = working_dir / '3_pnr' | ||
if '3_pnr' in steps_to_run: | ||
pnr_dir.mkdir(exist_ok=True) | ||
variants = generate_pnr(topology_dir, primitive_dir, pdk_dir, pnr_dir, subckt, nvariants=nvariants, effort=effort, check=check, extract=extract, gds_json=python_gds_json, render_placements=render_placements, PDN_mode=PDN_mode) | ||
variants = generate_pnr(topology_dir, primitive_dir, pdk_dir, pnr_dir, subckt, primitives=primitives, nvariants=nvariants, effort=effort, check=check, extract=extract, gds_json=python_gds_json, render_placements=render_placements, PDN_mode=PDN_mode) | ||
results.append( (netlist, variants)) | ||
assert len(variants) >= 1, f"No layouts were generated for {netlist}. Cannot proceed further. See LOG/align.log for last error." | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
import json | ||
import re | ||
from itertools import chain | ||
from collections import defaultdict | ||
|
||
from .. import PnR | ||
from ..schema.hacks import VerilogJsonTop | ||
|
@@ -12,56 +13,6 @@ | |
|
||
NType = PnR.NType | ||
|
||
def analyze_hN( tag, hN, beforeAddingBlockPins=False): | ||
logger.info( f'{tag} name {hN.name}') | ||
|
||
logger.info( f'Nets and PowerNets') | ||
for net in chain( hN.Nets, hN.PowerNets): | ||
logger.info( f' {net.name}') | ||
for conn in net.connected: | ||
if conn.type == NType.Block: | ||
if 0 <= conn.iter2 < len(hN.Blocks): | ||
blk = hN.Blocks[conn.iter2] | ||
inst = blk.instance[0] | ||
|
||
if 0 <= conn.iter < len(inst.blockPins): | ||
|
||
logger.info( f' {conn.type} {conn.iter} ({inst.blockPins[conn.iter].name}) {conn.iter2} ({inst.name} {inst.master})') | ||
else: | ||
logger.info( f' {conn.type} {conn.iter} (<out of range>) {conn.iter2} ({inst.name} {inst.master})') | ||
|
||
else: | ||
logger.info( f' {conn.type} {conn.iter} (<unknown>) {conn.iter2} (<out of range>)') | ||
elif conn.type == NType.Terminal: | ||
assert conn.iter2 == -1 | ||
if 0 <= conn.iter < len(hN.Terminals): | ||
logger.info( f' {conn.type} {conn.iter} ({hN.Terminals[conn.iter].name})') | ||
else: | ||
logger.info( f' {conn.type} {conn.iter} (<out of range>)') | ||
|
||
logger.info( f'PowerNets (second pass)') | ||
for net in hN.PowerNets: | ||
logger.info( f' {net.name}') | ||
for conn in net.dummy_connected: | ||
if 0 <= conn.iter2 < len(hN.Blocks): | ||
blk = hN.Blocks[conn.iter2] | ||
logger.info( f' blk.selectedInstance={blk.selectedInstance}') | ||
for inst_idx,inst in enumerate(blk.instance): | ||
if beforeAddingBlockPins: | ||
if 0 <= conn.iter < len(inst.dummy_power_pin): | ||
logger.info( f' {conn.iter} ({inst.dummy_power_pin[conn.iter].name}) {conn.iter2} ({inst.name} {inst.master}) inst_idx={inst_idx}') | ||
else: | ||
logger.info( f' {conn.iter} (<out of range>) {conn.iter2} ({inst.name} {inst.master}) inst_idx={inst_idx}') | ||
else: | ||
logger.info( f' {conn.iter} (<unknown>) {conn.iter2} (<out of range>)') | ||
|
||
logger.info( f'Blocks') | ||
for blk in hN.Blocks: | ||
logger.info( f' blk.child={blk.child} len(blk.instance)={len(blk.instance)} blk.selectedInstance={blk.selectedInstance} blk.instNum={blk.instNum}') | ||
for inst in blk.instance: | ||
logger.info( f' inst.name={inst.name} inst.master={inst.master} len(inst.dummy_power_pin)={len(inst.dummy_power_pin)}') | ||
|
||
|
||
def ReadVerilogJson( DB, j): | ||
hierTree = [] | ||
|
||
|
@@ -91,7 +42,13 @@ def ReadVerilogJson( DB, j): | |
temp_blockComplex = PnR.blockComplex() | ||
current_instance = PnR.block() | ||
|
||
current_instance.master = instance['template_name'] | ||
if 'template_name' in instance: | ||
current_instance.master = instance['template_name'] | ||
elif 'abstract_template_name' in instance: | ||
current_instance.master = instance['abstract_template_name'] | ||
else: | ||
assert False, f'Missing template_name (abstract or otherwise) in instance {instance}' | ||
|
||
current_instance.name = instance['instance_name'] | ||
|
||
blockPins = [] | ||
|
@@ -148,15 +105,16 @@ def process_connection( iter, net_name): | |
def _ReadMap( path, mapname): | ||
d = pathlib.Path(path) | ||
p = re.compile( r'^(\S+)\s+(\S+)\s*$') | ||
tbl = {} | ||
tbl2 = defaultdict(list) | ||
with (d / mapname).open( "rt") as fp: | ||
for line in fp: | ||
line = line.rstrip('\n') | ||
m = p.match(line) | ||
assert m | ||
k, v = m.groups() | ||
tbl[k] = str(d / v) | ||
return tbl | ||
tbl2[k].append( str(d / v)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @854768750 Here tbl2 is the python version of the map from abstract name to list of concrete names. |
||
logger.debug( f'expanded table: {tbl2}') | ||
return tbl2 | ||
|
||
def _attach_constraint_files( DB, fpath): | ||
d = pathlib.Path(fpath) | ||
|
@@ -190,7 +148,7 @@ def PnRdatabase( path, topcell, vname, lefname, mapname, drname): | |
DB.ReadPDKJSON( path + '/' + drname) | ||
|
||
_ReadLEF( DB, path, lefname) | ||
DB.gdsData = _ReadMap( path, mapname) | ||
DB.gdsData2 = _ReadMap( path, mapname) | ||
|
||
j = None | ||
if vname.endswith(".verilog.json"): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@854768750 I just fir checked if the abstract_template_name was in gdsData2. If not, I'll skip the whole process if cap is in the name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently this does not cause error on capacitor because capplacer is not functioning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine because, seems in BUFFER_VREFP1, Dcap is just like other ordinary primitives.