2024-12-10 22:48:07 +08:00
|
|
|
#
|
|
|
|
# nextpnr -- Next Generation Place and Route
|
|
|
|
#
|
|
|
|
# Copyright (C) 2024 The Project Peppercorn Authors.
|
|
|
|
#
|
|
|
|
# Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
|
|
# copyright notice and this permission notice appear in all copies.
|
|
|
|
#
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
#
|
|
|
|
|
|
|
|
import os
|
|
|
|
from os import path
|
|
|
|
import sys
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
sys.path.append(path.join(path.dirname(__file__), "../../.."))
|
|
|
|
from himbaechel_dbgen.chip import *
|
|
|
|
|
2024-12-20 18:03:10 +08:00
|
|
|
PIP_EXTRA_MUX = 1
|
|
|
|
PIP_EXTRA_CPE = 2
|
2024-12-10 22:48:07 +08:00
|
|
|
|
2024-12-25 21:36:33 +08:00
|
|
|
MUX_INVERT = 1
|
|
|
|
MUX_VISIBLE = 2
|
2025-01-06 21:15:05 +08:00
|
|
|
MUX_CONFIG = 4
|
2025-01-08 21:08:41 +08:00
|
|
|
MUX_CPE_INV = 8
|
2024-12-25 21:36:33 +08:00
|
|
|
|
2024-12-10 22:48:07 +08:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("--lib", help="Project Peppercorn python database script path", type=str, required=True)
|
|
|
|
parser.add_argument("--device", help="name of device to export", type=str, required=True)
|
|
|
|
parser.add_argument("--bba", help="bba file to write", type=str, required=True)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
sys.path.append(os.path.expanduser(args.lib))
|
|
|
|
sys.path += args.lib
|
2024-12-27 17:04:18 +08:00
|
|
|
import chip
|
2024-12-10 22:48:07 +08:00
|
|
|
import die
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class PipExtraData(BBAStruct):
|
2024-12-20 18:03:10 +08:00
|
|
|
pip_type: int
|
2024-12-10 22:48:07 +08:00
|
|
|
name: IdString
|
|
|
|
bits: int = 0
|
|
|
|
value: int = 0
|
2024-12-16 18:19:56 +08:00
|
|
|
invert: int = 0
|
2024-12-10 22:48:07 +08:00
|
|
|
|
|
|
|
def serialise_lists(self, context: str, bba: BBAWriter):
|
|
|
|
pass
|
|
|
|
def serialise(self, context: str, bba: BBAWriter):
|
|
|
|
bba.u32(self.name.index)
|
2024-12-16 18:19:56 +08:00
|
|
|
bba.u8(self.bits)
|
|
|
|
bba.u8(self.value)
|
|
|
|
bba.u8(self.invert)
|
2024-12-20 18:03:10 +08:00
|
|
|
bba.u8(self.pip_type)
|
2024-12-10 22:48:07 +08:00
|
|
|
|
|
|
|
def set_timings(ch):
|
|
|
|
speed = "DEFAULT"
|
|
|
|
tmg = ch.set_speed_grades([speed])
|
|
|
|
|
|
|
|
def main():
|
|
|
|
# Range needs to be +1, but we are adding +2 more to coordinates, since
|
|
|
|
# they are starting from -2 instead of zero required for nextpnr
|
2024-12-27 17:04:18 +08:00
|
|
|
dev = chip.get_device(args.device)
|
|
|
|
ch = Chip("gatemate", args.device, dev.max_col() + 3, dev.max_row() + 3)
|
2024-12-10 22:48:07 +08:00
|
|
|
# Init constant ids
|
|
|
|
ch.strs.read_constids(path.join(path.dirname(__file__), "..", "constids.inc"))
|
|
|
|
ch.read_gfxids(path.join(path.dirname(__file__), "..", "gfxids.inc"))
|
|
|
|
|
|
|
|
for type_name in die.get_tile_type_list():
|
|
|
|
tt = ch.create_tile_type(type_name)
|
|
|
|
for group in die.get_groups_for_type(type_name):
|
|
|
|
tt.create_group(group.name, group.type)
|
|
|
|
for wire in die.get_endpoints_for_type(type_name):
|
|
|
|
tt.create_wire(wire.name, wire.type)
|
|
|
|
for prim in die.get_primitives_for_type(type_name):
|
|
|
|
bel = tt.create_bel(prim.name, prim.type, prim.z)
|
2024-12-18 18:46:38 +08:00
|
|
|
for pin in die.get_primitive_pins(prim.type):
|
2025-01-03 22:06:52 +08:00
|
|
|
tt.add_bel_pin(bel, pin.name, die.get_pin_connection_name(prim,pin), pin.dir)
|
2024-12-10 22:48:07 +08:00
|
|
|
for mux in die.get_mux_connections_for_type(type_name):
|
|
|
|
pp = tt.create_pip(mux.src, mux.dst)
|
2024-12-25 21:36:33 +08:00
|
|
|
mux_flags = MUX_INVERT if mux.invert else 0
|
|
|
|
mux_flags |= MUX_VISIBLE if mux.visible else 0
|
2025-01-06 21:15:05 +08:00
|
|
|
mux_flags |= MUX_CONFIG if mux.config else 0
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(mux.name), mux.bits, mux.value, mux_flags)
|
2024-12-16 18:19:56 +08:00
|
|
|
if "CPE" in type_name:
|
2024-12-20 18:03:10 +08:00
|
|
|
pp = tt.create_pip("CPE.IN1", "CPE.RAM_O2")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_CPE,ch.strs.id("RAM_O2"))
|
2025-01-13 20:16:58 +08:00
|
|
|
pp = tt.create_pip("CPE.IN1", "CPE.RAM_O1")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_CPE,ch.strs.id("RAM_O1"))
|
2025-01-08 21:08:41 +08:00
|
|
|
for i in range(1,9):
|
|
|
|
tt.create_wire(f"CPE.V_IN{i}", "CPE_VIRTUAL_WIRE")
|
|
|
|
pp = tt.create_pip(f"CPE.V_IN{i}", f"CPE.IN{i}")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(f"CPE.IN{i}_INV"), 1, i, 0)
|
|
|
|
pp = tt.create_pip(f"CPE.V_IN{i}", f"CPE.IN{i}")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(f"CPE.IN{i}_INV"), 1, i, MUX_CPE_INV | MUX_INVERT)
|
2025-01-10 16:16:23 +08:00
|
|
|
tt.create_wire("CPE.V_CLK", "CPE_VIRTUAL_WIRE")
|
|
|
|
pp = tt.create_pip("CPE.V_CLK", "CPE.CLK")
|
2025-01-14 21:21:50 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.CLK_INV"), 1, 0, 0)
|
2025-01-10 16:16:23 +08:00
|
|
|
pp = tt.create_pip("CPE.V_CLK", "CPE.CLK")
|
2025-01-14 21:21:50 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.CLK_INV"), 1, 1, MUX_CPE_INV| MUX_INVERT)
|
|
|
|
tt.create_wire("CPE.V_EN", "CPE_VIRTUAL_WIRE")
|
|
|
|
pp = tt.create_pip("CPE.V_EN", "CPE.EN")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.EN_INV"), 1, 0, 0)
|
|
|
|
pp = tt.create_pip("CPE.V_EN", "CPE.EN")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.EN_INV"), 1, 1, MUX_CPE_INV| MUX_INVERT)
|
|
|
|
tt.create_wire("CPE.V_SR", "CPE_VIRTUAL_WIRE")
|
|
|
|
pp = tt.create_pip("CPE.V_SR", "CPE.SR")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.SR_INV"), 1, 0, 0)
|
|
|
|
pp = tt.create_pip("CPE.V_SR", "CPE.SR")
|
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id("CPE.SR_INV"), 1, 1, MUX_CPE_INV| MUX_INVERT)
|
2024-12-20 16:38:14 +08:00
|
|
|
if "GPIO" in type_name:
|
|
|
|
tt.create_wire("GPIO.OUT_D1", "WIRE_INTERNAL")
|
|
|
|
tt.create_wire("GPIO.OUT_D2", "WIRE_INTERNAL")
|
2024-12-21 19:24:26 +08:00
|
|
|
#tt.create_wire("GPIO.OUT_Q1", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.OUT_Q2", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.OUT_CLK","WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.CLK_INT","WIRE_INTERNAL")
|
2024-12-20 16:38:14 +08:00
|
|
|
|
|
|
|
pp = tt.create_pip("GPIO.OUT1", "GPIO.OUT_D1")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT1_4"), 1, 0, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
pp = tt.create_pip("GPIO.OUT4", "GPIO.OUT_D1")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT1_4"), 1, 1, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
|
|
|
|
pp = tt.create_pip("GPIO.OUT2", "GPIO.OUT_D2")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT2_3"), 1, 0, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
pp = tt.create_pip("GPIO.OUT3", "GPIO.OUT_D2")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT2_3"), 1, 1, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
|
|
|
|
pp = tt.create_pip("GPIO.OUT_D1","GPIO.DO")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT23_14_SEL"), 1, 0, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
pp = tt.create_pip("GPIO.OUT_D2","GPIO.DO")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT23_14_SEL"), 1, 1, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
|
|
|
|
|
|
|
|
pp = tt.create_pip("GPIO.OUT2","GPIO.OE")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OE_SIGNAL"), 2, 1, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
pp = tt.create_pip("GPIO.OUT3","GPIO.OE")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OE_SIGNAL"), 2, 2, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
pp = tt.create_pip("GPIO.OUT4","GPIO.OE")
|
2024-12-25 21:36:33 +08:00
|
|
|
pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OE_SIGNAL"), 2, 3, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.OUT4", "GPIO.CLK_INT")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.CLK_1_4"), 1, 0, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.OUT1", "GPIO.CLK_INT")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.CLK_1_4"), 1, 1, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
|
|
|
|
#pp = tt.create_pip("GPIO.CLK_INT", "GPIO.OUT_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.SEL_OUT_CLOCK"), 1, 1, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK1", "GPIO.OUT_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT_CLOCK"), 2, 0, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK2", "GPIO.OUT_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT_CLOCK"), 2, 1, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK3", "GPIO.OUT_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT_CLOCK"), 2, 2, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK4", "GPIO.OUT_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.OUT_CLOCK"), 2, 3, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
#tt.create_wire("GPIO.IN_D1", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.IN_D2", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.IN_Q1", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.IN_Q2", "WIRE_INTERNAL")
|
|
|
|
#tt.create_wire("GPIO.IN_CLK","WIRE_INTERNAL")
|
|
|
|
|
|
|
|
#pp = tt.create_pip("GPIO.CLK_INT", "GPIO.IN_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.SEL_IN_CLOCK"), 1, 1, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK1", "GPIO.IN_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.IN_CLOCK"), 2, 0, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK2", "GPIO.IN_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.IN_CLOCK"), 2, 1, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK3", "GPIO.IN_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.IN_CLOCK"), 2, 2, MUX_VISIBLE)
|
2024-12-21 19:24:26 +08:00
|
|
|
#pp = tt.create_pip("GPIO.CLOCK4", "GPIO.IN_CLK")
|
2024-12-25 21:36:33 +08:00
|
|
|
#pp.extra_data = PipExtraData(PIP_EXTRA_MUX,ch.strs.id("GPIO.IN_CLOCK"), 2, 3, MUX_VISIBLE)
|
2024-12-20 16:38:14 +08:00
|
|
|
|
|
|
|
tt.create_pip("GPIO.DI", "GPIO.IN1")
|
|
|
|
tt.create_pip("GPIO.DI", "GPIO.IN2")
|
|
|
|
|
2024-12-10 22:48:07 +08:00
|
|
|
# Setup tile grid
|
2024-12-27 17:04:18 +08:00
|
|
|
for x in range(dev.max_col() + 3):
|
|
|
|
for y in range(dev.max_row() + 3):
|
|
|
|
ch.set_tile_type(x, y, dev.get_tile_type(x - 2,y - 2))
|
2024-12-10 22:48:07 +08:00
|
|
|
# Create nodes between tiles
|
2024-12-27 17:04:18 +08:00
|
|
|
for _,nodes in dev.get_connections():
|
2024-12-10 22:48:07 +08:00
|
|
|
node = []
|
|
|
|
for conn in nodes:
|
2025-01-08 21:08:41 +08:00
|
|
|
conn.name = conn.name.replace("CPE.IN", "CPE.V_IN")
|
2025-01-08 22:02:56 +08:00
|
|
|
conn.name = conn.name.replace("CPE.CLK", "CPE.V_CLK")
|
2024-12-10 22:48:07 +08:00
|
|
|
node.append(NodeWire(conn.x + 2, conn.y + 2, conn.name))
|
|
|
|
ch.add_node(node)
|
|
|
|
set_timings(ch)
|
2024-12-17 02:21:32 +08:00
|
|
|
|
2024-12-27 21:34:12 +08:00
|
|
|
for package in dev.get_packages():
|
|
|
|
pkg = ch.create_package(package)
|
|
|
|
for pad in dev.get_package_pads(package):
|
|
|
|
pkg.create_pad(pad.name, f"X{pad.x+2}Y{pad.y+2}", pad.bel, pad.function, pad.bank)
|
2024-12-17 02:21:32 +08:00
|
|
|
|
2024-12-10 22:48:07 +08:00
|
|
|
ch.write_bba(args.bba)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|