2017-11-08 19:57:09 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
from fuzzconfig import *
|
|
|
|
|
import numpy as np
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
device_class = os.getenv("ICEDEVICE")
|
|
|
|
|
|
|
|
|
|
assert device_class == "5k"
|
|
|
|
|
|
|
|
|
|
working_dir = "work_%s_dsp" % (device_class, )
|
|
|
|
|
|
|
|
|
|
os.system("rm -rf " + working_dir)
|
|
|
|
|
os.mkdir(working_dir)
|
|
|
|
|
|
|
|
|
|
def randbin(n):
|
|
|
|
|
return "".join([np.random.choice(["0", "1"]) for i in range(n)])
|
|
|
|
|
|
|
|
|
|
#Only certain combinations are allowed in icecube, list them here
|
|
|
|
|
#This is not a complete set, but enough to cover all bits except cbit13, which
|
|
|
|
|
#is not set in any allowed config (?)
|
2018-01-22 17:34:51 +01:00
|
|
|
allowed_configs = [("0010000010000001001110110", "SB_MAC16_MUL_U_8X8_ALL_PIPELINE"),
|
|
|
|
|
("1110000010000001001110110", "SB_MAC16_MUL_S_8X8_ALL_PIPELINE"),
|
|
|
|
|
("0010000010000001000000000", "SB_MAC16_MUL_U_8X8_BYPASS"),
|
|
|
|
|
("1110000010000001000000000", "SB_MAC16_MUL_S_8X8_BYPASS"),
|
|
|
|
|
("0000000011000001111110110", "SB_MAC16_MUL_U_16X16_ALL_PIPELINE"),
|
|
|
|
|
("1100000011000001111110110", "SB_MAC16_MUL_S_16X16_ALL_PIPELINE"),
|
|
|
|
|
("0000000011000001110000110", "SB_MAC16_MUL_U_16X16_IM_BYPASS"),
|
|
|
|
|
("1100000011000001110000110", "SB_MAC16_MUL_S_16X16_IM_BYPASS"),
|
|
|
|
|
("0000000011000001100000000", "SB_MAC16_MUL_U_16X16_BYPASS"),
|
|
|
|
|
("1100000011000001100000000", "SB_MAC16_MUL_S_16X16_BYPASS"),
|
|
|
|
|
("0010000101000010111111111", "SB_MAC16_MAC_U_8X8_ALL_PIPELINE"),
|
|
|
|
|
("0010000101000010100001111", "SB_MAC16_MAC_U_8X8_IM_BYPASS"),
|
|
|
|
|
("0010000101000010100000000", "SB_MAC16_MAC_U_8X8_BYPASS"),
|
|
|
|
|
("0000001001100100111111111", "SB_MAC16_MAC_U_16X16_ALL_PIPELINE"),
|
|
|
|
|
("0001001001100100111111111", "SB_MAC16_MAC_U_16X16_CASC_ALL_PIPELINE"),
|
|
|
|
|
("0001101001100100111111111", "SB_MAC16_MAC_U_16X16_CIN_ALL_PIPELINE"),
|
|
|
|
|
("0000001001100100110001111", "SB_MAC16_MAC_U_16X16_IM_BYPASS"),
|
|
|
|
|
("0000001001100100100000000", "SB_MAC16_MAC_U_16X16_BYPASS"),
|
|
|
|
|
("1100001001100100110001111", "SB_MAC16_MAC_S_16X16_IM_BYPASS"),
|
|
|
|
|
("0010000001000000100001111", "SB_MAC16_ACC_U_16P16_ALL_PIPELINE"),
|
|
|
|
|
("0010000001000000100000000", "SB_MAC16_ACC_U_16P16_BYPASS"),
|
|
|
|
|
("0010000001100000100001111", "SB_MAC16_ACC_U_32P32_ALL_PIPELINE"),
|
|
|
|
|
("0010000001100000100000000", "SB_MAC16_ACC_U_32P32_BYPASS"),
|
|
|
|
|
("0010010001001000100001111", "SB_MAC16_ADS_U_16P16_ALL_PIPELINE"),
|
|
|
|
|
("0010010000001000000000000", "SB_MAC16_ADS_U_16P16_BYPASS"),
|
|
|
|
|
("0010010001101000100001111", "SB_MAC16_ADS_U_32P32_ALL_PIPELINE"),
|
|
|
|
|
("0010010000101000000000000", "SB_MAC16_ADS_U_32P32_BYPASS"),
|
|
|
|
|
("0010010101001010111111111", "SB_MAC16_MAS_U_8X8_ALL_PIPELINE")]
|
|
|
|
|
|
2017-11-08 19:57:09 +01:00
|
|
|
|
|
|
|
|
coverage = set()
|
|
|
|
|
for c in allowed_configs:
|
2018-01-22 17:34:51 +01:00
|
|
|
cfg, name = c
|
2017-11-08 19:57:09 +01:00
|
|
|
for i in range(25):
|
2018-01-22 17:34:51 +01:00
|
|
|
if cfg[i] == "1":
|
2017-11-08 19:57:09 +01:00
|
|
|
coverage.add(i)
|
|
|
|
|
|
|
|
|
|
assert len(coverage) >= 24
|
|
|
|
|
|
|
|
|
|
#print(len(coverage))
|
|
|
|
|
#print(coverage)
|
|
|
|
|
|
|
|
|
|
for idx in range(num):
|
|
|
|
|
with open(working_dir + "/dsp_%02d.v" % idx, "w") as f:
|
|
|
|
|
glbs = ["glb[%d]" % i for i in range(np.random.randint(8)+1)]
|
2018-01-22 17:34:51 +01:00
|
|
|
|
|
|
|
|
config = allowed_configs[np.random.randint(len(allowed_configs))]
|
|
|
|
|
params, cfgname = config
|
|
|
|
|
with open(working_dir + "/dsp_%02d.dsp" % idx, "w") as dspf:
|
|
|
|
|
dspf.write(cfgname + "\n")
|
|
|
|
|
params = params[::-1]
|
|
|
|
|
|
2017-11-08 19:57:09 +01:00
|
|
|
# TODO: ce should be on this list, but causes routing failures
|
|
|
|
|
glbs_choice = ["clk", "a", "b", "c", "d,", "ah", "bh", "ch", "dh", "irt", "irb", "ort", "orb", "olt", "olb", "ast", "asb", "oht", "ohb", "sei"]
|
|
|
|
|
print("""
|
|
|
|
|
module top (
|
|
|
|
|
input [%d:0] glb_pins,
|
|
|
|
|
input [%d:0] in_pins,
|
|
|
|
|
output [15:0] out_pins
|
|
|
|
|
);
|
|
|
|
|
wire [%d:0] glb, glb_pins;
|
|
|
|
|
SB_GB gbufs [%d:0] (
|
|
|
|
|
.USER_SIGNAL_TO_GLOBAL_BUFFER(glb_pins),
|
|
|
|
|
.GLOBAL_BUFFER_OUTPUT(glb)
|
|
|
|
|
);
|
|
|
|
|
""" % (len(glbs)-1, len(pins) - len(glbs) - 16 - 1, len(glbs)-1, len(glbs)-1), file=f)
|
|
|
|
|
bits = ["in_pins[%d]" % i for i in range(100)]
|
|
|
|
|
bits = list(np.random.permutation(bits))
|
|
|
|
|
for i in range(num_dsp):
|
|
|
|
|
tmp = list(np.random.permutation(bits))
|
|
|
|
|
bits_c = [tmp.pop() for k in range(16)]
|
|
|
|
|
bits_a = [tmp.pop() for k in range(16)]
|
|
|
|
|
bits_b = [tmp.pop() for k in range(16)]
|
|
|
|
|
bits_d = [tmp.pop() for k in range(16)]
|
|
|
|
|
bit_ce = tmp.pop()
|
|
|
|
|
bit_clk = tmp.pop()
|
|
|
|
|
bit_ahold = tmp.pop()
|
|
|
|
|
bit_bhold = tmp.pop()
|
|
|
|
|
bit_chold = tmp.pop()
|
|
|
|
|
bit_dhold = tmp.pop()
|
|
|
|
|
bit_irsttop = tmp.pop()
|
|
|
|
|
bit_irstbot = tmp.pop()
|
|
|
|
|
bit_orsttop = tmp.pop()
|
|
|
|
|
bit_orstbot = tmp.pop()
|
|
|
|
|
bit_oloadtop = tmp.pop()
|
|
|
|
|
bit_oloadbot = tmp.pop()
|
|
|
|
|
bit_addsubtop = tmp.pop()
|
|
|
|
|
bit_addsubbot = tmp.pop()
|
|
|
|
|
bit_oholdtop = tmp.pop()
|
|
|
|
|
bit_oholdbot = tmp.pop()
|
|
|
|
|
|
|
|
|
|
aci_opts = ["1'b0"]
|
|
|
|
|
if i > 0 and i % 4 != 0:
|
|
|
|
|
aci_opts.append("out_%d[33]" % (i-1));
|
|
|
|
|
sei_opts = ["1'b0"]
|
|
|
|
|
if i > 0 and i % 4 != 0:
|
|
|
|
|
sei_opts.append("out_%d[34]" % (i - 1));
|
|
|
|
|
|
|
|
|
|
bit_ci = tmp.pop()
|
|
|
|
|
bit_accumci = np.random.choice(aci_opts)
|
|
|
|
|
bit_signextin = np.random.choice(sei_opts)
|
|
|
|
|
|
|
|
|
|
if len(glbs) != 0:
|
|
|
|
|
s = np.random.choice(glbs_choice)
|
|
|
|
|
glbs_choice.remove(s)
|
|
|
|
|
if s == "clk": bit_clk = glbs.pop()
|
|
|
|
|
if s == "a": bits_a[np.random.randint(len(bits_a))] = glbs.pop()
|
|
|
|
|
if s == "b": bits_b[np.random.randint(len(bits_b))] = glbs.pop()
|
|
|
|
|
if s == "c": bits_c[np.random.randint(len(bits_c))] = glbs.pop()
|
|
|
|
|
if s == "d": bits_d[np.random.randint(len(bits_d))] = glbs.pop()
|
|
|
|
|
if s == "ah": bit_ahold = glbs.pop()
|
|
|
|
|
if s == "bh": bit_bhold = glbs.pop()
|
|
|
|
|
if s == "ch": bit_chold = glbs.pop()
|
|
|
|
|
if s == "dh": bit_dhold = glbs.pop()
|
|
|
|
|
if s == "irt": bit_irsttop = glbs.pop()
|
|
|
|
|
if s == "irb": bit_irstbot = glbs.pop()
|
|
|
|
|
if s == "ort": bit_orsttop = glbs.pop()
|
|
|
|
|
if s == "orb": bit_orstbot = glbs.pop()
|
|
|
|
|
if s == "olt": bit_oloadtop = glbs.pop()
|
|
|
|
|
if s == "olb": bit_oloadbot = glbs.pop()
|
|
|
|
|
if s == "ast": bit_addsubtop = glbs.pop()
|
|
|
|
|
if s == "asb": bit_addsubbot = glbs.pop()
|
|
|
|
|
if s == "oht": bit_oholdtop = glbs.pop()
|
|
|
|
|
if s == "ohb": bit_oholdbot = glbs.pop()
|
|
|
|
|
if s == "ci": bit_ci = glbs.pop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bits_a = "{%s}" % ", ".join(bits_a)
|
|
|
|
|
bits_b = "{%s}" % ", ".join(bits_b)
|
|
|
|
|
bits_c = "{%s}" % ", ".join(bits_c)
|
|
|
|
|
bits_d = "{%s}" % ", ".join(bits_d)
|
|
|
|
|
|
|
|
|
|
negclk = randbin(1)
|
2018-01-22 17:34:51 +01:00
|
|
|
|
2017-11-08 19:57:09 +01:00
|
|
|
print("""
|
|
|
|
|
wire [34:0] out_%d;
|
|
|
|
|
SB_MAC16 #(
|
|
|
|
|
.NEG_TRIGGER(1'b%s),
|
|
|
|
|
.C_REG(1'b%s),
|
|
|
|
|
.A_REG(1'b%s),
|
|
|
|
|
.B_REG(1'b%s),
|
|
|
|
|
.D_REG(1'b%s),
|
|
|
|
|
.TOP_8x8_MULT_REG(1'b%s),
|
|
|
|
|
.BOT_8x8_MULT_REG(1'b%s),
|
|
|
|
|
.PIPELINE_16x16_MULT_REG1(1'b%s),
|
|
|
|
|
.PIPELINE_16x16_MULT_REG2(1'b%s),
|
|
|
|
|
.TOPOUTPUT_SELECT(2'b%s),
|
|
|
|
|
.TOPADDSUB_LOWERINPUT(2'b%s),
|
|
|
|
|
.TOPADDSUB_UPPERINPUT(1'b%s),
|
|
|
|
|
.TOPADDSUB_CARRYSELECT(2'b%s),
|
|
|
|
|
.BOTOUTPUT_SELECT(2'b%s),
|
|
|
|
|
.BOTADDSUB_LOWERINPUT(2'b%s),
|
|
|
|
|
.BOTADDSUB_UPPERINPUT(1'b%s),
|
|
|
|
|
.BOTADDSUB_CARRYSELECT(2'b%s),
|
|
|
|
|
.MODE_8x8(1'b%s),
|
|
|
|
|
.A_SIGNED(1'b%s),
|
|
|
|
|
.B_SIGNED(1'b%s)
|
|
|
|
|
) dsp_%d (
|
|
|
|
|
.CLK(%s),
|
|
|
|
|
.CE(%s),
|
|
|
|
|
.C(%s),
|
|
|
|
|
.A(%s),
|
|
|
|
|
.B(%s),
|
|
|
|
|
.D(%s),
|
|
|
|
|
.AHOLD(%s),
|
|
|
|
|
.BHOLD(%s),
|
|
|
|
|
.CHOLD(%s),
|
|
|
|
|
.DHOLD(%s),
|
|
|
|
|
.IRSTTOP(%s),
|
|
|
|
|
.IRSTBOT(%s),
|
|
|
|
|
.ORSTTOP(%s),
|
|
|
|
|
.ORSTBOT(%s),
|
|
|
|
|
.OLOADTOP(%s),
|
|
|
|
|
.OLOADBOT(%s),
|
|
|
|
|
.ADDSUBTOP(%s),
|
|
|
|
|
.ADDSUBBOT(%s),
|
|
|
|
|
.OHOLDTOP(%s),
|
|
|
|
|
.OHOLDBOT(%s),
|
|
|
|
|
.CI(%s),
|
|
|
|
|
.ACCUMCI(%s),
|
|
|
|
|
.SIGNEXTIN(%s),
|
|
|
|
|
.O(out_%d[31:0]),
|
|
|
|
|
.CO(out_%d[32]),
|
|
|
|
|
.ACCUMCO(out_%d[33]),
|
|
|
|
|
.SIGNEXTOUT(out_%d[34])
|
|
|
|
|
);"""
|
|
|
|
|
% (
|
|
|
|
|
i,
|
|
|
|
|
negclk,
|
|
|
|
|
params[0], params[1], params[2], params[3],
|
|
|
|
|
params[4], params[5], params[6], params[7],
|
|
|
|
|
params[8:10][::-1], params[10:12][::-1], params[12], params[13:15][::-1],
|
|
|
|
|
params[15:17][::-1], params[17:19][::-1], params[19], params[20:22][::-1],
|
|
|
|
|
params[22], params[23], params[24],
|
|
|
|
|
i,
|
|
|
|
|
bit_clk, bit_ce, bits_c, bits_a, bits_b, bits_d,
|
|
|
|
|
bit_ahold, bit_bhold, bit_chold, bit_dhold,
|
|
|
|
|
bit_irsttop, bit_irstbot, bit_orsttop, bit_orstbot,
|
|
|
|
|
bit_oloadtop, bit_oloadbot, bit_addsubtop, bit_addsubbot,
|
|
|
|
|
bit_oholdtop, bit_oholdbot,
|
|
|
|
|
bit_ci, bit_accumci, bit_signextin,
|
|
|
|
|
i, i, i, i
|
|
|
|
|
), file=f)
|
|
|
|
|
bits = list(np.random.permutation(bits))
|
|
|
|
|
for k in range(33):
|
|
|
|
|
bits[k] = "out_%d[%d] ^ %s" % (i, k, bits[k])
|
|
|
|
|
for k in range(16):
|
|
|
|
|
print("assign out_pins[%d] = out_%d[%d] ^ out_%d[%d];" % (k, i, np.random.randint(33), i, np.random.randint(33)), file=f)
|
|
|
|
|
print("endmodule", file=f)
|
|
|
|
|
with open(working_dir + "/dsp_%02d.pcf" % idx, "w") as f:
|
|
|
|
|
p = list(np.random.permutation(pins))
|
|
|
|
|
for i in range(len(pins) - len(glbs) - 16):
|
|
|
|
|
print("set_io in_pins[%d] %s" % (i, p.pop()), file=f)
|
|
|
|
|
for i in range(16):
|
|
|
|
|
print("set_io out_pins[%d] %s" % (i, p.pop()), file=f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output_makefile(working_dir, "dsp")
|