mirror of https://github.com/openXC7/prjxray.git
138 lines
5.1 KiB
Python
138 lines
5.1 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
|
|
|
|
from prjxray import util
|
|
import os
|
|
import json
|
|
'''
|
|
Local utils script to hold shared code of the 005-tilegrid fuzzer scripts
|
|
'''
|
|
|
|
|
|
class TileFrames:
|
|
"""
|
|
Class for getting the number of frames used for configuring a tile
|
|
with the specified baseaddress using the information from the part's json file
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.tile_address_to_frames = dict()
|
|
|
|
def get_baseaddress(self, region, bus, row, column):
|
|
assert bus == 'BLOCK_RAM' or bus == 'CLB_IO_CLK', 'Incorrect block type'
|
|
address = (row << 17) + (column << 7) + (
|
|
(1 << 22) if region == 'bottom' else 0) + (
|
|
(1 << 23) if bus == 'BLOCK_RAM' else 0)
|
|
return address
|
|
|
|
def initialize_address_to_frames(self):
|
|
with open(os.path.join(os.getenv('XRAY_FAMILY_DIR'),
|
|
os.getenv('XRAY_PART'), 'part.json')) as pf:
|
|
part_json = json.load(pf)
|
|
for clock_region, rows in part_json['global_clock_regions'].items():
|
|
for row, buses in rows['rows'].items():
|
|
for bus, columns in buses['configuration_buses'].items():
|
|
for column, frames in columns[
|
|
'configuration_columns'].items():
|
|
address = self.get_baseaddress(
|
|
clock_region, bus, int(row), int(column))
|
|
assert address not in self.tile_address_to_frames
|
|
self.tile_address_to_frames[address] = frames[
|
|
'frame_count']
|
|
|
|
def get_tile_frames(self, baseaddress):
|
|
if len(self.tile_address_to_frames) == 0:
|
|
self.initialize_address_to_frames()
|
|
assert baseaddress in self.tile_address_to_frames, "Base address not found in the part's json file"
|
|
return self.tile_address_to_frames[baseaddress]
|
|
|
|
|
|
def get_entry(tile_type, block_type):
|
|
""" Get frames and words for a given tile_type (e.g. CLBLL) and block_type (CLB_IO_CLK, BLOCK_RAM, etc). """
|
|
return {
|
|
# (tile_type, block_type): (frames, words, height)
|
|
("CLBLL", "CLB_IO_CLK"): (36, 2, None),
|
|
("CLBLM", "CLB_IO_CLK"): (36, 2, None),
|
|
("HCLK", "CLB_IO_CLK"): (26, 1, None),
|
|
("INT", "CLB_IO_CLK"): (28, 2, None),
|
|
("BRAM", "CLB_IO_CLK"): (28, 10, None),
|
|
("BRAM", "BLOCK_RAM"): (128, 10, None),
|
|
("DSP", "CLB_IO_CLK"): (28, 2, None),
|
|
}.get((tile_type, block_type), None)
|
|
|
|
|
|
def get_int_params():
|
|
int_frames, int_words, _ = get_entry('INT', 'CLB_IO_CLK')
|
|
return int_frames, int_words
|
|
|
|
|
|
def add_tile_bits(
|
|
tile_name,
|
|
tile_db,
|
|
baseaddr,
|
|
offset,
|
|
frames,
|
|
words,
|
|
tile_frames,
|
|
verbose=False):
|
|
'''
|
|
Record data structure geometry for the given tile baseaddr
|
|
For most tiles there is only one baseaddr, but some like BRAM have multiple
|
|
Notes on multiple block types:
|
|
https://github.com/SymbiFlow/prjxray/issues/145
|
|
'''
|
|
bits = tile_db['bits']
|
|
block_type = util.addr2btype(baseaddr)
|
|
|
|
# Extract the information about the maximal number of frames from the part's json
|
|
max_frames = tile_frames.get_tile_frames(baseaddr)
|
|
if frames > max_frames:
|
|
print(
|
|
"Warning: The number of frames for base address {} specified for the tile {} ({}) exceeds the maximum allowed value ({}). Falling back to the maximum value."
|
|
.format(hex(baseaddr), tile_name, frames, max_frames))
|
|
frames = max_frames
|
|
# If frames count is None then use the maximum
|
|
if frames is None:
|
|
frames = max_frames
|
|
|
|
assert offset <= 100, (tile_name, offset)
|
|
# Few rare cases at X=0 for double width tiles split in half => small negative offset
|
|
assert offset >= 0 or "IOB" in tile_name or "GTX_INT_INTERFACE" in tile_name, (
|
|
tile_name, hex(baseaddr), offset)
|
|
assert 1 <= words <= 101, words
|
|
assert offset + words <= 101, (
|
|
tile_name, offset + words, offset, words, block_type)
|
|
|
|
baseaddr_str = '0x%08X' % baseaddr
|
|
block = bits.get(block_type, None)
|
|
if block is not None:
|
|
verbose and print(
|
|
"%s: existing defintion for %s" % (tile_name, block_type))
|
|
assert block["baseaddr"] == baseaddr_str
|
|
assert block["frames"] == frames, (block, frames)
|
|
assert block["offset"] == offset, "%s; orig offset %s, new %s" % (
|
|
tile_name, block["offset"], offset)
|
|
assert block["words"] == words
|
|
return
|
|
block = bits.setdefault(block_type, {})
|
|
|
|
# FDRI address
|
|
block["baseaddr"] = baseaddr_str
|
|
# Number of frames this entry is sretched across
|
|
# that is the following FDRI addresses are used: range(baseaddr, baseaddr + frames)
|
|
block["frames"] = frames
|
|
|
|
# Index of first word used within each frame
|
|
block["offset"] = offset
|
|
|
|
# Number of words used by tile.
|
|
block["words"] = words
|