diff options
Diffstat (limited to 'generic/examples')
-rw-r--r-- | generic/examples/.gitignore | 4 | ||||
-rw-r--r-- | generic/examples/README.md | 5 | ||||
-rw-r--r-- | generic/examples/__init__.py | 0 | ||||
-rw-r--r-- | generic/examples/bitstream.py | 17 | ||||
-rw-r--r-- | generic/examples/report.py | 13 | ||||
-rw-r--r-- | generic/examples/simple.py | 22 | ||||
-rwxr-xr-x | generic/examples/simple.sh | 2 | ||||
-rw-r--r-- | generic/examples/simple_config.py | 15 | ||||
-rw-r--r-- | generic/examples/write_fasm.py | 52 |
9 files changed, 92 insertions, 38 deletions
diff --git a/generic/examples/.gitignore b/generic/examples/.gitignore index 83d79a7d..38e95de5 100644 --- a/generic/examples/.gitignore +++ b/generic/examples/.gitignore @@ -1 +1,3 @@ -blinky.txt +blinky.fasm +__pycache__ +*.pyc diff --git a/generic/examples/README.md b/generic/examples/README.md index dd154a51..9fd106d9 100644 --- a/generic/examples/README.md +++ b/generic/examples/README.md @@ -7,7 +7,8 @@ This contains a simple, artificial, example of the nextpnr generic API. - simple_timing.py annotates cells with timing data (this is a separate script that must be run after packing) - - report.py stores design information after place-and-route to blinky.txt in place - of real bitstream generation + - write_fasm.py uses the nextpnr Python API to write a FASM file for a design + + - bitstream.py uses write_fasm.py to create a FASM ("FPGA assembly") file for the place-and-routed design - Run simple.sh to build an example design on the FPGA above
\ No newline at end of file diff --git a/generic/examples/__init__.py b/generic/examples/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/generic/examples/__init__.py diff --git a/generic/examples/bitstream.py b/generic/examples/bitstream.py new file mode 100644 index 00000000..1ab94f0c --- /dev/null +++ b/generic/examples/bitstream.py @@ -0,0 +1,17 @@ +from write_fasm import * +from simple_config import K + +# Need to tell FASM generator how to write parameters +# (celltype, parameter) -> ParameterConfig +param_map = { + ("GENERIC_SLICE", "K"): ParameterConfig(write=False), + ("GENERIC_SLICE", "INIT"): ParameterConfig(write=True, numeric=True, width=2**K), + ("GENERIC_SLICE", "FF_USED"): ParameterConfig(write=True, numeric=True, width=1), + + ("GENERIC_IOB", "INPUT_USED"): ParameterConfig(write=True, numeric=True, width=1), + ("GENERIC_IOB", "OUTPUT_USED"): ParameterConfig(write=True, numeric=True, width=1), + ("GENERIC_IOB", "ENABLE_USED"): ParameterConfig(write=True, numeric=True, width=1), +} + +with open("blinky.fasm", "w") as f: + write_fasm(ctx, param_map, f)
\ No newline at end of file diff --git a/generic/examples/report.py b/generic/examples/report.py deleted file mode 100644 index c43367fa..00000000 --- a/generic/examples/report.py +++ /dev/null @@ -1,13 +0,0 @@ -with open("blinky.txt", "w") as f: - for nname, net in ctx.nets: - print("# Net %s" % nname, file=f) - # FIXME: Pip ordering - for wire, pip in net.wires: - if pip.pip != "": - print("%s" % pip.pip, file=f) - print("", file=f) - for cname, cell in ctx.cells: - print("# Cell %s at %s" % (cname, cell.bel), file=f) - for param, val in cell.params: - print("%s.%s %s" % (cell.bel, param, val), file=f) - print("", file=f)
\ No newline at end of file diff --git a/generic/examples/simple.py b/generic/examples/simple.py index f87a6049..9339b68a 100644 --- a/generic/examples/simple.py +++ b/generic/examples/simple.py @@ -1,22 +1,4 @@ -# Grid size including IOBs at edges -X = 12 -Y = 12 -# SLICEs per tile -N = 8 -# LUT input count -K = 4 -# Number of local wires -Wl = N*(K+1) + 8 -# 1/Fc for bel input wire pips -Si = 4 -# 1/Fc for Q to local wire pips -Sq = 4 -# ~1/Fc local to neighbour local wire pips -Sl = 8 - -# Create graphic elements -# Bels -ctx.addDecalGraphic("bel", GraphicElement(type=TYPE_BOX, style=STYLE_INACTIVE, x1=0, y1=0, x2=0.2, y2=(1/(N+1))-0.02, z=0)) +from simple_config import * def is_io(x, y): return x == 0 or x == X-1 or y == 0 or y == Y-1 @@ -41,7 +23,6 @@ for x in range(X): ctx.addBelInput(bel="X%dY%d_IO%d" % (x, y, z), name="I", wire="X%dY%dZ%d_I0" % (x, y, z)) ctx.addBelInput(bel="X%dY%d_IO%d" % (x, y, z), name="EN", wire="X%dY%dZ%d_I1" % (x, y, z)) ctx.addBelOutput(bel="X%dY%d_IO%d" % (x, y, z), name="O", wire="X%dY%dZ%d_Q" % (x, y, z)) - ctx.setBelDecal(bel="X%dY%d_IO%d" % (x, y, z), decalxy=ctx.DecalXY("bel", 0.6, z * (1/(N+1)))) else: for z in range(N): ctx.addBel(name="X%dY%d_SLICE%d" % (x, y, z), type="GENERIC_SLICE", loc=Loc(x, y, z), gb=False) @@ -49,7 +30,6 @@ for x in range(X): for k in range(K): ctx.addBelInput(bel="X%dY%d_SLICE%d" % (x, y, z), name="I[%d]" % k, wire="X%dY%dZ%d_I%d" % (x, y, z, k)) ctx.addBelOutput(bel="X%dY%d_SLICE%d" % (x, y, z), name="Q", wire="X%dY%dZ%d_Q" % (x, y, z)) - ctx.setBelDecal(bel="X%dY%d_SLICE%d" % (x, y, z), decalxy=ctx.DecalXY("bel", 0.6, z * (1/(N+1)))) for x in range(X): for y in range(Y): diff --git a/generic/examples/simple.sh b/generic/examples/simple.sh index 2e8d6180..576a6418 100755 --- a/generic/examples/simple.sh +++ b/generic/examples/simple.sh @@ -1,4 +1,4 @@ #!/usr/bin/bash set -ex yosys -p "tcl ../synth/synth_generic.tcl 4 blinky.json" blinky.v -../../nextpnr-generic --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route report.py
\ No newline at end of file +../../nextpnr-generic --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route bitstream.py
\ No newline at end of file diff --git a/generic/examples/simple_config.py b/generic/examples/simple_config.py new file mode 100644 index 00000000..dfb38f1c --- /dev/null +++ b/generic/examples/simple_config.py @@ -0,0 +1,15 @@ +# Grid size including IOBs at edges +X = 12 +Y = 12 +# SLICEs per tile +N = 8 +# LUT input count +K = 4 +# Number of local wires +Wl = N*(K+1) + 8 +# 1/Fc for bel input wire pips +Si = 4 +# 1/Fc for Q to local wire pips +Sq = 4 +# ~1/Fc local to neighbour local wire pips +Sl = 8
\ No newline at end of file diff --git a/generic/examples/write_fasm.py b/generic/examples/write_fasm.py new file mode 100644 index 00000000..fb55c41d --- /dev/null +++ b/generic/examples/write_fasm.py @@ -0,0 +1,52 @@ +from collections import namedtuple + +""" + write: set to True to enable writing this parameter to FASM + + numeric: set to True to write this parameter as a bit array (width>1) or + single bit (width==1) named after the parameter. Otherwise this + parameter will be written as `name.value` + + width: width of numeric parameter (ignored for non-numeric parameters) + + alias: an alternative name for this parameter (parameter name used if alias + is None) +""" +ParameterConfig = namedtuple('ParameterConfig', 'write numeric width alias') + +# FIXME use defaults= once Python 3.7 is standard +ParameterConfig.__new__.__defaults__ = (False, True, 1, None) + + +""" +Write a design as FASM + + ctx: nextpnr context + paramCfg: ParameterConfig describing how to write parameters + f: output file +""" +def write_fasm(ctx, paramCfg, f): + for nname, net in sorted(ctx.nets, key=lambda x: str(x[1].name)): + print("# Net %s" % nname, file=f) + for wire, pip in sorted(net.wires, key=lambda x: str(x[1])): + if pip.pip != "": + print("%s" % pip.pip, file=f) + print("", file=f) + for cname, cell in sorted(ctx.cells, key=lambda x: str(x[1].name)): + print("# Cell %s at %s" % (cname, cell.bel), file=f) + for param, val in sorted(cell.params, key=lambda x: str(x)): + cfg = paramCfg[(cell.type, param)] + if not cfg.write: + continue + fasm_name = cfg.alias if cfg.alias is not None else param + if cfg.numeric: + if cfg.width == 1: + if int(val) != 0: + print("%s.%s" % (cell.bel, fasm_name), file=f) + else: + # Parameters with width >32 are direct binary, otherwise denary + binval = val if cfg.width > 32 else "{:0{}b}".format(int(val), cfg.width) + print("%s.%s[%d:0] = %d'b%s" % (cell.bel, fasm_name, cfg.width-1, cfg.width, binval), file=f) + else: + print("%s.%s.%s" % (cell.bel, fasm_name, val), file=f) + print("", file=f)
\ No newline at end of file |