2019-01-11 12:39:54 +01:00
#!/usr/bin/env python3
2020-04-16 10:06:01 +02:00
# -*- 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
2019-01-11 12:39:54 +01:00
from prjxray import util
2021-03-04 12:43:00 +01:00
import os
import json
2019-01-11 12:39:54 +01:00
'''
Local utils script to hold shared code of the 005 - tilegrid fuzzer scripts
'''
2019-01-28 20:32:16 +01:00
2021-03-04 12:43:00 +01:00
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 ]
2019-01-14 12:56:46 +01:00
def get_entry ( tile_type , block_type ) :
2019-01-28 20:31:44 +01:00
""" Get frames and words for a given tile_type (e.g. CLBLL) and block_type (CLB_IO_CLK, BLOCK_RAM, etc). """
2019-01-14 12:56:46 +01:00
return {
# (tile_type, block_type): (frames, words, height)
2019-01-28 20:31:44 +01:00
( " 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 ) ,
2019-01-14 12:56:46 +01:00
( " BRAM " , " CLB_IO_CLK " ) : ( 28 , 10 , None ) ,
( " BRAM " , " BLOCK_RAM " ) : ( 128 , 10 , None ) ,
2019-01-28 20:31:44 +01:00
( " DSP " , " CLB_IO_CLK " ) : ( 28 , 2 , None ) ,
2019-01-14 12:56:46 +01:00
} . get ( ( tile_type , block_type ) , None )
2019-01-11 12:51:42 +01:00
2019-01-28 20:31:44 +01:00
def get_int_params ( ) :
int_frames , int_words , _ = get_entry ( ' INT ' , ' CLB_IO_CLK ' )
return int_frames , int_words
2019-01-11 12:39:54 +01:00
def add_tile_bits (
2021-03-04 12:43:00 +01:00
tile_name ,
tile_db ,
baseaddr ,
offset ,
frames ,
words ,
tile_frames ,
verbose = False ) :
2019-01-11 12:39:54 +01:00
'''
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 )
2021-03-04 12:43:00 +01:00
# 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 (
2022-11-08 11:31:50 +01:00
" 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 ) )
2021-03-04 12:43:00 +01:00
frames = max_frames
# If frames count is None then use the maximum
if frames is None :
frames = max_frames
2019-01-11 12:39:54 +01:00
assert offset < = 100 , ( tile_name , offset )
# Few rare cases at X=0 for double width tiles split in half => small negative offset
2019-01-26 05:07:39 +01:00
assert offset > = 0 or " IOB " in tile_name , (
tile_name , hex ( baseaddr ) , offset )
2019-01-25 19:37:23 +01:00
assert 1 < = words < = 101 , words
2019-01-11 12:39:54 +01:00
assert offset + words < = 101 , (
tile_name , offset + words , offset , words , block_type )
2022-06-07 04:25:33 +02:00
is_xc7k480t = ' xc7k480t ' in os . environ [ ' XRAY_PART ' ]
2019-01-11 12:39:54 +01:00
baseaddr_str = ' 0x %08X ' % baseaddr
block = bits . get ( block_type , None )
if block is not None :
2022-06-07 04:25:33 +02:00
done = True
2019-01-11 12:39:54 +01:00
verbose and print (
" %s : existing defintion for %s " % ( tile_name , block_type ) )
assert block [ " baseaddr " ] == baseaddr_str
2019-01-25 19:37:23 +01:00
assert block [ " frames " ] == frames , ( block , frames )
2022-06-07 04:25:33 +02:00
# TODO: HACK: some of the offsets of the K480T seem to be messed up
# using the maximum offset below seems to make most sense when looking
# at the preceding blocks
if is_xc7k480t :
if not block [ " offset " ] == offset :
print ( " XXX Hack: %s ; orig offset %s , new %s " % ( tile_name , block [ " offset " ] , offset ) )
offset = max ( block [ ' offset ' ] , offset )
print ( " XXX Hack: using offset {offset} " )
done = False
else :
assert block [ " offset " ] == offset , " %s ; orig offset %s , new %s " % (
- tile_name , block [ " offset " ] , offset )
2019-01-11 12:39:54 +01:00
assert block [ " words " ] == words
2022-06-07 04:25:33 +02:00
if done : return
2019-01-11 12:39:54 +01:00
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
2019-01-28 20:31:44 +01:00
# Number of words used by tile.
2019-01-11 12:39:54 +01:00
block [ " words " ] = words