mirror of https://github.com/openXC7/prjxray.git
478 lines
12 KiB
Python
478 lines
12 KiB
Python
#!/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 = gen_slicems()
|
|
print(
|
|
'module roi(input clk, input [%d:0] din, output [%d:0] dout);' %
|
|
(DIN_N - 1, DOUT_N - 1))
|
|
randluts = 0
|
|
for clbi in range(CLBN):
|
|
loc = next(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))
|
|
print(
|
|
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));'
|
|
% (clbi, 8 * clbi, 8 * 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
|
|
|
|
''')
|