blob: 64fbb1a1eef6c1a04ffb060427f34a8f55e0dc79 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020 The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC
'''
Need coverage for the following:
RAM32X1S_N
RAM32X1D
RAM32M
RAM64X1S_N
RAM64X1D_N
RAM64M
RAM128X1S_N
RAM128X1D
RAM256X1S
SRL16E_N
SRLC32E_N
Note: LUT6 was added to try to simplify reduction, although it might not be needed
'''
import os, random
random.seed(0)
from prjxray import util
from prjxray import verilog
# INCREMENT is the amount of additional CLBN to be instantiated in the design.
# This makes the fuzzer compilation more robust against failures.
INCREMENT = os.getenv('CLBN', 0)
CLBN = 50 + int(INCREMENT)
print('//Requested CLBs: %s' % str(CLBN))
def gen_slicems():
for _tile_name, site_name, _site_type in util.get_roi().gen_sites(
['SLICEM']):
yield site_name
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
verilog.top_harness(DIN_N, DOUT_N)
f = open('params.csv', 'w')
f.write('module,loc,bela,belb,belc,beld\n')
slices = sorted(gen_slicems())
random.shuffle(slices)
print(
'module roi(input clk, input [%d:0] din, output [%d:0] dout);' %
(DIN_N - 1, DOUT_N - 1))
randluts = 0
for clbi, loc in zip(range(CLBN), slices):
params = ''
cparams = ''
# Multi module
# Fill with random assortment of SRL16E and SRLC32E
if random.randint(0, 1):
params = ''
module = 'my_ram_N'
# Can fit 4 per CLB
# BELable
bel_opts = [
'SRL16E',
'SRLC32E',
# Weight LUT6 more heavily to make WEMUX.CE solve quicker
'LUT6',
'LUT6',
]
bels = []
for beli in range(4):
belc = chr(ord('A') + beli)
if randluts:
bel = random.choice(bel_opts)
else:
# Force one without memory elements to bring CE bit low
bel = 'LUT6'
params += ', .%c_%s(1)' % (belc, bel)
bels.append(bel)
# Record the BELs we chose in the module (A, B, C, D)
cparams = ',' + (','.join(bels))
randluts += 1
# Greedy module
# Don't place anything else in it
# For solving muxes vs previous results
else:
modules = [
# (module, N max, FF opt)
('my_RAM32X1S_N', 4, 0),
('my_RAM32X1D', None, 0),
('my_RAM32M', None, 0),
('my_RAM64X1S_N', 4, 0),
('my_RAM64X1D_N', 2, 0),
('my_RAM64M', None, 0),
('my_RAM128X1S_N', 2, 1),
('my_RAM128X1D', None, 1),
('my_RAM256X1S', None, 1),
]
module, nmax, ff_param = random.choice(modules)
n = ''
if nmax:
n = random.randint(1, nmax)
params += ',.N(%d)' % n
cparams += ',%s' % n
ff = ''
if ff_param:
ff = random.randint(0, 1)
params += ',.FF(%d)' % ff
cparams += ',%s' % ff
# Pad to match above CSV size
cparams += ",,"
print(' %s' % module)
print(' #(.LOC("%s")%s)' % (loc, params))
sel = random.random()
if sel > .15:
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));'
% (clbi, 8 * clbi, 8 * clbi))
else:
print(
" clb_%d (.clk(clk), .din({8{1'b1}}), .dout());" %
(clbi, ))
f.write('%s,%s%s\n' % (module, loc, cparams))
f.close()
print(
'''endmodule
// ---------------------------------------------------------------------
''')
print(
'''
//***************************************************************
//Basic
module maybe_ff (input clk, din, dout);
parameter FF = 0;
generate
if (FF) begin
reg r;
assign dout = r;
always @(posedge clk) begin
r = din;
end
end else begin
assign dout = din;
end
endgenerate
endmodule
module my_RAM32X1S_N (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
//1-4
parameter N=1;
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin : loop
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM32X1S #(
) RAM32X1S (
.O(dout[i]),
.A0(din[0]),
.A1(din[1]),
.A2(din[2]),
.A3(din[3]),
.A4(din[4]),
.D(din[5]),
.WCLK(clk),
.WE(ce));
end
endgenerate
endmodule
module my_RAM32X1D (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM32X1D #(
) RAM32X1D (
.DPO(dout[0]),
.SPO(dout[1]),
.A0(din[0]),
.A1(din[1]),
.A2(din[2]),
.A3(din[3]),
.A4(din[4]),
.D(din[5]),
.DPRA0(din[6]),
.DPRA1(din[7]),
.DPRA2(din[0]),
.DPRA3(din[1]),
.DPRA4(din[2]),
.WCLK(din[3]),
.WE(din[4]));
endmodule
module my_RAM32M (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM32M #(
) RAM32M (
.DOA(dout[1:0]),
.DOB(dout[3:2]),
.DOC(dout[5:4]),
.DOD(dout[7:6]),
.ADDRA(din[4:0]),
.ADDRB(din[4:0]),
.ADDRC(din[4:0]),
.ADDRD(din[4:0]),
.DIA(din[5:4]),
.DIB(din[6:5]),
.DIC(din[7:6]),
.DID(din[1:0]),
.WCLK(din[1]),
.WE(din[2]));
endmodule
module my_RAM64X1S_N (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
//1-4
parameter N=1;
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin : loop
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM64X1S #(
) RAM64X1S (
.O(dout[i]),
.A0(din[0]),
.A1(din[1]),
.A2(din[2]),
.A3(din[3]),
.A4(din[4]),
.A5(din[5]),
.D(din[6]),
.WCLK(clk),
.WE(ce));
end
endgenerate
endmodule
module my_RAM64X1D_N (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
//1-2
parameter N=1;
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin : loop
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM64X1D #(
.INIT(64'h0),
.IS_WCLK_INVERTED(1'b0)
) ramb (
.DPO(dout[i]),
.D(din[0]),
.WCLK(clk),
.WE(din[2]),
.A0(din[3]),
.A1(din[4]),
.A2(din[5]),
.A3(din[6]),
.A4(din[7]),
.A5(din[0]),
.DPRA0(din[1]),
.DPRA1(din[2]),
.DPRA2(din[3]),
.DPRA3(din[4]),
.DPRA4(din[5]),
.DPRA5(din[6]));
end
endgenerate
endmodule
module my_RAM64M (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
parameter BEL="A6LUT";
(* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *)
RAM64M #(
) RAM64M (
.DOA(dout[0]),
.DOB(dout[1]),
.DOC(dout[2]),
.DOD(dout[3]),
.ADDRA(din[0]),
.ADDRB(din[1]),
.ADDRC(din[2]),
.ADDRD(din[3]),
.DIA(din[4]),
.DIB(din[5]),
.DIC(din[6]),
.DID(din[7]),
.WCLK(clk),
.WE(din[1]));
endmodule
module my_RAM128X1S_N (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
//1-2
parameter N=1;
parameter FF = 0;
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin : loop
wire o;
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM128X1S #(
) RAM128X1S (
.O(o),
.A0(din[0]),
.A1(din[1]),
.A2(din[2]),
.A3(din[3]),
.A4(din[4]),
.A5(din[5]),
.A6(din[6]),
.D(din[7]),
.WCLK(din[0]),
.WE(din[1]));
maybe_ff #(.FF(FF)) ff (.clk(clk), .din(o), .dout(dout[i]));
end
endgenerate
endmodule
module my_RAM128X1D (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
parameter FF = 0;
wire dpo, spo;
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM128X1D #(
.INIT(128'h0),
.IS_WCLK_INVERTED(1'b0)
) RAM128X1D (
.DPO(dpo),
.SPO(spo),
.D(din[0]),
.WCLK(clk),
.WE(din[2]));
maybe_ff #(.FF(FF)) ff0 (.clk(clk), .din(dpo), .dout(dout[0]));
maybe_ff #(.FF(FF)) ff1 (.clk(clk), .din(spo), .dout(dout[1]));
endmodule
//Dedicated LOC
module my_RAM256X1S (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
parameter FF = 0;
wire o;
(* LOC=LOC, KEEP, DONT_TOUCH *)
RAM256X1S #(
) RAM256X1S (
.O(o),
.A({din[0], din[7:0]}),
.D(din[0]),
.WCLK(din[1]),
.WE(din[2]));
maybe_ff #(.FF(FF)) ff (.clk(clk), .din(o), .dout(dout[0]));
endmodule
//***************************************************************
module my_ram_N_inst (input clk, input [7:0] din, output dout);
parameter LOC="";
parameter BEL="";
parameter N_SRL16E=0;
parameter N_SRLC32E=0;
parameter N_LUT6=0;
parameter SRLINIT = 32'h00000000;
parameter LUTINIT6 = 64'h0000_0000_0000_0000;
wire ce = din[4];
generate
//********************
if (N_SRL16E) begin
(* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *)
SRL16E #(
) lut (
.Q(dout),
.A0(din[0]),
.A1(din[1]),
.A2(din[2]),
.A3(din[3]),
.CE(ce),
.CLK(clk),
.D(din[6]));
end
if (N_SRLC32E) begin
(* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *)
SRLC32E #(
.INIT(SRLINIT),
.IS_CLK_INVERTED(1'b0)
) lut (
.Q(dout),
.Q31(),
.A(din[4:0]),
.CE(ce),
.CLK(clk),
.D(din[7]));
end
if (N_LUT6) begin
(* LOC=LOC, BEL=BEL, KEEP, DONT_TOUCH *)
LUT6_2 #(
.INIT(LUTINIT6)
) lut (
.I0(din[0]),
.I1(din[1]),
.I2(din[2]),
.I3(din[3]),
.I4(din[4]),
.I5(din[5]),
.O5(),
.O6(dout));
end
endgenerate
endmodule
/*
Supermodule for LOC'able prims
Mix and match as needed
Specify at most one function generator per LUT
*/
module my_ram_N (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = "";
parameter D_SRL16E=0;
parameter D_SRLC32E=0;
parameter D_LUT6=0;
parameter C_SRL16E=0;
parameter C_SRLC32E=0;
parameter C_LUT6=0;
parameter B_SRL16E=0;
parameter B_SRLC32E=0;
parameter B_LUT6=0;
parameter A_SRL16E=0;
parameter A_SRLC32E=0;
parameter A_LUT6=0;
my_ram_N_inst #(.LOC(LOC), .BEL("D6LUT"), .N_SRL16E(D_SRL16E), .N_SRLC32E(D_SRLC32E), .N_LUT6(D_LUT6))
lutd(.clk(clk), .din(din), .dout(dout[3]));
my_ram_N_inst #(.LOC(LOC), .BEL("C6LUT"), .N_SRL16E(C_SRL16E), .N_SRLC32E(C_SRLC32E), .N_LUT6(C_LUT6))
lutc(.clk(clk), .din(din), .dout(dout[2]));
my_ram_N_inst #(.LOC(LOC), .BEL("B6LUT"), .N_SRL16E(B_SRL16E), .N_SRLC32E(B_SRLC32E), .N_LUT6(B_LUT6))
lutb(.clk(clk), .din(din), .dout(dout[1]));
my_ram_N_inst #(.LOC(LOC), .BEL("A6LUT"), .N_SRL16E(A_SRL16E), .N_SRLC32E(A_SRLC32E), .N_LUT6(A_LUT6))
luta(.clk(clk), .din(din), .dout(dout[0]));
endmodule
''')