Skip to content

Commit

Permalink
Merge pull request #961 from antmicro/srl16_support
Browse files Browse the repository at this point in the history
SRL16 support
  • Loading branch information
litghost committed Sep 10, 2019
2 parents 5cd98d6 + fd60b45 commit 04cadc7
Show file tree
Hide file tree
Showing 36 changed files with 1,712 additions and 104 deletions.
20 changes: 20 additions & 0 deletions xc7/bels.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,26 @@
"DSRL":
["LUT_OR_MEM6SHFREG.SLICEM", "LUT_OR_MEM6SHFREG.SLICEM/D6LUT", "LUT_OR_MEM6LRAM.SLICEM/D6LUT"]
},
"SRLC16E_VPR_0": {
"ASRL":
["LUT_OR_MEM5SHFREG.SLICEM", "LUT_OR_MEM5SHFREG.SLICEM/A5LUT", "LUT_OR_MEM5LRAM.SLICEM/A5LUT"],
"BSRL":
["LUT_OR_MEM5SHFREG.SLICEM", "LUT_OR_MEM5SHFREG.SLICEM/B5LUT", "LUT_OR_MEM5LRAM.SLICEM/B5LUT"],
"CSRL":
["LUT_OR_MEM5SHFREG.SLICEM", "LUT_OR_MEM5SHFREG.SLICEM/C5LUT", "LUT_OR_MEM5LRAM.SLICEM/C5LUT"],
"DSRL":
["LUT_OR_MEM5SHFREG.SLICEM", "LUT_OR_MEM5SHFREG.SLICEM/D5LUT", "LUT_OR_MEM5LRAM.SLICEM/D5LUT"]
},
"SRLC16E_VPR_1": {
"ASRL":
["LUT_OR_MEM6SHFREG.SLICEM", "LUT_OR_MEM6SHFREG.SLICEM/A6LUT", "LUT_OR_MEM6LRAM.SLICEM/A6LUT"],
"BSRL":
["LUT_OR_MEM6SHFREG.SLICEM", "LUT_OR_MEM6SHFREG.SLICEM/B6LUT", "LUT_OR_MEM6LRAM.SLICEM/B6LUT"],
"CSRL":
["LUT_OR_MEM6SHFREG.SLICEM", "LUT_OR_MEM6SHFREG.SLICEM/C6LUT", "LUT_OR_MEM6LRAM.SLICEM/C6LUT"],
"DSRL":
["LUT_OR_MEM6SHFREG.SLICEM", "LUT_OR_MEM6SHFREG.SLICEM/D6LUT", "LUT_OR_MEM6LRAM.SLICEM/D6LUT"]
},
"F7AMUX":{
"SLICEM_MODES":
["SELMUX2_1.SLICEM/F7AMUX"],
Expand Down
264 changes: 205 additions & 59 deletions xc7/fasm2bels/clb_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,47 @@ def create_srl32(site, srl):
return bel


def get_srl16_init(features, tile_name, slice_name, srl):
"""
Decodes SRL16 INIT parameter. Returns two initialization strings, each one
for one of two SRL16s.
"""

lut_init = get_lut_init(features, tile_name, slice_name, srl)
bits = lut_init.replace("64'b", "")

assert bits[1::2] == bits[::2]

srl_init = bits[::2]
return "16'b{}".format(srl_init[:16]), "16'b{}".format(srl_init[16:])


def create_srl16(site, srl, srl_type, part):
"""
Create an instance of SRL16 bel. Either for "x6LUT" or for "x5LUT"
depending on the part parameter.
"""

assert part == '5' or part == '6'

bel = Bel(srl_type, srl + part + 'SRL', priority=3)
bel.set_bel(srl + part + 'LUT')

site.add_sink(bel, 'CLK', 'CLK')

if part == '5':
site.add_sink(bel, 'D', '{}I'.format(srl))
if part == '6':
site.add_sink(bel, 'D', '{}X'.format(srl))

for idx in range(4):
site.add_sink(bel, 'A{}'.format(idx), '{}{}'.format(srl, idx + 2))

site.add_internal_source(bel, 'Q', srl + 'O' + part)

return bel


def decode_dram(site):
""" Decode the modes of each LUT in the slice based on set features.
Expand Down Expand Up @@ -199,67 +240,130 @@ def ff_bel(site, lut, ff5):
}[(ffsync, latch, zrst)]


def cleanup_slice(top, site):
""" Perform post-routing cleanups required for SLICE.
def cleanup_carry4(top, site):
""" Performs post-routing cleanups of CARRY4 bel required for SLICE.
Cleanups:
- Detect if CARRY4 is required. If not, remove from site.
- Remove connections to CARRY4 that are not in used (e.g. if C[3] and
CO[3] are not used, disconnect S[3] and DI[2]).
"""

carry4 = site.maybe_get_bel('CARRY4')
if carry4 is not None:

if carry4 is None:
return
# Simplest check is if the CARRY4 has output in used by either the OUTMUX
# or the FFMUX, if any of these muxes are enable, CARRY4 must remain.
co_in_use = [False for _ in range(4)]
o_in_use = [False for _ in range(4)]
for idx, lut in enumerate('ABCD'):
if site.has_feature('{}FFMUX.XOR'.format(lut)):
o_in_use[idx] = True

# Simplest check is if the CARRY4 has output in used by either the OUTMUX
# or the FFMUX, if any of these muxes are enable, CARRY4 must remain.
co_in_use = [False for _ in range(4)]
o_in_use = [False for _ in range(4)]
for idx, lut in enumerate('ABCD'):
if site.has_feature('{}FFMUX.XOR'.format(lut)):
o_in_use[idx] = True
if site.has_feature('{}FFMUX.CY'.format(lut)):
co_in_use[idx] = True

if site.has_feature('{}FFMUX.CY'.format(lut)):
co_in_use[idx] = True
if site.has_feature('{}OUTMUX.XOR'.format(lut)):
o_in_use[idx] = True

if site.has_feature('{}OUTMUX.XOR'.format(lut)):
o_in_use[idx] = True
if site.has_feature('{}OUTMUX.CY'.format(lut)):
co_in_use[idx] = True

if site.has_feature('{}OUTMUX.CY'.format(lut)):
# No outputs in the SLICE use CARRY4, check if the COUT line is in use.
for sink in top.find_sinks_from_source(site, 'COUT'):
co_in_use[idx] = True
break

# No outputs in the SLICE use CARRY4, check if the COUT line is in use.
for sink in top.find_sinks_from_source(site, 'COUT'):
co_in_use[idx] = True
break
for idx in [3, 2, 1, 0]:
if co_in_use[idx] or o_in_use[idx]:
for odx in range(idx):
co_in_use[odx] = True
o_in_use[odx] = True

for idx in [3, 2, 1, 0]:
if co_in_use[idx] or o_in_use[idx]:
for odx in range(idx):
co_in_use[odx] = True
o_in_use[odx] = True
break

break
if not any(co_in_use) and not any(o_in_use):
# No outputs in use, remove entire BEL
top.remove_bel(site, carry4)
else:
for idx in range(4):
if not o_in_use[idx] and not co_in_use[idx]:
sink_wire_pkey = site.remove_internal_sink(
carry4, 'S[{}]'.format(idx)
)
if sink_wire_pkey is not None:
top.remove_sink(sink_wire_pkey)

if not any(co_in_use) and not any(o_in_use):
# No outputs in use, remove entire BEL
top.remove_bel(site, carry4)
else:
for idx in range(4):
if not o_in_use[idx] and not co_in_use[idx]:
sink_wire_pkey = site.remove_internal_sink(
carry4, 'S[{}]'.format(idx)
)
if sink_wire_pkey is not None:
top.remove_sink(sink_wire_pkey)
sink_wire_pkey = site.remove_internal_sink(
carry4, 'DI[{}]'.format(idx)
)
if sink_wire_pkey is not None:
top.remove_sink(sink_wire_pkey)

sink_wire_pkey = site.remove_internal_sink(
carry4, 'DI[{}]'.format(idx)
)
if sink_wire_pkey is not None:
top.remove_sink(sink_wire_pkey)

def cleanup_srl(top, site):
"""Performs post-routing cleanups of SRLs required for SLICE.
Cleanups:
- For each LUT if in 2xSRL16 mode detect whether both SRL16 are used.
removes unused ones.
"""

# Remove unused SRL16
for i, row in enumerate("ABCD"):

# n5SRL, check O5
srl = site.maybe_get_bel("{}5SRL".format(row))
if srl is not None:

if not site.has_feature("{}OUTMUX.O5".format(row)) and \
not site.has_feature("{}FFMUX.O5".format(row)):
top.remove_bel(site, srl)

# n6SRL, check O6 and MC31
srl = site.maybe_get_bel("{}6SRL".format(row))
if srl is not None:

# nOUTMUX, nFFMUX
noutmux_o6_used = site.has_feature("{}OUTMUX.O6".format(row))
nffmux_o6_used = site.has_feature("{}FFMUX.O6".format(row))

# nUSED
nused_used = True
sinks = list(top.find_sinks_from_source(site, row))
if len(sinks) == 0:
nused_used = False

# n7MUX
f7nmux_used = True
if row in "AB" and site.maybe_get_bel("F7AMUX") is None:
f7nmux_used = False
if row in "CD" and site.maybe_get_bel("F7BMUX") is None:
f7nmux_used = False

# A6SRL MC31 output
if row == "A":
mc31_used = site.has_feature("DOUTMUX.MC31") or \
site.has_feature("DFFMUX.MC31")
else:
mc31_used = False

# Remove if necessary
anything_used = nused_used or noutmux_o6_used or nffmux_o6_used or\
f7nmux_used or mc31_used

if not anything_used:
top.remove_bel(site, srl)


def cleanup_slice(top, site):
"""Performs post-routing cleanups required for SLICE."""

# Cleanup CARRY4 stuff
cleanup_carry4(top, site)

# Cleanup SRL stuff
cleanup_srl(top, site)


def process_slice(top, s):
Expand Down Expand Up @@ -349,23 +453,65 @@ def connect_ce_sr(bel, ce, sr):

# SRL32
if not site.has_feature('{}LUT.SMALL'.format(row)):
srls[row] = create_srl32(site, row)
srls[row].parameters['INIT'] = get_srl32_init(
srl = create_srl32(site, row)
srl.parameters['INIT'] = get_srl32_init(
s, aparts[0], aparts[1], row
)

site.add_sink(srls[row], 'CE', WE)
site.add_sink(srl, 'CE', WE)

if row == 'A' and site.has_feature('DOUTMUX.MC31'):
site.add_internal_source(srls[row], 'Q31', 'AMC31')
site.add_internal_source(srl, 'Q31', 'AMC31')
if row == 'A' and site.has_feature('DFFMUX.MC31'):
site.add_internal_source(srls[row], 'Q31', 'AMC31')
site.add_internal_source(srl, 'Q31', 'AMC31')

site.add_bel(srls[row])
site.add_bel(srl)
srls[row] = (srl, )

# 2x SRL16
else:
assert False, "SRL16 not supported yet!"

srls[row] = []
init = get_srl16_init(s, aparts[0], aparts[1], row)

for i, part in enumerate(['5', '6']):

# Determine whether to use SRL16E or SRLC16E
srl_type = 'SRL16E'
use_mc31 = False

if part == '6':

if row == 'A' and site.has_feature('DOUTMUX.MC31'):
srl_type = 'SRLC16E'
use_mc31 = True
if row == 'A' and site.has_feature('DFFMUX.MC31'):
srl_type = 'SRLC16E'
use_mc31 = True

if row == 'D' and site.has_feature(
'CLUT.DI1MUX.DI_DMC31'):
srl_type = 'SRLC16E'
if row == 'C' and site.has_feature(
'BLUT.DI1MUX.DI_CMC31'):
srl_type = 'SRLC16E'
if row == 'B' and site.has_feature(
'ALUT.DI1MUX.DI_BMC31'):
srl_type = 'SRLC16E'

# Create the SRL
srl = create_srl16(site, row, srl_type, part)
srl.parameters['INIT'] = init[i]

site.add_sink(srl, 'CE', WE)

if use_mc31 and srl_type == 'SRLC16E':
site.add_internal_source(srl, 'Q15', 'AMC31')

site.add_bel(srl, name="{}{}SRL".format(row, part))
srls[row].append(srl)

srls[row] = tuple(srls[row])

# LUT
else:
Expand Down Expand Up @@ -645,17 +791,17 @@ def connect_ce_sr(bel, ce, sr):
srl_chains.add("BA")

# SRL chain connections
if "DC" in srl_chains:
site.add_internal_source(srls['D'], 'Q31', 'DMC31')
srls['C'].connections['D'] = 'DMC31'
for chain in srl_chains:
src = chain[0]
dst = chain[1]

if "CB" in srl_chains:
site.add_internal_source(srls['C'], 'Q31', 'CMC31')
srls['B'].connections['D'] = 'CMC31'
if site.has_feature("{}LUT.SMALL".format(src)):
q = "Q15"
else:
q = "Q31"

if "BA" in srl_chains:
site.add_internal_source(srls['B'], 'Q31', 'BMC31')
srls['A'].connections['D'] = 'BMC31'
site.add_internal_source(srls[src][-1], q, '{}MC31'.format(src))
srls[dst][0].connections['D'] = '{}MC31'.format(src)

need_f8 = site.has_feature('BFFMUX.F8') or site.has_feature('BOUTMUX.F8')
need_f7a = site.has_feature('AFFMUX.F7') or site.has_feature('AOUTMUX.F7')
Expand Down
1 change: 1 addition & 0 deletions xc7/primitives/slicem/slicem.model.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
<xi:include href="dram_4_output_stub.model.xml" xpointer="xpointer(models/child::node())" />
<xi:include href="dram_8_output_stub.model.xml" xpointer="xpointer(models/child::node())" />
<xi:include href="srl/srlc32e_vpr.model.xml" xpointer="xpointer(models/child::node())" />
<xi:include href="srl/srlc16e_vpr.model.xml" xpointer="xpointer(models/child::node())" />
</models>
4 changes: 2 additions & 2 deletions xc7/primitives/slicem/slicem.pb_type.xml
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
<direct name="D_SRL.O5_to_SLICEM_MODES.DO5" input="DSRL.O5" output="SLICEM_MODES.DO5"/>
<direct name="D_SRL.O6_to_SLICEM_MODES.DO6" input="DSRL.O6" output="SLICEM_MODES.DO6"/>

<!-- WE/CE inputs -->
<!-- CE and WE -->
<direct name="SLICEM_MODES.CE_to_WE_MUX.CE" input="SLICEM_MODES.CE" output="WE_MUX.CE"/>
<direct name="SLICEM_MODES.WE_to_WE_MUX.WE" input="SLICEM_MODES.WE" output="WE_MUX.WE"/>

Expand Down Expand Up @@ -297,7 +297,7 @@
<direct name="F7AMUX_I0" input="BSRL.O6" output="F7AMUX.I0">
<pack_pattern in_port="BSRL.O6" name="SRL_x2" out_port="F7AMUX.I0"/>
<pack_pattern in_port="BSRL.O6" name="SRL_x3" out_port="F7AMUX.I0"/>
<pack_pattern in_port="BSRL.O6" name="SRL_x4" out_port="F7AMUX.I0"/>
<pack_pattern in_port="BSRL.O6" name="SRL_x4" out_port="F7AMUX.I0"/>
</direct>
<direct name="F7AMUX_I1" input="ASRL.O6" output="F7AMUX.I1">
<pack_pattern in_port="ASRL.O6" name="SRL_x2" out_port="F7AMUX.I1"/>
Expand Down
6 changes: 5 additions & 1 deletion xc7/primitives/slicem/srl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
add_file_target(FILE srlc32e_vpr.model.xml SCANNER_TYPE xml)
add_file_target(FILE srlc32e_vpr.pb_type.xml SCANNER_TYPE xml)
add_file_target(FILE srlc16e_vpr.model.xml SCANNER_TYPE xml)
add_file_target(FILE srlc16e_vpr_0.pb_type.xml SCANNER_TYPE xml)
add_file_target(FILE srlc16e_vpr_1.pb_type.xml SCANNER_TYPE xml)

add_file_target(FILE a_srl.pb_type.xml SCANNER_TYPE xml)
add_file_target(FILE ntemplate.N_srl.pb_type.xml SCANNER_TYPE xml)

n_template(
NAME N_srl.pb_type.xml
PREFIXES a;b;c;d
PREFIXES b;c;d
SRCS ntemplate.N_srl.pb_type.xml
)

Loading

0 comments on commit 04cadc7

Please sign in to comment.