mirror of https://github.com/openXC7/prjxray.git
186 lines
4.4 KiB
Python
186 lines
4.4 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 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))
|
|
|
|
|
|
def bram_count():
|
|
db = Database(util.get_db_root(), util.get_part())
|
|
grid = db.grid()
|
|
|
|
count = 0
|
|
for tile_name in grid.tiles():
|
|
loc = grid.loc_of_tilename(tile_name)
|
|
gridinfo = grid.gridinfo_at_loc(loc)
|
|
|
|
for site_name, site_type in gridinfo.sites.items():
|
|
if site_type in ['RAMBFIFO36E1']:
|
|
count += 1
|
|
|
|
return count
|
|
|
|
|
|
def sdp_bram(name, width, address_bits):
|
|
depth = 2**address_bits
|
|
|
|
return '''
|
|
module {name}(
|
|
// Write port
|
|
input wrclk,
|
|
input [{width}-1:0] di,
|
|
input wren,
|
|
input [{address_bits}-1:0] wraddr,
|
|
// Read port
|
|
input rdclk,
|
|
input rden,
|
|
input [{address_bits}-1:0] rdaddr,
|
|
output reg [{width}-1:0] do);
|
|
|
|
(* ram_style = "block" *) reg [{width}-1:0] ram[0:{depth}];
|
|
|
|
always @ (posedge wrclk) begin
|
|
if(wren == 1) begin
|
|
ram[wraddr] <= di;
|
|
end
|
|
end
|
|
|
|
always @ (posedge rdclk) begin
|
|
if(rden == 1) begin
|
|
do <= ram[rdaddr];
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
'''.format(
|
|
name=name,
|
|
width=width,
|
|
address_bits=address_bits,
|
|
depth=depth,
|
|
)
|
|
|
|
|
|
MAX_BRAM = 8
|
|
|
|
|
|
def emit_sdp_bram(luts, name, modules, lines, width, address_bits):
|
|
modules.append(sdp_bram(name=name, width=width, address_bits=address_bits))
|
|
|
|
lines.append(
|
|
'''
|
|
wire [{address_bits}-1:0] {name}_wraddr;
|
|
wire [{address_bits}-1:0] {name}_rdaddr;
|
|
'''.format(
|
|
name=name,
|
|
address_bits=address_bits,
|
|
))
|
|
|
|
for bit in range(address_bits):
|
|
lines.append(
|
|
"""
|
|
assign {name}_wraddr[{bit}] = {net};""".format(
|
|
name=name, bit=bit, net=luts.get_next_output_net()))
|
|
|
|
for bit in range(address_bits):
|
|
lines.append(
|
|
"""
|
|
assign {name}_rdaddr[{bit}] = {net};""".format(
|
|
name=name, bit=bit, net=luts.get_next_output_net()))
|
|
|
|
lines.append(
|
|
'''
|
|
(* KEEP, DONT_TOUCH *)
|
|
{name} {name}_inst(
|
|
.wraddr({name}_wraddr),
|
|
.rdaddr({name}_rdaddr)
|
|
);
|
|
'''.format(name=name))
|
|
|
|
return width, address_bits, math.ceil(
|
|
float(width) / 72) * 72 * (2**address_bits)
|
|
|
|
|
|
def max_address_bits(width):
|
|
return math.floor(math.log(float(MAX_BRAM * 36 * 1024) / width, 2))
|
|
|
|
|
|
def random_sdp_bram(luts, name, modules, lines):
|
|
sdp_choices = set()
|
|
|
|
for width in (1, 2, 4, 8, 16, 18, 32, 36):
|
|
sdp_choices.add((width, (1, max_address_bits(width))))
|
|
|
|
for nbram in range(2, MAX_BRAM + 1):
|
|
sdp_choices.add((nbram * 32, (1, max_address_bits(nbram * 32))))
|
|
sdp_choices.add((nbram * 36, (1, max_address_bits(nbram * 36))))
|
|
sdp_choices.add((nbram * 16, (1, max_address_bits(nbram * 16))))
|
|
sdp_choices.add((nbram * 32, (1, max_address_bits(nbram * 32))))
|
|
|
|
# Bias some wide but shallow BRAMs to toggle the lower address bits
|
|
# more.
|
|
for address_bits in range(1, 4):
|
|
sdp_choices.add((nbram * 16, (address_bits, address_bits)))
|
|
|
|
sdp_choices = sorted(sdp_choices)
|
|
|
|
width, address_bits_range = random.choice(sdp_choices)
|
|
address_bits = random.randint(*address_bits_range)
|
|
return emit_sdp_bram(luts, name, modules, lines, width, address_bits)
|
|
|
|
|
|
def run():
|
|
luts = LutMaker()
|
|
count = bram_count()
|
|
|
|
max_bram_count = random.randint(1, 200)
|
|
|
|
modules = []
|
|
lines = []
|
|
|
|
idx = 0
|
|
while count > MAX_BRAM:
|
|
width, address_bits, bits = random_sdp_bram(
|
|
luts, "ram{}".format(idx), modules, lines)
|
|
|
|
brams = math.ceil(bits / float(36 * 1024))
|
|
|
|
count -= brams
|
|
|
|
print(width, address_bits, bits, brams, count, file=sys.stderr)
|
|
idx += 1
|
|
|
|
if idx >= max_bram_count:
|
|
break
|
|
|
|
for module in modules:
|
|
print(module)
|
|
|
|
print('''
|
|
module top();
|
|
''')
|
|
|
|
for lut in luts.create_wires_and_luts():
|
|
print(lut)
|
|
|
|
for l in lines:
|
|
print(l)
|
|
|
|
print("endmodule")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
run()
|