mirror of https://github.com/openXC7/prjxray.git
250 lines
7.7 KiB
Python
250 lines
7.7 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
|
|
import os
|
|
import random
|
|
random.seed(int(os.getenv("SEED"), 16))
|
|
from prjxray import util
|
|
from prjxray import verilog
|
|
from prjxray.verilog import vrandbit, vrandbits
|
|
import json
|
|
|
|
|
|
def gen_bram18():
|
|
'''
|
|
sample:
|
|
"sites": {
|
|
"RAMB18_X0Y50": "FIFO18E1",
|
|
"RAMB18_X0Y51": "RAMB18E1",
|
|
"RAMB36_X0Y25": "RAMBFIFO36E1"
|
|
},
|
|
'''
|
|
for _tile_name, site_name, _site_type in sorted(util.get_roi().gen_sites(
|
|
['RAMB18E1', 'FIFO18E1'])):
|
|
yield site_name
|
|
|
|
|
|
def gen_bram36():
|
|
for _tile_name, site_name, _site_type in util.get_roi().gen_sites(
|
|
['RAMBFIFO36E1']):
|
|
yield site_name
|
|
|
|
|
|
def gen_brams():
|
|
'''
|
|
Correctly assign a site to either bram36 or 2x bram18
|
|
'''
|
|
# XXX: mix 18 and 36?
|
|
for site in gen_bram18():
|
|
yield ('RAMB18E1', site)
|
|
|
|
|
|
def place_bram18(site, loci):
|
|
ports = {
|
|
'clk': 'clk',
|
|
'din': 'din[ %d +: 8]' % (8 * loci, ),
|
|
'dout': 'dout[ %d +: 8]' % (8 * loci, ),
|
|
}
|
|
|
|
write_modes = ["WRITE_FIRST", "READ_FIRST", "NO_CHANGE"]
|
|
collisions = ["DELAYED_WRITE", "PERFORMANCE"]
|
|
priorities = ["RSTREG", "REGCE"]
|
|
|
|
# Datasheet says 72 is legal in some cases, but think its a copy paste error from BRAM36
|
|
# also 0 and 36 aren't real sizes
|
|
# Bias choice to 18 as its needed to solve certain bits quickly
|
|
widths = [1, 2, 4, 9, 18, 18, 36]
|
|
mode = '"TDP"'
|
|
|
|
read_width_a = random.choice(widths)
|
|
write_width_b = random.choice(widths)
|
|
if read_width_a >= 36 or write_width_b >= 36:
|
|
read_width_b = 0
|
|
write_width_a = 0
|
|
mode = '"SDP"'
|
|
doa_reg = vrandbit()
|
|
dob_reg = doa_reg
|
|
write_modes = ["WRITE_FIRST", "READ_FIRST"]
|
|
rstreg_priority_a = verilog.quote(random.choice(priorities))
|
|
rstreg_priority_b = rstreg_priority_a
|
|
else:
|
|
read_width_b = random.choice(widths)
|
|
write_width_a = random.choice(widths)
|
|
doa_reg = vrandbit()
|
|
dob_reg = vrandbit()
|
|
rstreg_priority_a = verilog.quote(random.choice(priorities))
|
|
rstreg_priority_b = verilog.quote(random.choice(priorities))
|
|
|
|
params = {
|
|
'LOC': verilog.quote(site),
|
|
'IS_CLKARDCLK_INVERTED': vrandbit(),
|
|
'IS_CLKBWRCLK_INVERTED': vrandbit(),
|
|
'IS_ENARDEN_INVERTED': vrandbit(),
|
|
'IS_ENBWREN_INVERTED': vrandbit(),
|
|
'IS_RSTRAMARSTRAM_INVERTED': vrandbit(),
|
|
'IS_RSTRAMB_INVERTED': vrandbit(),
|
|
'IS_RSTREGARSTREG_INVERTED': vrandbit(),
|
|
'IS_RSTREGB_INVERTED': vrandbit(),
|
|
'RAM_MODE': mode,
|
|
'WRITE_MODE_A': verilog.quote(random.choice(write_modes)),
|
|
'WRITE_MODE_B': verilog.quote(random.choice(write_modes)),
|
|
"DOA_REG": doa_reg,
|
|
"DOB_REG": dob_reg,
|
|
"SRVAL_A": vrandbits(18),
|
|
"SRVAL_B": vrandbits(18),
|
|
"INIT_A": vrandbits(18),
|
|
"INIT_B": vrandbits(18),
|
|
"READ_WIDTH_A": read_width_a,
|
|
"READ_WIDTH_B": read_width_b,
|
|
"WRITE_WIDTH_A": write_width_a,
|
|
"WRITE_WIDTH_B": write_width_b,
|
|
"RDADDR_COLLISION_HWCONFIG": verilog.quote(random.choice(collisions)),
|
|
"RSTREG_PRIORITY_A": rstreg_priority_a,
|
|
"RSTREG_PRIORITY_B": rstreg_priority_b,
|
|
}
|
|
|
|
return ('my_RAMB18E1', ports, params)
|
|
|
|
|
|
def main():
|
|
brams = list(gen_brams())
|
|
DUTN = len(brams)
|
|
DIN_N = DUTN * 8
|
|
DOUT_N = DUTN * 8
|
|
|
|
verilog.top_harness(DIN_N, DOUT_N)
|
|
|
|
f = open('params.jl', 'w')
|
|
f.write('module,loc,params\n')
|
|
print(
|
|
'module roi(input clk, input [%d:0] din, output [%d:0] dout);' %
|
|
(DIN_N - 1, DOUT_N - 1))
|
|
|
|
for loci, (site_type, site) in enumerate(brams):
|
|
modname, ports, params = {
|
|
'RAMB18E1': place_bram18,
|
|
#'RAMBFIFO36E1': place_bram36,
|
|
}[site_type](site, loci)
|
|
|
|
verilog.instance(modname, 'inst_%u' % loci, ports, params=params)
|
|
|
|
j = {'module': modname, 'i': loci, 'params': params}
|
|
f.write('%s\n' % (json.dumps(j)))
|
|
print('')
|
|
|
|
f.close()
|
|
print(
|
|
'''endmodule
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
''')
|
|
|
|
# RAMB18E1
|
|
print(
|
|
'''
|
|
module my_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout);
|
|
parameter LOC = "";
|
|
parameter IS_CLKARDCLK_INVERTED = 1'b0;
|
|
parameter IS_CLKBWRCLK_INVERTED = 1'b0;
|
|
parameter IS_ENARDEN_INVERTED = 1'b0;
|
|
parameter IS_ENBWREN_INVERTED = 1'b0;
|
|
parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0;
|
|
parameter IS_RSTRAMB_INVERTED = 1'b0;
|
|
parameter IS_RSTREGARSTREG_INVERTED = 1'b0;
|
|
parameter IS_RSTREGB_INVERTED = 1'b0;
|
|
parameter RAM_MODE = "TDP";
|
|
parameter WRITE_MODE_A = "WRITE_FIRST";
|
|
parameter WRITE_MODE_B = "WRITE_FIRST";
|
|
parameter RDADDR_COLLISION_HWCONFIG = "DELAYED_WRITE";
|
|
parameter RSTREG_PRIORITY_A = "RSTREG";
|
|
parameter RSTREG_PRIORITY_B = "RSTREG";
|
|
|
|
parameter DOA_REG = 1'b0;
|
|
parameter DOB_REG = 1'b0;
|
|
parameter SRVAL_A = 18'b0;
|
|
parameter SRVAL_B = 18'b0;
|
|
parameter INIT_A = 18'b0;
|
|
parameter INIT_B = 18'b0;
|
|
|
|
parameter READ_WIDTH_A = 0;
|
|
parameter READ_WIDTH_B = 0;
|
|
parameter WRITE_WIDTH_A = 0;
|
|
parameter WRITE_WIDTH_B = 0;
|
|
''')
|
|
print('''\
|
|
(* LOC=LOC *)
|
|
RAMB18E1 #(''')
|
|
for i in range(8):
|
|
print(" .INITP_%02X(256'b0)," % (i, ))
|
|
print('')
|
|
for i in range(0x40):
|
|
print(" .INIT_%02X(256'b0)," % (i, ))
|
|
print('')
|
|
print(
|
|
'''
|
|
.IS_CLKARDCLK_INVERTED(IS_CLKARDCLK_INVERTED),
|
|
.IS_CLKBWRCLK_INVERTED(IS_CLKBWRCLK_INVERTED),
|
|
.IS_ENARDEN_INVERTED(IS_ENARDEN_INVERTED),
|
|
.IS_ENBWREN_INVERTED(IS_ENBWREN_INVERTED),
|
|
.IS_RSTRAMARSTRAM_INVERTED(IS_RSTRAMARSTRAM_INVERTED),
|
|
.IS_RSTRAMB_INVERTED(IS_RSTRAMB_INVERTED),
|
|
.IS_RSTREGARSTREG_INVERTED(IS_RSTREGARSTREG_INVERTED),
|
|
.IS_RSTREGB_INVERTED(IS_RSTREGB_INVERTED),
|
|
.RAM_MODE(RAM_MODE),
|
|
.WRITE_MODE_A(WRITE_MODE_A),
|
|
.WRITE_MODE_B(WRITE_MODE_B),
|
|
|
|
.DOA_REG(DOA_REG),
|
|
.DOB_REG(DOB_REG),
|
|
.SRVAL_A(SRVAL_A),
|
|
.SRVAL_B(SRVAL_B),
|
|
.INIT_A(INIT_A),
|
|
.INIT_B(INIT_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),
|
|
|
|
.RDADDR_COLLISION_HWCONFIG(RDADDR_COLLISION_HWCONFIG),
|
|
|
|
.RSTREG_PRIORITY_A(RSTREG_PRIORITY_A),
|
|
.RSTREG_PRIORITY_B(RSTREG_PRIORITY_B)
|
|
) ram (
|
|
.CLKARDCLK(din[0]),
|
|
.CLKBWRCLK(din[1]),
|
|
.ENARDEN(din[2]),
|
|
.ENBWREN(din[3]),
|
|
.REGCEAREGCE(din[4]),
|
|
.REGCEB(din[5]),
|
|
.RSTRAMARSTRAM(din[6]),
|
|
.RSTRAMB(din[7]),
|
|
.RSTREGARSTREG(din[0]),
|
|
.RSTREGB(din[1]),
|
|
.ADDRARDADDR(din[2]),
|
|
.ADDRBWRADDR(din[3]),
|
|
.DIADI(din[4]),
|
|
.DIBDI(din[5]),
|
|
.DIPADIP(din[6]),
|
|
.DIPBDIP(din[7]),
|
|
.WEA(1'b0),
|
|
.WEBWE(din[1]),
|
|
.DOADO(dout[0]),
|
|
.DOBDO(dout[1]),
|
|
.DOPADOP(dout[2]),
|
|
.DOPBDOP(dout[3]));
|
|
endmodule
|
|
''')
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|