Merge pull request #900 from litghost/extend_zero_db_features

Add support to zero db to support simple groups.
This commit is contained in:
litghost 2019-06-25 09:02:10 -07:00 committed by GitHub
commit bc3fcb0db2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 225 additions and 87 deletions

View File

@ -23,14 +23,29 @@ SEGBITS=\
hclk \
int \
DB_SIMPLE=$(addprefix mask_,$(MASKS)) $(addprefix ppips_,$(PPIPS)) $(addprefix segbits_,$(SEGBITS))
SEGBITS_R=\
clk_bufg_top \
clk_bufg_bot \
$(SEGBITS)
# Extra (segbits|mask)_bram_(l|r).block_ram.db files
# FIXME: Are these things also needed for the DSP blocks?
BLOCK_RAM_EXTRA_FOR=mask_bram segbits_bram
BLOCK_RAM_EXTRA_DB_FILES=$(addsuffix .block_ram.db,$(addsuffix _l,$(BLOCK_RAM_EXTRA_FOR)) $(addsuffix _r,$(BLOCK_RAM_EXTRA_FOR)))
SEGBITS_L=\
$(SEGBITS)
DB_FILES=$(sort $(addsuffix _l.db,$(DB_SIMPLE)) $(addsuffix _r.db,$(DB_SIMPLE)) $(BLOCK_RAM_EXTRA_DB_FILES))
DB_SIMPLE_LR=$(addprefix mask_,$(MASKS)) $(addprefix ppips_,$(PPIPS))
DB_SIMPLE_L=$(addprefix segbits_,$(SEGBITS_L))
DB_SIMPLE_R=$(addprefix segbits_,$(SEGBITS_R))
DB_SIMPLE=\
$(addsuffix _l, $(DB_SIMPLE_LR) $(DB_SIMPLE_L)) \
$(addsuffix _r, $(DB_SIMPLE_LR) $(DB_SIMPLE_R))
BLOCK_RAM_EXTRA_FOR=\
mask_bram \
segbits_bram
BLOCK_RAM_EXTRA_DB_FILES=\
$(addsuffix .block_ram.db,$(addsuffix _l,$(BLOCK_RAM_EXTRA_FOR)) $(addsuffix _r,$(BLOCK_RAM_EXTRA_FOR)))
DB_FILES=$(sort $(addsuffix .origin_info.db,$(DB_SIMPLE)) $(addsuffix .db,$(DB_SIMPLE)) $(BLOCK_RAM_EXTRA_DB_FILES))
DB_FILES_PATH=$(addprefix $(XRAY_DATABASE_DIR)/$(XRAY_DATABASE)/,$(DB_FILES))
check:

View File

@ -1,3 +1,4 @@
N := 1
CLB_DBFIXUP=Y
include ../clb.mk

View File

@ -0,0 +1,3 @@
# NOCLKINV is inverse of CLKINV
CLB.SLICE_X0.CLKINV ^ CLB.SLICE_X0.NOCLKINV
CLB.SLICE_X1.CLKINV ^ CLB.SLICE_X1.NOCLKINV

View File

@ -94,8 +94,10 @@ with open("design.txt", "r") as f:
# CLKINV turns out to be more complicated than origianlly thought
if isff(cel_prim):
segmk.add_site_tag(site, "CLKINV", cinv)
segmk.add_site_tag(site, "NOCLKINV", 1 ^ cinv)
else:
segmk.add_site_tag(site, "CLKINV", 1 ^ cinv)
segmk.add_site_tag(site, "NOCLKINV", cinv)
# Synchronous vs asynchronous FF
# Unlike most bits, shared between all CLB FFs

View File

@ -1,4 +1,5 @@
N := 3
SLICEL ?= N
CLB_DBFIXUP=Y
include ../clb.mk

View File

@ -0,0 +1,3 @@
CLB.SLICE_X0.ALUT.DI1MUX.AI ^ CLB.SLICE_X0.ALUT.DI1MUX.BDI1_BMC31
CLB.SLICE_X0.BLUT.DI1MUX.BI ^ CLB.SLICE_X0.BLUT.DI1MUX.DI_CMC31
CLB.SLICE_X0.CLUT.DI1MUX.CI ^ CLB.SLICE_X0.CLUT.DI1MUX.DI_DMC31

View File

@ -25,8 +25,11 @@ for l in f:
b31 = int(b31)
a31 = int(a31)
segmk.add_site_tag(loc, "ALUT.DI1MUX.AI", 1 ^ a31)
segmk.add_site_tag(loc, "ALUT.DI1MUX.BDI1_BMC31", a31)
segmk.add_site_tag(loc, "BLUT.DI1MUX.BI", 1 ^ b31)
segmk.add_site_tag(loc, "BLUT.DI1MUX.DI_CMC31", b31)
segmk.add_site_tag(loc, "CLUT.DI1MUX.CI", 1 ^ c31)
segmk.add_site_tag(loc, "CLUT.DI1MUX.DI_DMC31", c31)
segmk.compile()
segmk.write()

View File

@ -51,57 +51,152 @@ def bits_str(bits):
return ' '.join(sorted(list(bits)))
def zero_groups(tag, bits, zero_db, strict=True, verbose=False):
"""
See if a line occurs within a bit group
If it does, add 0 bits
class ZeroGroups(object):
def __init__(self, zero_db):
self.groups = []
self.bit_to_group = {}
self.tag_to_groups = {}
self.zero_tag_to_group = {}
self.parse_zero_db(zero_db)
Ex: 01_02 04_05
Means find a line that has either of these bits
If either of them occurs, default bits in that set to zero
def print_groups(self):
print('Zero groups:')
for bits in self.groups:
print(bits_str(bits))
Ex: 01_02 04_05|07_08 10_11
If any bits from the first group occur,
default bits in the second group to zero
print('Zero tags:')
for tag in self.zero_tag_to_group:
print(tag, bits_str(self.zero_tag_to_group[tag]))
Ex: 01_02 04_05,ALL_ZERO
ALL_ZERO is an enum that is part of the group but is all 0
It must have 0 candidates
def parse_zero_db(self, zero_db):
""" Convert zero db format into data structure
strict: assert that the size of the given group is the size of the given mask
"""
for zdb in zero_db:
allzero_tag = None
if "," in zdb:
zdb, allzero_tag = zdb.split(",")
Zero db format examples:
if "|" in zdb:
a, b = zdb.split("|")
a = a.split()
b = b.split()
else:
a = zdb.split()
b = a
Ex: 01_02 04_05
Means find a line that has either of these bits
If either of them occurs, default bits in that set to zero
bitmatch = False
for bit in a:
if bit in bits:
bitmatch = True
Ex: 01_02 04_05|07_08 10_11
If any bits from the first group occur,
default bits in the second group to zero
if not (bitmatch or allzero_tag == tag):
continue
Ex: 01_02 04_05,ALL_ZERO
ALL_ZERO is an enum that is part of the group but is all 0
It must have 0 candidates
bits_orig = set(bits)
for bit in b:
if bit not in bits:
Ex: CLB.SLICE_X0.CLKINV ^ CLB.SLICE_X0.NOCLKINV
CLB.SLICE_X0.NOCLKINV is all bits in CLB.SLICE_X0.CLKINV unset
Ex: A | B ^ C
C is all bits in (A)|(B) unset
"""
for zdb in zero_db:
if "^" in zdb:
self.groups.append(set())
zero_group = self.groups[-1]
other_tags, allzero_tag = zdb.split('^')
allzero_tag = allzero_tag.strip()
for tag in other_tags.split():
self.tag_to_groups[tag.strip()] = [zero_group]
self.zero_tag_to_group[allzero_tag] = zero_group
continue
allzero_tag = None
if "," in zdb:
zdb, allzero_tag = zdb.split(",")
if "|" in zdb:
a, b = zdb.split("|")
a = a.split()
b = b.split()
self.groups.append(set(b))
zero_group = self.groups[-1]
else:
a = zdb.split()
self.groups.append(set(a))
zero_group = self.groups[-1]
if allzero_tag is not None:
self.zero_tag_to_group[allzero_tag] = zero_group
for bit in a:
self.bit_to_group[bit] = zero_group
def add_tag_bits(self, tag, bits):
if tag in self.zero_tag_to_group:
return
group_ids = set()
groups = []
if tag in self.tag_to_groups:
assert len(self.tag_to_groups[tag]) == 1
self.tag_to_groups[tag][0] |= bits
for bit in bits:
if bit in self.bit_to_group:
# Make sure each bit only belongs to one group
assert id(self.bit_to_group[bit]) == id(
self.tag_to_groups[tag])
else:
self.bit_to_group[bit] = self.tag_to_groups[tag]
group_ids.add(id(self.tag_to_groups[tag]))
groups = self.tag_to_groups[tag]
for bit in bits:
if bit in self.bit_to_group:
if id(self.bit_to_group[bit]) not in group_ids:
group_ids.add(id(self.bit_to_group[bit]))
groups.append(self.bit_to_group[bit])
self.tag_to_groups[tag] = groups
def add_bits_from_zero_groups(self, tag, bits, strict=True, verbose=False):
""" Add bits from a zero group, if needed
Arguments
---------
tag : str
Tag being to examine for zero group
bits : set of str
Set of bits set on this tag
strict : bool
Assert that the size of the given group is the size of the given
mask.
verbose : bool
Print to stdout grouping being made
"""
tag_is_masked = tag in self.tag_to_groups
tag_is_zero = tag in self.zero_tag_to_group
# Should not have a tag that is both masked and a zero tag.
assert not (tag_is_masked and tag_is_zero)
if tag_is_masked:
for b in self.tag_to_groups[tag]:
bits_orig = set(bits)
for bit in b:
if bit not in bits:
bits.add("!" + bit)
verbose and print(
"Grouped %s: %s => %s" %
(tag, bits_str(bits_orig), bits_str(bits)))
if tag_is_zero:
for bit in self.zero_tag_to_group[tag]:
bits.add("!" + bit)
verbose and print(
"Grouped %s: %s => %s" %
(tag, bits_str(bits_orig), bits_str(bits)))
if a == b and strict:
assert len(bits) == len(
a), "Mask size %u != DB entry size %u: %s" % (
len(a), len(bits), bits_str(bits))
def add_zero_bits(fn_in, zero_db, clb_int=False, strict=True, verbose=False):
@ -111,11 +206,15 @@ def add_zero_bits(fn_in, zero_db, clb_int=False, strict=True, verbose=False):
If an entry has any of the
'''
zero_groups = ZeroGroups(zero_db)
lines = []
new_lines = set()
changes = 0
llast = None
drops = 0
with open(fn_in, "r") as f:
for line in f:
# Hack: skip duplicate lines
@ -124,53 +223,64 @@ def add_zero_bits(fn_in, zero_db, clb_int=False, strict=True, verbose=False):
if line == llast:
continue
lines.append(line)
tag, bits, mode, _ = util.parse_db_line(line)
# an enum that needs masking
# check below asserts that a mask was actually applied
if mode and mode != "<0 candidates>" and not strict:
if bits is not None and mode is None:
zero_groups.add_tag_bits(tag, bits)
if verbose:
zero_groups.print_groups()
for line in lines:
tag, bits, mode, _ = util.parse_db_line(line)
# an enum that needs masking
# check below asserts that a mask was actually applied
if mode and mode != "<0 candidates>" and not strict:
verbose and print("WARNING: dropping unresolved line: %s" % line)
drops += 1
continue
assert mode not in (
"<const0>",
"<const1>"), "Entries must be resolved. line: %s" % (line, )
if mode == "always":
new_line = line
else:
if mode:
assert mode == "<0 candidates>", line
bits = set()
else:
bits = set(bits)
"""
This appears to be a large range of one hot interconnect bits
They are immediately before the first CLB real bits
"""
if clb_int:
zero_range(tag, bits, 22, 25)
zero_groups.add_bits_from_zero_groups(
tag, bits, strict=strict, verbose=verbose)
if strict:
assert len(bits) > 0, 'Line {} found no bits.'.format(line)
elif len(bits) == 0:
verbose and print(
"WARNING: dropping unresolved line: %s" % line)
drops += 1
continue
assert mode not in (
"<const0>",
"<const1>"), "Entries must be resolved. line: %s" % (line, )
new_line = " ".join([tag] + sorted(bits))
if mode == "always":
new_line = line
else:
if mode:
assert mode == "<0 candidates>", line
bits = set()
else:
bits = set(bits)
"""
This appears to be a large range of one hot interconnect bits
They are immediately before the first CLB real bits
"""
if clb_int:
zero_range(tag, bits, 22, 25)
zero_groups(tag, bits, zero_db, strict=strict, verbose=verbose)
if re.match(r'.*<.*>.*', new_line):
print("Original line: %s" % line)
assert 0, "Failed to remove line mode: %s" % (new_line)
if strict:
assert len(bits) > 0, 'Line {} found no bits.'.format(line)
elif len(bits) == 0:
verbose and print(
"WARNING: dropping unresolved line: %s" % line)
drops += 1
continue
new_line = " ".join([tag] + sorted(bits))
if re.match(r'.*<.*>.*', new_line):
print("Original line: %s" % line)
assert 0, "Failed to remove line mode: %s" % (new_line)
if new_line != line:
changes += 1
new_lines.add(new_line)
llast = line
if new_line != line:
changes += 1
new_lines.add(new_line)
llast = line
if drops:
print("WARNING: %s dropped %s unresolved lines" % (fn_in, drops))