mirror of https://github.com/openXC7/prjxray.git
Add fuzzer for BRAM/FIFO enable bits.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
a4c9257647
commit
bf817f3548
|
|
@ -0,0 +1,23 @@
|
|||
N ?= 5
|
||||
|
||||
include ../fuzzer.mk
|
||||
|
||||
database: build/segbits_bramx.db
|
||||
|
||||
build/segbits_bramx.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} -o build/segbits_bramx.rdb $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
|
||||
|
||||
build/segbits_bramx.db: build/segbits_bramx.rdb
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
|
||||
--seg-fn-in build/segbits_bramx.rdb \
|
||||
--seg-fn-out build/segbits_bramx.unmerged.db
|
||||
python3 merge_in_use.py build/segbits_bramx.unmerged.db > build/segbits_bramx.db
|
||||
${XRAY_MASKMERGE} build/mask_bramx.db $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
|
||||
|
||||
pushdb:
|
||||
${XRAY_MERGEDB} bram_l build/segbits_bramx.db
|
||||
${XRAY_MERGEDB} bram_r build/segbits_bramx.db
|
||||
${XRAY_MERGEDB} mask_bram_l build/mask_bramx.db
|
||||
${XRAY_MERGEDB} mask_bram_r build/mask_bramx.db
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
27_150,BRAM.RAMB18_Y0.RAM_IN_USE
|
||||
27_169,BRAM.RAMB18_Y1.RAM_IN_USE
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
|
||||
from prjxray.segmaker import Segmaker
|
||||
|
||||
|
||||
def bitfilter(frame, bit):
|
||||
# Filter out interconnect bits.
|
||||
if frame in [0, 1, 17, 23, 25]:
|
||||
return False
|
||||
|
||||
# ZINV_RSTRAMARSTRAM seems hard to de-correlate from FIFO_Y0_IN_USE.
|
||||
if (frame, bit) == (27, 116):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
segmk = Segmaker("design.bits")
|
||||
|
||||
print("Loading tags")
|
||||
with open('params.json') as f:
|
||||
params = json.load(f)
|
||||
|
||||
for tile_param in params:
|
||||
for param, tag in (
|
||||
('Y0_IN_USE', 'RAMB18_Y0.IN_USE'),
|
||||
('Y1_IN_USE', 'RAMB18_Y1.IN_USE'),
|
||||
('RAMB_Y0_IN_USE', 'RAMB18_Y0.RAM_IN_USE'),
|
||||
('RAMB_Y1_IN_USE', 'RAMB18_Y1.RAM_IN_USE'),
|
||||
('FIFO_Y0_IN_USE', 'RAMB18_Y0.FIFO_IN_USE'),
|
||||
('FIFO_Y1_IN_USE', 'RAMB18_Y1.FIFO_IN_USE'),
|
||||
):
|
||||
segmk.add_tile_tag(tile_param['tile'], tag, tile_param[param])
|
||||
|
||||
segmk.compile(bitfilter=bitfilter)
|
||||
segmk.write()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
proc run {} {
|
||||
create_project -force -part $::env(XRAY_PART) design design
|
||||
read_verilog top.v
|
||||
synth_design -top top
|
||||
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||
|
||||
place_design
|
||||
route_design
|
||||
|
||||
write_checkpoint -force design.dcp
|
||||
write_bitstream -force design.bit
|
||||
}
|
||||
|
||||
run
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
""" Merge IN_USE entries.
|
||||
|
||||
Segmatch has trouble directly solving for RAM_IN_USE and FIFO_IN_USE.
|
||||
Instead if solves for IN_USE (e.g. RAM_IN_USE or FIFO_IN_USE) and the FIFO_IN_USE bit.
|
||||
|
||||
This tool merges the 3 entries into 2 entries RAM_IN_USE and FIFO_IN_USE.
|
||||
|
||||
|
||||
BRAM.RAMB18_Y0.FIFO_IN_USE 27_150
|
||||
BRAM.RAMB18_Y0.IN_USE 27_100 27_99
|
||||
BRAM.RAMB18_Y0.RAM_IN_USE !27_150
|
||||
|
||||
becomes
|
||||
|
||||
BRAM.RAMB18_Y0.FIFO_IN_USE 27_100 27_99 27_150
|
||||
BRAM.RAMB18_Y0.RAM_IN_USE 27_100 27_99 !27_150
|
||||
|
||||
"""
|
||||
import argparse
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('unmerged_db')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
site_parts = {}
|
||||
|
||||
with open(args.unmerged_db) as f:
|
||||
for l in f:
|
||||
parts = l.strip().split(' ')
|
||||
|
||||
feature = parts[0]
|
||||
bits = parts[1:]
|
||||
|
||||
feature_parts = feature.split('.')
|
||||
|
||||
assert feature_parts[0] == 'BRAM'
|
||||
assert feature_parts[1] in ('RAMB18_Y0', 'RAMB18_Y1')
|
||||
site = feature_parts[1]
|
||||
|
||||
if site not in site_parts:
|
||||
site_parts[site] = {}
|
||||
|
||||
site_parts[site][feature_parts[2]] = bits
|
||||
|
||||
assert len(site_parts) == 2
|
||||
for site in site_parts:
|
||||
assert 'IN_USE' in site_parts[site]
|
||||
assert len(site_parts[site]) == 3
|
||||
|
||||
for feature in site_parts[site]:
|
||||
if feature == 'IN_USE':
|
||||
continue
|
||||
|
||||
print('BRAM.{site}.{feature} {bits}'.format(
|
||||
site=site,
|
||||
feature=feature,
|
||||
bits=' '.join(site_parts[site]['IN_USE'] + site_parts[site][feature])))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
import json
|
||||
import os
|
||||
import random
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray import verilog
|
||||
from prjxray.db import Database
|
||||
from prjxray.lut_maker import LutMaker
|
||||
|
||||
WRITE_MODES = ("WRITE_FIRST", "NO_CHANGE", "READ_FIRST")
|
||||
|
||||
def gen_sites():
|
||||
db = Database(util.get_db_root())
|
||||
grid = db.grid()
|
||||
for tile_name in sorted(grid.tiles()):
|
||||
loc = grid.loc_of_tilename(tile_name)
|
||||
gridinfo = grid.gridinfo_at_loc(loc)
|
||||
|
||||
if gridinfo.tile_type not in ['BRAM_L', 'BRAM_R']:
|
||||
continue
|
||||
|
||||
sites = {}
|
||||
for site_name, site_type in gridinfo.sites.items():
|
||||
sites[site_type] = site_name
|
||||
|
||||
yield tile_name, sites
|
||||
|
||||
def ramb18(tile_name, luts, lines, sites):
|
||||
""" RAMB18E1 in either top or bottom site. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = random.randint(0, 1) == 1
|
||||
params['Y1_IN_USE'] = not params['Y0_IN_USE']
|
||||
params['RAMB_Y0_IN_USE'] = params['Y0_IN_USE']
|
||||
params['RAMB_Y1_IN_USE'] = params['Y1_IN_USE']
|
||||
params['FIFO_Y0_IN_USE'] = False
|
||||
params['FIFO_Y1_IN_USE'] = False
|
||||
|
||||
if params['Y0_IN_USE']:
|
||||
site = sites['FIFO18E1']
|
||||
elif params['Y1_IN_USE']:
|
||||
site = sites['RAMB18E1']
|
||||
else:
|
||||
assert False
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
RAMB18E1 #(
|
||||
) bram_{site} (
|
||||
);
|
||||
'''.format(
|
||||
site=site))
|
||||
|
||||
return params
|
||||
|
||||
def ramb18_2x(tile_name, luts, lines, sites):
|
||||
""" RAMB18E1 in both top and bottom site. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = True
|
||||
params['Y1_IN_USE'] = True
|
||||
params['RAMB_Y0_IN_USE'] = True
|
||||
params['RAMB_Y1_IN_USE'] = True
|
||||
params['FIFO_Y0_IN_USE'] = False
|
||||
params['FIFO_Y1_IN_USE'] = False
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{top_site}" *)
|
||||
RAMB18E1 #(
|
||||
) bram_{top_site} (
|
||||
);
|
||||
(* KEEP, DONT_TOUCH, LOC = "{bottom_site}" *)
|
||||
RAMB18E1 #(
|
||||
) bram_{bottom_site} (
|
||||
);
|
||||
'''.format(
|
||||
top_site=sites['FIFO18E1'],
|
||||
bottom_site=sites['RAMB18E1'],
|
||||
))
|
||||
|
||||
return params
|
||||
|
||||
def ramb36(tile_name, luts, lines, sites):
|
||||
""" RAMB36 consuming entire tile. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = True
|
||||
params['Y1_IN_USE'] = True
|
||||
params['RAMB_Y0_IN_USE'] = True
|
||||
params['RAMB_Y1_IN_USE'] = True
|
||||
params['FIFO_Y0_IN_USE'] = False
|
||||
params['FIFO_Y1_IN_USE'] = False
|
||||
|
||||
site = sites['RAMBFIFO36E1']
|
||||
|
||||
lines.append(
|
||||
"""
|
||||
wire [7:0] webwe_{site};
|
||||
wire [3:0] wea_{site};
|
||||
wire regce_{site};
|
||||
wire [15:0] rdaddr_{site};
|
||||
wire [15:0] wraddr_{site};
|
||||
""".format(site=site))
|
||||
|
||||
for bit in range(15):
|
||||
lines.append('assign rdaddr_{site}[{bit}] = {net};'.format(bit=bit, site=site,net=luts.get_next_output_net()))
|
||||
lines.append('assign wraddr_{site}[{bit}] = {net};'.format(bit=bit, site=site,net=luts.get_next_output_net()))
|
||||
|
||||
for bit in range(8):
|
||||
lines.append('assign webwe_{site}[{bit}] = {net};'.format(bit=bit, site=site,net=luts.get_next_output_net()))
|
||||
|
||||
for bit in range(4):
|
||||
lines.append('assign wea_{site}[{bit}] = {net};'.format(bit=bit, site=site,net=luts.get_next_output_net()))
|
||||
|
||||
lines.append('assign regce_{site} = {net};'.format(bit=bit, site=site,net=luts.get_next_output_net()))
|
||||
|
||||
do_reg = verilog.vrandbit()
|
||||
ram_mode = random.choice(('SDP', 'TDP'))
|
||||
READ_WIDTH_A = 0
|
||||
READ_WIDTH_B = 0
|
||||
|
||||
if ram_mode == 'TDP':
|
||||
write_mode_a = random.choice(WRITE_MODES)
|
||||
write_mode_b = random.choice(WRITE_MODES)
|
||||
WRITE_WIDTH_A = 36
|
||||
WRITE_WIDTH_B = 36
|
||||
else:
|
||||
write_mode_a = 'WRITE_FIRST'
|
||||
write_mode_b = 'WRITE_FIRST'
|
||||
WRITE_WIDTH_A = 72
|
||||
WRITE_WIDTH_B = 72
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
RAMB36E1 #(
|
||||
.DOA_REG({doa_reg}),
|
||||
.DOB_REG({dob_reg}),
|
||||
.WRITE_MODE_A({write_mode_a}),
|
||||
.WRITE_MODE_B({write_mode_b}),
|
||||
.READ_WIDTH_A({READ_WIDTH_A}),
|
||||
.READ_WIDTH_B({READ_WIDTH_B}),
|
||||
.WRITE_WIDTH_A({WRITE_WIDTH_A}),
|
||||
.WRITE_WIDTH_B({WRITE_WIDTH_B}),
|
||||
.INIT_A(36'hFF_FFFF_FFFF),
|
||||
.SRVAL_A(36'hFF_FFFF_FFFF),
|
||||
.INIT_B(36'hFF_FFFF_FFFF),
|
||||
.SRVAL_B(36'hFF_FFFF_FFFF),
|
||||
.RAM_MODE({ram_mode})
|
||||
) bram_{site} (
|
||||
.ADDRARDADDR(rdaddr_{site}),
|
||||
.ADDRBWRADDR(wraddr_{site}),
|
||||
.REGCEAREGCE(regce_{site}),
|
||||
.REGCEB(regce_{site}),
|
||||
.WEBWE(webwe_{site}),
|
||||
.WEA(wea_{site})
|
||||
);
|
||||
'''.format(
|
||||
site=site,
|
||||
doa_reg=do_reg,
|
||||
dob_reg=do_reg,
|
||||
write_mode_a=verilog.quote(write_mode_a),
|
||||
write_mode_b=verilog.quote(write_mode_b),
|
||||
ram_mode=verilog.quote(ram_mode),
|
||||
READ_WIDTH_A=READ_WIDTH_A,
|
||||
READ_WIDTH_B=READ_WIDTH_B,
|
||||
WRITE_WIDTH_A=WRITE_WIDTH_A,
|
||||
WRITE_WIDTH_B=WRITE_WIDTH_B,
|
||||
))
|
||||
|
||||
return params
|
||||
|
||||
def fifo18(tile_name, luts, lines, sites):
|
||||
""" FIFO18E1 without bottom RAMB site. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = True
|
||||
params['Y1_IN_USE'] = False
|
||||
params['RAMB_Y0_IN_USE'] = False
|
||||
params['RAMB_Y1_IN_USE'] = False
|
||||
params['FIFO_Y0_IN_USE'] = True
|
||||
params['FIFO_Y1_IN_USE'] = False
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
wire fifo_rst_{site};
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 fifo_lut_{site} (
|
||||
.O(fifo_rst_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
FIFO18E1 #(
|
||||
.ALMOST_EMPTY_OFFSET(8),
|
||||
.ALMOST_FULL_OFFSET(8),
|
||||
.DATA_WIDTH({data_width})
|
||||
) fifo_{site} (
|
||||
.RST(fifo_rst_{site})
|
||||
);
|
||||
'''.format(
|
||||
site=sites['FIFO18E1'],
|
||||
data_width=random.choice((4, 9)),
|
||||
))
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def fifo18_ramb18(tile_name, luts, lines, sites):
|
||||
""" FIFO18E1 in top site and RAMB18E1 in bottom site. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = True
|
||||
params['Y1_IN_USE'] = True
|
||||
params['RAMB_Y0_IN_USE'] = False
|
||||
params['RAMB_Y1_IN_USE'] = True
|
||||
params['FIFO_Y0_IN_USE'] = True
|
||||
params['FIFO_Y1_IN_USE'] = False
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
wire fifo_rst_{fifo_site};
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 fifo_lut_{fifo_site} (
|
||||
.O(fifo_rst_{fifo_site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{fifo_site}" *)
|
||||
FIFO18E1 #(
|
||||
.ALMOST_EMPTY_OFFSET(5),
|
||||
.ALMOST_FULL_OFFSET(5)
|
||||
) fifo_{fifo_site} (
|
||||
.RST(fifo_rst_{fifo_site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{ramb_site}" *)
|
||||
RAMB18E1 #(
|
||||
) bram_{ramb_site} (
|
||||
);
|
||||
'''.format(
|
||||
fifo_site=sites['FIFO18E1'],
|
||||
ramb_site=sites['RAMB18E1'],
|
||||
))
|
||||
|
||||
return params
|
||||
|
||||
def fifo36(tile_name, luts, lines, sites):
|
||||
""" FIFO36E1 consuming entire tile. """
|
||||
|
||||
params = {}
|
||||
params['tile'] = tile_name
|
||||
params['Y0_IN_USE'] = True
|
||||
params['Y1_IN_USE'] = True
|
||||
params['RAMB_Y0_IN_USE'] = False
|
||||
params['RAMB_Y1_IN_USE'] = False
|
||||
params['FIFO_Y0_IN_USE'] = True
|
||||
params['FIFO_Y1_IN_USE'] = True
|
||||
|
||||
data_width = random.choice((4, 9))
|
||||
if data_width == 4:
|
||||
ALMOST_EMPTY_OFFSET = 8184
|
||||
ALMOST_FULL_OFFSET = 8184
|
||||
else:
|
||||
ALMOST_EMPTY_OFFSET = 4087
|
||||
ALMOST_FULL_OFFSET = 4087
|
||||
|
||||
lines.append(
|
||||
'''
|
||||
wire fifo_rst_{site};
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 fifo_lut_{site} (
|
||||
.O(fifo_rst_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
FIFO36E1 #(
|
||||
.ALMOST_EMPTY_OFFSET({ALMOST_EMPTY_OFFSET}),
|
||||
.ALMOST_FULL_OFFSET({ALMOST_FULL_OFFSET}),
|
||||
.DATA_WIDTH({data_width}),
|
||||
.INIT(36'hFF_FFFF_FFFF),
|
||||
.SRVAL(36'hFF_FFFF_FFFF)
|
||||
) fifo_{site} (
|
||||
.RST(fifo_rst_{site})
|
||||
);
|
||||
'''.format(
|
||||
site=sites['RAMBFIFO36E1'],
|
||||
data_width=data_width,
|
||||
ALMOST_EMPTY_OFFSET=ALMOST_EMPTY_OFFSET,
|
||||
ALMOST_FULL_OFFSET=ALMOST_FULL_OFFSET))
|
||||
|
||||
return params
|
||||
|
||||
def main():
|
||||
print('''
|
||||
module top();
|
||||
''')
|
||||
|
||||
luts = LutMaker()
|
||||
lines = []
|
||||
|
||||
params_list = []
|
||||
for tile_name, sites in gen_sites():
|
||||
gen_fun = random.choice((ramb18, ramb18_2x, ramb36, fifo18, fifo18_ramb18, fifo36))
|
||||
params_list.append(gen_fun(tile_name, luts, lines, sites))
|
||||
|
||||
for lut in luts.create_wires_and_luts():
|
||||
print(lut)
|
||||
|
||||
for l in lines:
|
||||
print(l)
|
||||
|
||||
print("endmodule")
|
||||
|
||||
with open('params.json', 'w') as f:
|
||||
json.dump(params_list, f, indent=2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -3,6 +3,7 @@ import sys
|
|||
import random
|
||||
import math
|
||||
from prjxray import util
|
||||
from prjxray.lut_maker import LutMaker
|
||||
from prjxray.db import Database
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
|
||||
|
|
@ -23,53 +24,6 @@ def bram_count():
|
|||
return count
|
||||
|
||||
|
||||
class LutMaker(object):
|
||||
def __init__(self):
|
||||
self.input_lut_idx = 0
|
||||
self.output_lut_idx = 0
|
||||
self.lut_input_idx = 0
|
||||
|
||||
def get_next_input_net(self):
|
||||
net = 'lut_{}_i[{}]'.format(self.input_lut_idx, self.lut_input_idx)
|
||||
|
||||
self.lut_input_idx += 1
|
||||
if self.lut_input_idx > 5:
|
||||
self.lut_input_idx = 0
|
||||
self.input_lut_idx += 1
|
||||
|
||||
return net
|
||||
|
||||
def get_next_output_net(self):
|
||||
net = 'lut_{}_o'.format(self.output_lut_idx)
|
||||
self.output_lut_idx += 1
|
||||
return net
|
||||
|
||||
def create_wires_and_luts(self):
|
||||
if self.output_lut_idx > self.input_lut_idx:
|
||||
nluts = self.output_lut_idx
|
||||
else:
|
||||
nluts = self.input_lut_idx
|
||||
if self.lut_input_idx > 0:
|
||||
nluts += 1
|
||||
|
||||
for lut in range(nluts):
|
||||
yield """
|
||||
wire [5:0] lut_{lut}_i;
|
||||
wire lut_{lut}_o;
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 lut_{lut} (
|
||||
.I0(lut_{lut}_i[0]),
|
||||
.I1(lut_{lut}_i[1]),
|
||||
.I2(lut_{lut}_i[2]),
|
||||
.I3(lut_{lut}_i[3]),
|
||||
.I4(lut_{lut}_i[4]),
|
||||
.I5(lut_{lut}_i[5]),
|
||||
.O(lut_{lut}_o)
|
||||
);
|
||||
""".format(lut=lut)
|
||||
|
||||
|
||||
def sdp_bram(name, width, address_bits):
|
||||
depth = 2**address_bits
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ $(eval $(call fuzzer,025-bram-config,005-tilegrid))
|
|||
$(eval $(call fuzzer,026-bram-data,005-tilegrid))
|
||||
$(eval $(call fuzzer,027-bram36-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,028-fifo-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,029-bram-fifo-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,050-pip-seed,005-tilegrid))
|
||||
$(eval $(call fuzzer,051-pip-imuxlout-bypalts,050-pip-seed))
|
||||
$(eval $(call fuzzer,052-pip-clkin,050-pip-seed))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
class LutMaker(object):
|
||||
def __init__(self):
|
||||
self.input_lut_idx = 0
|
||||
self.output_lut_idx = 0
|
||||
self.lut_input_idx = 0
|
||||
|
||||
def get_next_input_net(self):
|
||||
net = 'lut_{}_i[{}]'.format(self.input_lut_idx, self.lut_input_idx)
|
||||
|
||||
self.lut_input_idx += 1
|
||||
if self.lut_input_idx > 5:
|
||||
self.lut_input_idx = 0
|
||||
self.input_lut_idx += 1
|
||||
|
||||
return net
|
||||
|
||||
def get_next_output_net(self):
|
||||
net = 'lut_{}_o'.format(self.output_lut_idx)
|
||||
self.output_lut_idx += 1
|
||||
return net
|
||||
|
||||
def create_wires_and_luts(self):
|
||||
if self.output_lut_idx > self.input_lut_idx:
|
||||
nluts = self.output_lut_idx
|
||||
else:
|
||||
nluts = self.input_lut_idx
|
||||
if self.lut_input_idx > 0:
|
||||
nluts += 1
|
||||
|
||||
for lut in range(nluts):
|
||||
yield """
|
||||
wire [5:0] lut_{lut}_i;
|
||||
wire lut_{lut}_o;
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 lut_{lut} (
|
||||
.I0(lut_{lut}_i[0]),
|
||||
.I1(lut_{lut}_i[1]),
|
||||
.I2(lut_{lut}_i[2]),
|
||||
.I3(lut_{lut}_i[3]),
|
||||
.I4(lut_{lut}_i[4]),
|
||||
.I5(lut_{lut}_i[5]),
|
||||
.O(lut_{lut}_o)
|
||||
);
|
||||
""".format(lut=lut)
|
||||
Loading…
Reference in New Issue