-
Notifications
You must be signed in to change notification settings - Fork 67
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
Get info about packages/pins from the IDE files. #57
Changes from 1 commit
9e4bcd3
687676a
b68cecb
ceb3897
f5024b2
30171b2
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 |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
from apycula import chipdb | ||
|
||
class Bba(object): | ||
|
||
def __init__(self, file): | ||
self.file = file | ||
self.block_idx = Counter() | ||
|
@@ -20,7 +20,7 @@ def write_value(val): | |
|
||
def str(self, val, sep="|"): | ||
self.file.write(f"str {sep}{val}{sep}\n") | ||
|
||
@contextmanager | ||
def block(self, prefix="block"): | ||
idx = self.block_idx[prefix] | ||
|
@@ -147,6 +147,17 @@ def write_timing(b, timing): | |
b.u32(len(timing)) | ||
b.ref(blk) | ||
|
||
def write_partnumber_packages(b, db): | ||
import ipdb; ipdb.set_trace() | ||
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. uh breakpoints should go I think haha 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.
The structure has changed: a table with packages has been added. |
||
with b.block("partnumber_packages") as blk: | ||
for partnumber, pkg_rec in db.packages.items(): | ||
pkg, device = pkg_rec | ||
b.u32(id_string(partnumber)) | ||
b.u32(id_string(pkg)) | ||
b.u32(id_string(device)) | ||
b.u32(len(db.packages)) | ||
b.ref(blk) | ||
|
||
pin_re = re.compile(r"IO([TBRL])(\d+)([A-Z])") | ||
def iob2bel(db, name): | ||
banks = {'T': [(1, n) for n in range(1, db.cols)], | ||
|
@@ -189,6 +200,7 @@ def write_chipdb(db, f, device): | |
write_grid(b, db.grid) | ||
write_global_aliases(b, db) | ||
write_timing(b, db.timing) | ||
write_partnumber_packages(b, db) | ||
write_pinout(b, db) | ||
id_strings(b) | ||
b.post(f'EmbeddedFile chipdb_file_{cdev}("gowin/chipdb-{device}.bin", {blk});') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,88 @@ | ||
import pandas as pd | ||
from os.path import expanduser | ||
from glob import glob | ||
|
||
docdir = expanduser("~/Documents/gowinsemi/") | ||
files = glob(docdir+"*Pinout.xlsx") | ||
import json | ||
import os | ||
import csv | ||
|
||
VeryTrue = 2 | ||
|
||
def get_package(series, package, special_pins, header): | ||
fname = None | ||
for f in files: | ||
if "%s Pinout" % series in f: | ||
fname = f | ||
break | ||
assert fname, "No file found for {}".format(series) | ||
# caches | ||
# .CSV index of vendor files {(device, package) : file_name} | ||
_pindef_index = {} | ||
# (device, package) : pins | ||
_pindef_files = {} | ||
|
||
def get_package(device, package, special_pins): | ||
global _pindef_files | ||
if (device, package) not in _pindef_files: | ||
gowinhome = os.getenv("GOWINHOME") | ||
if not gowinhome: | ||
raise Exception("GOWINHOME not set") | ||
with open(_pindef_index[(device, package)]) as f: | ||
pins = json.load(f) | ||
_pindef_files[(device, package)] = [d for d in pins['PIN_DATA'] if d['TYPE'] == 'I/O'] | ||
|
||
df = pd.read_excel(fname, sheet_name="Pin List", header=header, engine='openpyxl') | ||
df = df.dropna(subset=[package]) | ||
df = df[df['Function']=="I/O"] | ||
if special_pins != VeryTrue: | ||
df = df[df["Configuration Function"] != "RECONFIG_N"] # can't be output | ||
df = df[~df["Configuration Function"].str.startswith("JTAGSEL_N", na=False)] # dedicated pin | ||
pins = [pin for pin in _pindef_files[(device, package)] | ||
if 'CFG' not in pin.keys() or ( | ||
pin['CFG'] != 'RECONFIG_N' and not pin['CFG'].startswith('JTAGSEL_N'))] | ||
else: | ||
pins = _pindef_files[(device, package)] | ||
if not special_pins: | ||
df = df[df["Configuration Function"].isna()] | ||
return df | ||
|
||
def all_packages(series, start, header): | ||
df = get_package(series, "Pin Name", True, header) | ||
return list(df.columns[start:]) | ||
return [pin for pin in pins if 'CFG' not in pin.keys()] | ||
return pins | ||
|
||
def get_pins(series, package, special_pins=False, header=0): | ||
df = get_package(series, package, special_pins, header) | ||
df = df[["BANK", package]].astype("int32") | ||
return df.groupby("BANK")[package].apply(list).to_dict() | ||
# {partnumber : (pkg, device)} | ||
def all_packages(device): | ||
gowinhome = os.getenv("GOWINHOME") | ||
if not gowinhome: | ||
raise Exception("GOWINHOME not set") | ||
global _pindef_index | ||
_pindef_index = {} | ||
res = {} | ||
with open(f"{gowinhome}/IDE/data/device/device_package.csv", mode='r') as csv_file: | ||
csv_reader = csv.DictReader(csv_file, fieldnames = | ||
["unused_id", "partnumber", "series", "device", "package", "filename"]) | ||
for row in csv_reader: | ||
if row['device'] != device: | ||
continue | ||
res[row['partnumber']] = (row['package'], device) | ||
_pindef_index[(row['device'], row['package'])] = \ | ||
f"{gowinhome}/IDE/data/device/{row['filename']}" | ||
return res | ||
|
||
def get_bank_pins(series, header = 0): | ||
df = get_package(series, "Pin Name", VeryTrue, header) | ||
# bad table for GW1N-1 | ||
if series == "GW1N-1": | ||
df.loc[df['Pin Name'] == 'IOB2B', ['BANK']] = 2 | ||
dpins = list(map(lambda x:x.split('/')[0], df['Pin Name'].to_list())) | ||
dbanks = df['BANK'].astype("int32").to_list() | ||
return dict(zip(dpins, dbanks)) | ||
def get_pins(device, package, special_pins=False): | ||
df = get_package(device, package, special_pins) | ||
res = {} | ||
for pin in df: | ||
res.setdefault(str(pin['BANK']), []).append(str(pin['INDEX'])) | ||
return res | ||
|
||
def get_locs(series, package, special_pins=False, header=0): | ||
df = get_package(series, package, special_pins, header) | ||
return {p.split('/')[0] for p in df["Pin Name"]} | ||
def get_bank_pins(device, package): | ||
df = get_package(device, package, VeryTrue) | ||
res = {} | ||
for pin in df: | ||
res[pin['NAME']] = str(pin['BANK']) | ||
return res | ||
|
||
def get_pin_locs(series, package, special_pins=False, header=0): | ||
def tryint(n): | ||
try: | ||
return int(n) | ||
except: | ||
return n | ||
def get_locs(device, package, special_pins=False): | ||
df = get_package(device, package, special_pins) | ||
res = set() | ||
for pin in df: | ||
res.update({pin['NAME']}) | ||
return res | ||
|
||
df = get_package(series, package, special_pins, header) | ||
return {tryint(num): p.split('/')[0] for _, num, p in df[[package, "Pin Name"]].itertuples()} | ||
def get_pin_locs(device, package, special_pins=False): | ||
df = get_package(device, package, special_pins) | ||
res = {} | ||
for pin in df: | ||
res[str(pin['INDEX'])] = pin['NAME'] | ||
return res | ||
|
||
def get_clock_locs(series, package, header=0): | ||
df = get_package(series, package, True, header) | ||
df = df[df["Configuration Function"].str.startswith("GCLK", na=False)] | ||
return {tuple(p.split('/')) for p in df["Pin Name"]} | ||
def get_clock_locs(device, package): | ||
df = get_package(device, package, True) | ||
return [(pin['NAME'], *pin['CFG'].split('/')) for pin in df | ||
if 'CFG' in pin.keys() and pin['CFG'].startswith("GCLK")] | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,25 +33,22 @@ | |
|
||
params = { | ||
"GW1NS-2": { | ||
"package": "LQ144", | ||
"header": 0, | ||
"package": "LQFP144", | ||
"device": "GW1NS-2C-LQ144-5", | ||
"partnumber": "GW1NS-UX2CLQ144C5/I4", | ||
}, | ||
"GW1N-9": { | ||
"package": "PG256", | ||
"header": 0, | ||
"package": "PBGA256", | ||
"device": "GW1N-9-PBGA256-6", | ||
"partnumber": "GW1N-LV9PG256C6/I5", | ||
}, | ||
"GW1N-4": { | ||
"package": "PG256", | ||
"header": 0, | ||
"package": "PBGA256", | ||
"device": "GW1N-4-PBGA256-6", | ||
"partnumber": "GW1N-LV4PG256C6/I5", | ||
}, | ||
"GW1N-1": { | ||
"package": "LQ144", | ||
"package": "LQFP144", | ||
"header": 1, # stupid note in excel | ||
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. this header can go |
||
"device": "GW1N-1-LQFP144-6", | ||
"partnumber": "GW1N-LV1LQ144C6/I5", | ||
|
@@ -464,9 +461,7 @@ def run_pnr(mod, constr, config): | |
|
||
db = chipdb.from_fse(fse) | ||
db.timing = tm | ||
db.pinout = chipdb.xls_pinout(device) | ||
# pin <-> bank | ||
db.pin_bank = pindef.get_bank_pins(device, params['header']) | ||
db.packages, db.pinout, db.pin_bank = chipdb.xls_pinout(device) | ||
|
||
corners = [ | ||
(0, 0, fse['header']['grid'][61][0][0]), | ||
|
@@ -480,7 +475,7 @@ def run_pnr(mod, constr, config): | |
for col, typ in enumerate(row_dat): | ||
locations.setdefault(typ, []).append((row, col)) | ||
|
||
pin_names = pindef.get_locs(device, params['package'], True, params['header']) | ||
pin_names = pindef.get_locs(device, params['package'], True) | ||
edges = {'T': fse['header']['grid'][61][0], | ||
'B': fse['header']['grid'][61][-1], | ||
'L': [row[0] for row in fse['header']['grid'][61]], | ||
|
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.
maybe this shouldn't be called xls when it's not excel based ;)