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

WIP: add initial support for BELs chains #70

Closed
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ env
*.swp
*.swo
*.yaml
!test_data/*
194 changes: 193 additions & 1 deletion fpga_interchange/chip_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class ConstraintType(Enum):
TAG_REQUIRES = 1


class ChainCoordinate(Enum):
X = 0
Y = 1


class BelInfo():
str_id_fields = ['ports']
int_fields = ['types', 'wires']
Expand Down Expand Up @@ -646,6 +651,191 @@ def append_bba(self, bba, label_prefix):
bba.u32(len(getattr(self, field)))


class ChainPatternConfig():
def __init__(self, type, port):
self.type = type
self.port = port

def append_children_bba(self, bba, label_prefix):
pass

def append_bba(self, bba, label_prefix):
bba.str_id(self.type)
bba.str_id(self.port)


class ChainPattern():
children_fields = [
'source', 'sink'
]
children_types = [
'ChainPatternConfigPOD', 'ChainPatternConfigPOD'
]

def __init__(self, source, sink):
self.source = ChainPatternConfig(source.type, source.port)
self.sink = ChainPatternConfig(sink.type, sink.port)

def field_label(self, label_prefix, field):
prefix = '{}.{}'.format(label_prefix, field)
return prefix

def append_children_bba(self, bba, label_prefix):
label = label_prefix

for field, field_type in zip(self.children_fields,
self.children_types):
prefix = self.field_label(label, field)
value = getattr(self, field)
value.append_children_bba(bba, prefix)

bba.label(prefix, field_type)
value.append_bba(bba, prefix)

def append_bba(self, bba, label_prefix):
for field in self.children_fields:
bba.ref(self.field_label(label_prefix, field))
bba.u32(1)


class ChainDriverPortBel():
def __init__(self, name, bel):
self.name = name
self.bel = bel

def field_label(self, label_prefix, field):
prefix = '{}.{}.{}'.format(label_prefix, self.name, field)
return prefix

def append_children_bba(self, bba, label_prefix):
pass

def append_bba(self, bba, label_prefix):
bba.str_id(self.name)
bba.str_id(self.bel)


class ChainDriver():
def __init__(self, ports, cells):
self.ports = []
self.cells = cells

for port in ports:
self.ports.append(ChainDriverPortBel(port.name, port.bel))

def field_label(self, label_prefix, field):
prefix = '{}.{}'.format(label_prefix, field)
return prefix

def append_children_bba(self, bba, label_prefix):
label = self.field_label(label_prefix, 'ports')
for port in self.ports:
port.append_children_bba(bba, label)

bba.label(label, 'ChainDriverPortBelPOD')
for port in self.ports:
port.append_bba(bba, label)

bba.label(self.field_label(label_prefix, 'cells'), 'constids')
for cell in self.cells:
bba.str_id(cell)

def append_bba(self, bba, label_prefix):
bba.ref(self.field_label(label_prefix, 'ports'))
bba.u32(len(self.ports))

bba.ref(self.field_label(label_prefix, 'cells'))
bba.u32(len(self.cells))


class ChainCoordConfig():
def __init__(self, coord, step):
self.coord = ChainCoordinate[str(coord).upper()]
self.step = step

def append_children_bba(self, bba, label_prefix):
pass

def append_bba(self, bba, label_prefix):
bba.u8(self.coord.value)
bba.u8(self.step)
bba.u16(0)


class BelChain():
children_fields = [
'patterns', 'coord_configs', 'chain_drivers'
]
children_types = [
'ChainPatternPOD', 'ChainCoordConfigPOD', 'ChainDriverPOD'
]

def __init__(self, name, patterns, sites, coord_configs, cells, chain_drivers):
# Chain name
self.name = name

# Chain patterns
self.patterns = []
for pattern in patterns:
self.patterns.append(ChainPattern(pattern.source, pattern.sink))

# Sites for which chain patterns apply
self.sites = sites

# Coordinates configurations
# which coordinate by what step should be incremented
self.coord_configs = []
for coord_config in coord_configs:
self.coord_configs.append(ChainCoordConfig(coord_config.coord, coord_config.step))

# Chain cells used in BEL chain
self.cells = cells

# Optional drivers of the cells used in BEL chain
self.chain_drivers = []
if chain_drivers is not None:
for driver in chain_drivers:
self.chain_drivers.append(ChainDriver(driver.ports, driver.cells))

def field_label(self, label_prefix, field):
prefix = '{}.{}.{}'.format(label_prefix, self.name, field)
return prefix

def append_children_bba(self, bba, label_prefix):
label = label_prefix

bba.label(self.field_label(label_prefix, 'sites'), 'constids')
for site in self.sites:
bba.str_id(site)

bba.label(self.field_label(label_prefix, 'cells'), 'constids')
for cell in self.cells:
bba.str_id(cell)

for field, field_type in zip(self.children_fields,
self.children_types):
prefix = self.field_label(label, field)
for value in getattr(self, field):
value.append_children_bba(bba, prefix)

bba.label(prefix, field_type)
for value in getattr(self, field):
value.append_bba(bba, prefix)

def append_bba(self, bba, label_prefix):
bba.str_id(self.name)

bba.ref(self.field_label(label_prefix, 'sites'))
bba.u32(len(self.sites))

bba.ref(self.field_label(label_prefix, 'cells'))
bba.u32(len(self.cells))

for field in self.children_fields:
bba.ref(self.field_label(label_prefix, field))
bba.u32(len(getattr(self, field)))


class PackagePin():
def __init__(self):
self.package_pin = ''
Expand Down Expand Up @@ -1053,6 +1243,7 @@ def __init__(self):
self.packages = []
self.wire_types = []
self.global_cells = []
self.bel_chains = []

# str, constids
self.bel_buckets = []
Expand All @@ -1068,7 +1259,7 @@ def append_bba(self, bba, label_prefix):

children_fields = [
'tile_types', 'sites', 'tiles', 'nodes', 'packages', 'wire_types',
'global_cells', 'macros', 'macro_rules'
'global_cells', 'macros', 'macro_rules', 'bel_chains'
]
children_types = [
'TileTypeInfoPOD',
Expand All @@ -1080,6 +1271,7 @@ def append_bba(self, bba, label_prefix):
'GlobalCellPOD',
'MacroPOD',
'MacroExpansionPOD',
'BelChainPOD',
]
for field, field_type in zip(children_fields, children_types):
prefix = '{}.{}'.format(label, field)
Expand Down
4 changes: 2 additions & 2 deletions fpga_interchange/nextpnr.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,5 @@ def pop(self):

def check_labels(self):
refs_and_labels = self.refs & self.labels
assert len(refs_and_labels) == len(self.refs)
assert len(refs_and_labels) == len(self.labels)
assert len(refs_and_labels) == len(self.refs), "{} vs. {}".format(len(refs_and_labels), len(self.refs))
assert len(refs_and_labels) == len(self.labels), "{} vs. {}".format(len(refs_and_labels), len(self.labels))
17 changes: 15 additions & 2 deletions fpga_interchange/populate_chip_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
TileWireRef, CellBelMap, ParameterPins, CellBelPin, ConstraintTag, \
CellConstraint, ConstraintType, Package, PackagePin, LutCell, \
LutElement, LutBel, CellParameter, DefaultCellConnections, DefaultCellConnection, \
WireType, Macro, MacroNet, MacroPortInst, MacroCellInst, MacroExpansion, MacroParamMapRule, MacroParamRuleType, MacroParameter, GlobalCell, GlobalCellPin

WireType, Macro, MacroNet, MacroPortInst, MacroCellInst, MacroExpansion, \
MacroParamMapRule, MacroParamRuleType, MacroParameter, GlobalCell, GlobalCellPin, BelChain
from fpga_interchange.constraints.model import Tag, Placement, \
ImpliesConstraint, RequiresConstraint
from fpga_interchange.constraint_generator import ConstraintPrototype
Expand Down Expand Up @@ -1835,6 +1835,19 @@ def populate_chip_info(device, constids, device_config):
assert lut_element.site not in lut_elements
lut_elements[lut_element.site] = LutElementsEmitter(lut_element.luts)

bel_chains = {}
for bel_chain in device.device_resource_capnp.belChainsDefinitions.belChains:
assert bel_chain.name not in bel_chains.keys()
drivers_present = bel_chain.which() == "chainDrivers"
bel_chains[bel_chain.name] = BelChain(bel_chain.name,
bel_chain.patterns,
bel_chain.sites,
bel_chain.coordConfigs,
bel_chain.cells,
bel_chain.chainDrivers if drivers_present else None)

chip_info.bel_chains.append(bel_chains[bel_chain.name])

for tile_type_index, tile_type in enumerate(
device.device_resource_capnp.tileTypeList):
flattened_tile_type = FlattenedTileType(
Expand Down
26 changes: 26 additions & 0 deletions test_data/series7_bel_chains.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
belChains:
- name: carryChain
patterns:
- {source: {type: "CARRY4", port: "CO[3]"}, sink: {type: "CARRY4", port: "CI"}}
sites:
- SLICEL
- SLICEM
cells:
- CARRY4
chainDrivers: # Place driver cell of S port to a proper BEL
- ports:
- name: S[0]
bel: AFF
- name: S[1]
bel: BFF
- name: S[2]
bel: CFF
- name: S[3]
bel: DFF
cells:
- FDRE
- FDSE
- FDCE
coordConfigs:
- {coord: y, step: -1} # Default
- {coord: y, step: -2} # When crossing clock region