Skip to content
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

gowin: Himbaechel arch #1184

Merged
merged 39 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3bc88d0
wip start
yrabbit Jun 28, 2023
e54f7aa
generate bba
yrabbit Jun 28, 2023
9139fef
gowin: Add himbaechel arch
yrabbit Jun 28, 2023
c344914
gowin: add global VCC and VSS networks
yrabbit Jun 30, 2023
995fd23
gowin: add support for all DFF types
yrabbit Jun 30, 2023
fbae840
gowin: Himbaechel, fix style
yrabbit Jul 1, 2023
3e4edfb
gowin: Himbaechel. Add a wideluts
yrabbit Jul 2, 2023
8576708
gowin: Himbaechel. Add ALU.
yrabbit Jul 5, 2023
d101fe8
gowin: Himbaechel. Add the LUTRAM
yrabbit Jul 6, 2023
b4712ff
gowin: Himbaechel. Add a clock router.
yrabbit Jul 12, 2023
27bfbbc
gowin: Himbaechel. Add bundle data generation.
yrabbit Jul 12, 2023
cf94939
gowin: Himbaechel. Add constraint file processing.
yrabbit Jul 14, 2023
c07f5ef
gowin: Himbaechel. Implement the GSR primitive
yrabbit Jul 19, 2023
3b9ac71
gowin: Himbaechel. Use pin functions info
yrabbit Jul 20, 2023
3522e00
gowin: Himbaechel. Implement PLLs
yrabbit Jul 22, 2023
4f9919e
gowin: Himbaechel. Add extra chip data
yrabbit Jul 23, 2023
91e09ef
gowin: Himbaechel. Add simplified IO
yrabbit Jul 25, 2023
80a359b
gowin: Himbaechel. Add redundant checks
yrabbit Jul 27, 2023
c250bef
gowin: Himbaechel. Add SERDES and differential IO
yrabbit Aug 6, 2023
41c328b
gowin: Himbaechel. Add OSER8
yrabbit Aug 7, 2023
cf5f952
gowin: Himbaechel. Add OSER10 and OVIDEO
yrabbit Aug 8, 2023
a8570f3
gowin: Himbaechel. Add IDES primitives
yrabbit Aug 10, 2023
bc1c67a
gowin: Himbaechel. Unify the creation of tail types
yrabbit Aug 12, 2023
eac2eb1
gowin: Himbaechel. Add OSER16 and IDES16
yrabbit Aug 13, 2023
83835e4
gowin: Himbaechel. Add the GW1N-4 simple IOs
yrabbit Aug 15, 2023
0c41254
gowin: Himbaechel. Fix DESER and PLL
yrabbit Aug 17, 2023
422de29
Merge branch 'master' into h-gw
yrabbit Aug 17, 2023
8925b86
gowin: Himbaechel. Refactor.
yrabbit Aug 17, 2023
a9f3bb2
gowin: Himbaechel. Improve error messages
yrabbit Aug 17, 2023
da2fc67
gowin: Himbaechel. Fix IO for GW1NZ-1
yrabbit Aug 19, 2023
e597fca
Merge branch 'master' into h-gw
yrabbit Aug 19, 2023
7af5270
gowin: Himbaechel. Add rough CMake stuff
yrabbit Aug 19, 2023
cf7dd93
gowin: Himbaechel. Improve CMake thing a little
yrabbit Aug 19, 2023
9bfb0cf
gowin: Himbaechel. Handling of disabled units
yrabbit Aug 21, 2023
40e23a7
gowin: Himbaechel. Install bases
yrabbit Aug 23, 2023
251e511
Merge branch 'master' into h-gw
yrabbit Aug 25, 2023
44bd264
gowin: Himbaechel. Fix problems.
yrabbit Aug 25, 2023
6fd0dab
Merge branch 'master' into h-gw
yrabbit Aug 30, 2023
6a1842f
Merge branch 'master' into h-gw
yrabbit Aug 30, 2023
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
3 changes: 2 additions & 1 deletion himbaechel/family.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(HIMBAECHEL_UARCHES "example")
set(HIMBAECHEL_UARCHES "example;gowin")
foreach(uarch ${HIMBAECHEL_UARCHES})
add_subdirectory(${family}/uarch/${uarch})
aux_source_directory(${family}/uarch/${uarch} HM_UARCH_FILES)
foreach(target ${family_targets})
target_sources(${target} PRIVATE ${HM_UARCH_FILES})
Expand Down
86 changes: 81 additions & 5 deletions himbaechel/himbaechel_dbgen/chip.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ def create_pip(self, src: str, dst: str):
def has_wire(self, wire: str):
# Check if a wire has already been created
return self.strs.id(wire) in self._wire2idx
def set_wire_type(self, wire: str, type: str):
# wire type change
self.wires[self._wire2idx[self.strs.id(wire)]].wire_type = self.strs.id(type)
def serialise_lists(self, context: str, bba: BBAWriter):
# list children of members
for i, bel in enumerate(self.bels):
Expand Down Expand Up @@ -371,6 +374,62 @@ def serialise(self, context: str, bba: BBAWriter):
bba.ref(f"{context}_extra_data")
else:
bba.u32(0)

@dataclass
class PadInfo(BBAStruct):
# package pin name
package_pin: IdString
# reference to corresponding bel
tile: IdString
bel: IdString
# function name
pad_function: IdString
# index of pin bank
pad_bank: int
# extra pad flags
flags: int
extra_data: object = None

def serialise_lists(self, context: str, bba: BBAWriter):
if self.extra_data is not None:
self.extra_data.serialise_lists(f"{context}_extra_data", bba)
bba.label(f"{context}_extra_data")
self.extra_data.serialise(f"{context}_extra_data", bba)
def serialise(self, context: str, bba: BBAWriter):
bba.u32(self.package_pin.index)
bba.u32(self.tile.index)
bba.u32(self.bel.index)
bba.u32(self.pad_function.index)
bba.u32(self.pad_bank)
bba.u32(self.flags)
if self.extra_data is not None:
bba.ref(f"{context}_extra_data")
else:
bba.u32(0)

@dataclass
class PackageInfo(BBAStruct):
strs: StringPool
name: IdString
pads: list[int] = field(default_factory=list)

def create_pad(self, package_pin: str, tile: str, bel: str, pad_function: str, pad_bank: int, flags: int = 0):
pad = PadInfo(package_pin = self.strs.id(package_pin), tile = self.strs.id(tile), bel = self.strs.id(bel),
pad_function = self.strs.id(pad_function), pad_bank = pad_bank, flags = flags)
self.pads.append(pad)
return pad

def serialise_lists(self, context: str, bba: BBAWriter):
for i, pad in enumerate(self.pads):
pad.serialise_lists(f"{context}_pad{i}", bba)
bba.label(f"{context}_pads")
for i, pad in enumerate(self.pads):
pad.serialise(f"{context}_pad{i}", bba)

def serialise(self, context: str, bba: BBAWriter):
bba.u32(self.name.index)
bba.slice(f"{context}_pads", len(self.pads))

class Chip:
def __init__(self, uarch: str, name: str, width: int, height: int):
self.strs = StringPool()
Expand All @@ -385,6 +444,7 @@ def __init__(self, uarch: str, name: str, width: int, height: int):
self.node_shape_idx = dict()
self.tile_shapes = []
self.tile_shapes_idx = dict()
self.packages = []
self.extra_data = None
def create_tile_type(self, name: str):
tt = TileType(self.strs, self.strs.id(name))
Expand Down Expand Up @@ -449,6 +509,11 @@ def flatten_tile_shapes(self):
self.tile_shapes_idx[key] = tile.shape_idx
print(f"{len(self.tile_shapes)} unique tile routing shapes")

def create_package(self, name: str):
pkg = PackageInfo(self.strs, self.strs.id(name))
self.packages.append(pkg)
return pkg

def serialise(self, bba: BBAWriter):
self.flatten_tile_shapes()
# TODO: preface, etc
Expand All @@ -459,11 +524,17 @@ def serialise(self, bba: BBAWriter):
shp.serialise_lists(f"nshp{i}", bba)
for i, tsh in enumerate(self.tile_shapes):
tsh.serialise_lists(f"tshp{i}", bba)
for i, pkg in enumerate(self.packages):
pkg.serialise_lists(f"pkg{i}", bba)
for y, row in enumerate(self.tiles):
for x, tinst in enumerate(row):
tinst.serialise_lists(f"tinst_{x}_{y}", bba)

self.strs.serialise_lists(f"constids", bba)
if self.extra_data is not None:
self.extra_data.serialise_lists("extra_data", bba)
bba.label("extra_data")
self.extra_data.serialise("extra_data", bba)

bba.label(f"tile_types")
for i, tt in enumerate(self.tile_types):
Expand All @@ -474,6 +545,9 @@ def serialise(self, bba: BBAWriter):
bba.label(f"tile_shapes")
for i, tsh in enumerate(self.tile_shapes):
tsh.serialise(f"tshp{i}", bba)
bba.label(f"packages")
for i, pkg in enumerate(self.packages):
pkg.serialise(f"pkg{i}", bba)
bba.label(f"tile_insts")
for y, row in enumerate(self.tiles):
for x, tinst in enumerate(row):
Expand All @@ -496,16 +570,18 @@ def serialise(self, bba: BBAWriter):
bba.slice("tile_insts", self.width*self.height)
bba.slice("node_shapes", len(self.node_shapes))
bba.slice("tile_shapes", len(self.tile_shapes))
# packages: not yet used
bba.u32(0)
bba.u32(0)
# packages
bba.slice("packages", len(self.packages))
# speed grades: not yet used
bba.u32(0)
bba.u32(0)
# db-defined constids
bba.ref("constids")
# extra data: not yet used
bba.u32(0)
# extra data
if self.extra_data is not None:
bba.ref("extra_data")
else:
bba.u32(0)

def write_bba(self, filename):
with open(filename, "w") as f:
Expand Down
2 changes: 2 additions & 0 deletions himbaechel/uarch/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
message(STATUS "Configuring Himbaechel-Example uarch")

37 changes: 37 additions & 0 deletions himbaechel/uarch/gowin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
message(STATUS "Configuring Himbaechel-Gowin uarch")
cmake_minimum_required(VERSION 3.5)
project(himbaechel-gowin-chipdb NONE)

find_package(Python3 3.5 REQUIRED COMPONENTS Interpreter)
set(ALL_HIMBAECHEL_GOWIN_DEVICES GW1N-1 GW1NZ-1 GW1NS-2 GW1N-4 GW1N-9 GW1N-9C GW1NS-4 GW2A-18 GW2A-18C)
set(ALL_HIMBAECHEL_GOWIN_DEVICES "")
set(HIMBAECHEL_GOWIN_DEVICES ${ALL_HIMBAECHEL_GOWIN_DEVICES} CACHE STRING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have this default to none for now so building nextpnr himbaechel doesn't require the gowin binary?

I still want to work a bit more on the user experience for building nextpnr-himbaechel and device databases, then maybe we can revisit this when nextpnr-himbaechel has replaced the old nextpnr-gowin.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you tell me more about the build process of nextpnr-himbaechel and device databases? This is something I care about in YoWASP. It is not feasible to ship one binary that includes every binary and every chipdb due to size constraints (about 100 MB) and I would rather avoid configuring and building nextpnr several times if at all feasible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to provide a unified framework for arches to share one nextpnr binary with a reduced amount of per-arch code, and with a relatively compact deduplicated representation. Gowin will move there first and I will also look at xo2/3 moving to it. Longer term if it works out there will be more migrations and new arches using it.

It is going to have the chipdb binaries as data files (which should in every case be significantly less than 100MB). These will be configurable in the build process and in the next few days there should be a nice discovery process for those so you can pass the name of a device on the command line and it will load the right subarch and chipdb automatically (it'll be a relative path based approach similar to Yosys, I need to look exactly what we do for different arches and build environments there still).

I would guess, once it reaches a point of being end user ready (i.e. the legacy nextpnr-gowin is formally deprecated and then removed in favour of this), we'd have one nextpnr-himbaechel package and then another containing the chip databases per arch.

Copy link
Member

@whitequark whitequark Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Can you make sure every architecture (~ user-visible package) gets its own directory under share/ and nothing outside of this directory is installed? Then I will be able to ship this nicely in YoWASP.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that matches what I was planning

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic! Then what I will do in yowasp-nextpnr-himbaechel is to pull in all of the chipdbs that yowasp-nextpnr-${ARCH} have registered using the standard Python "entry points" (plugin) mechanism and mount them under share/. Ideally that in itself will be enough.

Do you plan to have e.g. a nextpnr-ecp5 runner that proxies to nextpnr-himbaechel --uarch ecp5? This could be done by snooping argv[0] (checking if it ends with -ecp5, etc) and it would greatly simplify migration for Amaranth.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this could definitely be done as part of the migration path. Although I realise a bit more work around the himbaechel startup and API is needed to support arbitrary command line arguments, which is needed both for backwards compatibility and a friendly CLI in general.

"Include support for these Gowin devices (available: ${ALL_HIMBAECHEL_GOWIN_DEVICES})")
message(STATUS "Enabled Himbaechel-Gowin devices: ${HIMBAECHEL_GOWIN_DEVICES}")

set(chipdb_binaries)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chipdb)
foreach(device ${HIMBAECHEL_GOWIN_DEVICES})
if(NOT device IN_LIST ALL_HIMBAECHEL_GOWIN_DEVICES)
message(FATAL_ERROR "Device ${device} is not a supported Gowin device")
endif()

set(device_bba chipdb/chipdb-${device}.bba)
set(device_bin chipdb/chipdb-${device}.bin)
add_custom_command(
OUTPUT ${device_bin}
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gowin_arch_gen.py -d ${device} -o ${device_bba}
COMMAND bbasm ${BBASM_ENDIAN_FLAG} ${device_bba} ${device_bin}.new
# atomically update
COMMAND ${CMAKE_COMMAND} -E rename ${device_bin}.new ${device_bin}
DEPENDS
bbasm
${CMAKE_CURRENT_SOURCE_DIR}/gowin_arch_gen.py
${CMAKE_CURRENT_SOURCE_DIR}/constids.inc
VERBATIM)
list(APPEND chipdb_binaries ${device_bin})
endforeach()

add_custom_target(chipdb-himbaechel-gowin ALL DEPENDS ${chipdb_binaries})
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chipdb/ DESTINATION share/nextpnr/himbaechel/gowin
PATTERN "*.bba" EXCLUDE)
Loading