def add_tile_bits(tile_db, baseaddr, offset, frames, words, height=None): ''' 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) assert 0 <= offset <= 100, offset assert 1 <= words <= 101 assert offset + words <= 101, ( tile_db, offset + words, offset, words, block_type) assert block_type not in bits block = bits.setdefault(block_type, {}) # FDRI address block["baseaddr"] = '0x%08X' % baseaddr # 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 # related to words... # deprecated field? Don't worry about for now # DSP has some differences between height and words block["words"] = words if height is None: height = words block["height"] = height
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 specified for the tile {} ({}) exceeds the maximum allowed value ({}). Falling back to the maximum value." .format(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, (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
def make_tile_baseaddrs(tiles, site_baseaddr, verbose=False): # Look up a base address by tile name tile_baseaddrs = dict() verbose and print('') verbose and print('%u tiles' % len(tiles)) verbose and print("%u baseaddrs" % len(site_baseaddr)) added = 0 for tile in tiles: for site_name in tile["sites"].keys(): if site_name not in site_baseaddr: continue framebaseaddr = site_baseaddr[site_name] bt = util.addr2btype(framebaseaddr) tile_baseaddr = tile_baseaddrs.setdefault(tile["name"], {}) if bt in tile_baseaddr: # actually lets just fail these, better to remove at tcl level to speed up processing assert 0, 'duplicate base address' assert tile_baseaddr[bt] == [framebaseaddr, 0] else: tile_baseaddr[bt] = [framebaseaddr, 0] verbose and print( "baseaddr: %s.%s @ %s.0x%08x" % (tile["name"], site_name, bt, framebaseaddr)) added += 1 assert added, "Failed to add any base addresses" assert added == len(site_baseaddr) return tile_baseaddrs
def run(fn_in, fn_out, verbose=False): database = json.load(open(fn_in, "r")) # Load a map of sites to base addresses # Need to figure out the # FIXME: generate frames from part file (or equivilent) # See https://github.com/SymbiFlow/prjxray/issues/327 # FIXME: generate words from pitch tdb_fns = [ ("iob/build/segbits_tilegrid.tdb", 42, 4), # FIXME: height ("mmcm/build/segbits_tilegrid.tdb", 30, 101), # FIXME: height ("pll/build/segbits_tilegrid.tdb", 30, 101), ] for (tdb_fn, frames, words) in tdb_fns: for (tile, frame, wordidx) in load_db(tdb_fn): tilej = database[tile] bitsj = tilej['bits'] bt = util.addr2btype(frame) verbose and print("Add %s %08X_%03u" % (tile, frame, wordidx)) add_tile_bits(tilej, frame, wordidx, frames, words) # Save json.dump(database, open(fn_out, "w"), sort_keys=True, indent=4, separators=(",", ": "))