Skip to content
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
13 changes: 13 additions & 0 deletions .github/workflows/chipdb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ on:
pull_request:

jobs:
family_info:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build family_info.json
run: |
docker pull pepijndevos/apicula:1.9.8
docker run -v $(pwd):/usr/src/apicula pepijndevos/apicula:1.9.8 make apycula/family_info.json
- name: Archive artifact
uses: actions/upload-artifact@v3
with:
name: family_info.json
path: apycula/family_info.json
gw1n1:
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ endif
.PHONY: all clean
all: apycula/GW1N-1.pickle apycula/GW1N-9.pickle apycula/GW1N-4.pickle \
apycula/GW1NS-2.pickle apycula/GW1NS-4.pickle apycula/GW1N-9C.pickle \
apycula/GW1NZ-1.pickle apycula/GW2A-18.pickle apycula/GW2A-18C.pickle
apycula/GW1NZ-1.pickle apycula/GW2A-18.pickle apycula/GW2A-18C.pickle \
family_info.json

%.json: apycula/dat19_h4x.py
python3 -m apycula.dat19_h4x $*
Expand All @@ -20,7 +21,12 @@ all: apycula/GW1N-1.pickle apycula/GW1N-9.pickle apycula/GW1N-4.pickle \
apycula/%.pickle: %_stage2.pickle
gzip -c $< > $@

apycula/family_info.json: apycula/build_family_info.py
python3 -m apycula.build_family_info
cp family_info.json apycula/

clean:
rm *.json
rm *.pickle
rm apycula/*.pickle
rm apycula/family_info.json
48 changes: 48 additions & 0 deletions apycula/build_family_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import json
import os
import subprocess
from collections import defaultdict

def build_family_aliases():
db_hashes = defaultdict(list)

family_info = defaultdict(dict)

# load IDCODEs from programmer.json
with open("/usr/src/gowin/IDE/bin/programmer.json") as f:
data = json.loads(f.read())
for device_data in data["DEVICE_CONFIG"]:
if device_data["DEVICE"] == "JTAG_NOP":
continue

family_info[device_data["DEVICE"]]["idcode"] = device_data["IDCODE"]

# if devices have the same *.fse hash, assume they are the same family
md5_exec = subprocess.run("md5sum /usr/src/gowin/IDE/share/device/*/*.fse",
shell=True, check=True, capture_output=True,
encoding='utf-8')

for line in md5_exec.stdout.splitlines():
computed_hash, path = line.split(" ")
family = os.path.split(path)[-1].replace(".fse", "")
db_hashes[computed_hash].append(family)

for computed_hash, families in db_hashes.items():
# arbitrarily use the shortest family as the "true" family
families.sort(key=lambda x: (len(x), x))

for family in families:
base_family = families[0]
family_info[family]["base_family"] = base_family

# if the family has no IDCODE, try to inherit from the base family
if "idcode" not in family_info[family] and "idcode" in family_info[base_family]:
family_info[family]["idcode"] = family_info[families[0]]["idcode"]

return family_info


if __name__ == "__main__":
family_aliases = build_family_aliases()
with open("family_info.json", "w") as f:
f.write(json.dumps(dict(family_aliases), indent=2))
13 changes: 13 additions & 0 deletions apycula/family_aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import importlib.resources
import json

def replace_family_alias(family):
with importlib.resources.path('apycula', f'family_info.json') as path:
with open(path, 'r') as f:
family_info = json.load(f)

if family in family_info:
return family_info[family]["base_family"]
else:
return family

24 changes: 20 additions & 4 deletions apycula/gowin_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from apycula import attrids
from apycula import bslib
from apycula.wirenames import wirenames, wirenumbers
from apycula.family_aliases import replace_family_alias

device = ""
pnr = None
Expand Down Expand Up @@ -1029,12 +1030,25 @@ def route(db, tilemap, pips):
for row, col in bits:
tile[row][col] = 1

def header_footer(db, bs, compress):
def header_footer(db, bs, compress, family):
"""
Generate fs header and footer
Currently limited to checksum with
CRC_check and security_bit_enable set
"""
# override part IDCODE in header
assert db.cmd_hdr[3][0] == 0x06 # IDCODE data

with importlib.resources.path('apycula', f'family_info.json') as path:
with open(path, 'r') as f:
family_info = json.load(f)

if family in family_info and "idcode" in family_info[family]:
db.cmd_hdr[3][-4:] = bytes.fromhex(family_info[family]["idcode"])
else:
print("Not overriding IDCODE as it is not present in family_info.json")

# calculate checksum
bs = np.fliplr(bs)
bs=np.packbits(bs)
# configuration data checksum is computed on all
Expand Down Expand Up @@ -1157,7 +1171,7 @@ def main():
parser.add_argument('--png')

args = parser.parse_args()
device = args.device
device = replace_family_alias(args.device)

with open(args.netlist) as f:
pnr = json.load(f)
Expand All @@ -1173,7 +1187,9 @@ def main():
mods = m.group(1) or ""
luts = m.group(3)
device = f"GW1N{mods}-{luts}"
with importlib.resources.path('apycula', f'{args.device}.pickle') as path:
device = replace_family_alias(device)

with importlib.resources.path('apycula', f'{device}.pickle') as path:
with closing(gzip.open(path, 'rb')) as f:
db = pickle.load(f)

Expand Down Expand Up @@ -1206,7 +1222,7 @@ def main():
tile[row][col] = 0

res = chipdb.fuse_bitmap(db, tilemap)
header_footer(db, res, args.compress)
header_footer(db, res, args.compress, device)
if pil_available and args.png:
bslib.display(args.png, res)
bslib.write_bitstream(args.output, res, db.cmd_hdr, db.cmd_ftr, args.compress)
Expand Down
3 changes: 2 additions & 1 deletion apycula/gowin_unpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from apycula import attrids
from apycula.bslib import read_bitstream
from apycula.wirenames import wirenames
from apycula.family_aliases import replace_family_alias

_device = ""
_pinout = ""
Expand Down Expand Up @@ -1074,7 +1075,7 @@ def main():
args = parser.parse_args()

global _device
_device = args.device
_device = replace_family_alias(args.device)
# For tool integration it is allowed to pass a full part number
m = re.match("GW1N(S?)[A-Z]*-(LV|UV|UX)([0-9])C?([A-Z]{2}[0-9]+P?)(C[0-9]/I[0-9])", _device)
if m:
Expand Down
10 changes: 5 additions & 5 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,16 @@ pll-tangnano4k.json: pll-tangnano4k-synth.json tangnano4k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NSR-LV4CQN48PC7/I6 --cst tangnano4k.cst

%-tangnano9k.fs: %-tangnano9k.json
gowin_pack -d GW1N-9C -o $@ $^
gowin_pack -d GW1NR-9C -o $@ $^

pll-nanolcd-tangnano9k.fs: pll-nanolcd-tangnano9k.json
gowin_pack -d GW1N-9C --sspi_as_gpio --mspi_as_gpio -o $@ $^
gowin_pack -d GW1NR-9C --sspi_as_gpio --mspi_as_gpio -o $@ $^

%-tangnano9k.json: %-tangnano9k-synth.json tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1N-9C --cst tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1NR-9C --cst tangnano9k.cst

%lvds-tangnano9k.json: %lvds-tangnano9k-synth.json lvds-tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1N-9C --cst lvds-tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1NR-9C --cst lvds-tangnano9k.cst

%-honeycomb.fs: %-honeycomb.json
gowin_pack -d GW1NS-2 -o $@ $<
Expand Down Expand Up @@ -264,7 +264,7 @@ pll-%-honeycomb-synth.json: pll/GW1NS-2C-%.vh pll.v pll/rpll.v
$(NEXTPNR) --json $< --write $@ --device GW1NSR-LV4CQN48PC7/I6 --cst longwires/tangnano4k.cst

%-lw-tangnano9k.json: %-tangnano9k-synth.json longwires/tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1N-9C --cst longwires/tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --family GW1NR-9C --cst longwires/tangnano9k.cst

%-lw-runber.json: %-runber-synth.json longwires/runber.cst
$(NEXTPNR) --json $< --write $@ --device GW1N-UV4LQ144C6/I5 --cst longwires/runber.cst
Expand Down
12 changes: 6 additions & 6 deletions examples/himbaechel/Makefile.himbaechel
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ clean:
# ============================================================
# Tangnano20k
%-tangnano20k.fs: %-tangnano20k.json
gowin_pack -d GW2A-18C -o $@ $<
gowin_pack -d GW2AR-18C -o $@ $<

%-tangnano20k.json: %-tangnano20k-synth.json tangnano20k.cst
$(NEXTPNR) --json $< --write $@ --device GW2AR-LV18QN88C8/I7 --vopt family=GW2A-18C --vopt cst=tangnano20k.cst
$(NEXTPNR) --json $< --write $@ --device GW2AR-LV18QN88C8/I7 --vopt family=GW2AR-18C --vopt cst=tangnano20k.cst

%-tangnano20k-synth.json: %.v
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=1 -p "read_verilog $^; synth_gowin -json $@"
Expand Down Expand Up @@ -223,7 +223,7 @@ blinky-pll-tangnano4k-synth.json: pll/GW1NS-4-dyn.vh blinky-pll-vr.v
gowin_pack -d GW1N-9C -o $@ $^

%-tangnano9k.json: %-tangnano9k-synth.json tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --vopt family=GW1N-9C --vopt cst=tangnano9k.cst
$(NEXTPNR) --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --vopt family=GW1NR-9C --vopt cst=tangnano9k.cst

%-tangnano9k-synth.json: %.v
$(YOSYS) -D LEDS_NR=6 -D OSC_TYPE_OSC -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"
Expand All @@ -232,7 +232,7 @@ pll-nanolcd-tangnano9k-synth.json: pll/GW1N-9C-dyn.vh pll-nanolcd/TOP.v pll-nano
$(YOSYS) -D INV_BTN=0 -p "read_verilog $^; synth_gowin -json $@"

pll-nanolcd-tangnano9k.fs: pll-nanolcd-tangnano9k.json
gowin_pack -d GW1N-9C --sspi_as_gpio --mspi_as_gpio -o $@ $^
gowin_pack -d GW1NR-9C --sspi_as_gpio --mspi_as_gpio -o $@ $^

# ============================================================
# szfpga (GW1N-9)
Expand Down Expand Up @@ -288,10 +288,10 @@ blinky-pll-runber-synth.json: pll/GW1N-4-dyn.vh blinky-pll.v
gowin_unpack -d GW1NS-4 -o $@ $^

%-tangnano9k-unpacked.v: %-tangnano9k.fs
gowin_unpack -d GW1N-9C -o $@ $^
gowin_unpack -d GW1NR-9C -o $@ $^

%-tangnano20k-unpacked.v: %-tangnano20k.fs
gowin_unpack -d GW2A-18C -o $@ $^
gowin_unpack -d GW2AR-18C -o $@ $^

%-runber-unpacked.v: %-runber.fs
gowin_unpack -d GW1N-4 -o $@ $^
Expand Down