mirror of https://github.com/openXC7/prjxray.git
iob-pips: initial attempt to document ioi pips
Signed-off-by: Alessandro Comodi <acomodi@antmicro.com>
This commit is contained in:
parent
b6b8dc19cd
commit
e26a6432a4
|
|
@ -0,0 +1,48 @@
|
|||
export FUZDIR=$(shell pwd)
|
||||
PIP_TYPE?=ioi3
|
||||
PIPLIST_TCL=$(FUZDIR)/ioi3_pip_list.tcl
|
||||
|
||||
TODO_RE="[LR]IOI3\.(IOI_([IO]LOGIC[01]_CLK(DIV|B)?)|(IOI_OCLK_[01]))\.IOI_LEAF_GCLK[0-9]"
|
||||
|
||||
MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE)
|
||||
N = 40
|
||||
|
||||
SEGMATCH_FLAGS=-c 2 -m 15 -M 30
|
||||
SPECIMENS_DEPS=build/cmt_regions.csv
|
||||
|
||||
include ../pip_loop.mk
|
||||
|
||||
build/segbits_ioi3_x.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_ioi3_x.rdb \
|
||||
$(shell find build -name segdata_lioi3*.txt) $(shell find build -name segdata_rioi3*.txt)
|
||||
|
||||
RDBS = build/segbits_ioi3_x.rdb
|
||||
|
||||
database: ${RDBS}
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
|
||||
--seg-fn-in build/segbits_ioi3_x.rdb \
|
||||
--seg-fn-out build/segbits_ioi3_x.db
|
||||
|
||||
# Keep a copy to track iter progress
|
||||
cp build/segbits_ioi3_x.rdb build/$(ITER)/segbits_ioi3_x.rdb
|
||||
cp build/segbits_ioi3_x.db build/$(ITER)/segbits_ioi3_x.db
|
||||
|
||||
|
||||
${XRAY_MASKMERGE} build/mask_xioi3.db \
|
||||
$(shell find build -name segdata_ioi3_l.txt) \
|
||||
$(shell find build -name segdata_ioi3_r.txt)
|
||||
|
||||
# Clobber existing .db to eliminate potential conflicts
|
||||
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
|
||||
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} ioi3_l build/segbits_ioi3_x.db
|
||||
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} ioi3_r build/segbits_ioi3_x.db
|
||||
|
||||
build/cmt_regions.csv: output_cmt.tcl
|
||||
mkdir -p build
|
||||
cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl
|
||||
|
||||
pushdb:
|
||||
${XRAY_MERGEDB} lioi3 build/segbits_ioi3_x.db
|
||||
${XRAY_MERGEDB} rioi3 build/segbits_ioi3_x.db
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from prjxray.segmaker import Segmaker
|
||||
import os, re
|
||||
import os.path
|
||||
|
||||
|
||||
def bitfilter(frame, word):
|
||||
if frame < 26:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
segmk = Segmaker("design.bits")
|
||||
|
||||
tiledata = {}
|
||||
pipdata = {}
|
||||
ignpip = set()
|
||||
|
||||
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
|
||||
'ioi3', 'ioi3_l.txt')) as f:
|
||||
for l in f:
|
||||
tile_type, dst, src = l.strip().split('.')
|
||||
if tile_type not in pipdata:
|
||||
pipdata[tile_type] = []
|
||||
|
||||
pipdata[tile_type].append((src, dst))
|
||||
|
||||
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
|
||||
'ioi3', 'ioi3_r.txt')) as f:
|
||||
for l in f:
|
||||
tile_type, dst, src = l.strip().split('.')
|
||||
if tile_type not in pipdata:
|
||||
pipdata[tile_type] = []
|
||||
|
||||
pipdata[tile_type].append((src, dst))
|
||||
|
||||
print("Loading tags from design.txt.")
|
||||
with open("design.txt", "r") as f:
|
||||
for line in f:
|
||||
tile, pip, src, dst, pnum, pdir = line.split()
|
||||
if not tile.startswith('LIOI3') and not tile.startswith('RIOI3'):
|
||||
continue
|
||||
|
||||
log = open("log.txt", "a")
|
||||
print(line, file=log)
|
||||
pip_prefix, _ = pip.split(".")
|
||||
tile_from_pip, tile_type = pip_prefix.split('/')
|
||||
|
||||
_, src = src.split("/")
|
||||
_, dst = dst.split("/")
|
||||
pnum = int(pnum)
|
||||
pdir = int(pdir)
|
||||
|
||||
if tile not in tiledata:
|
||||
tiledata[tile] = {
|
||||
"type": tile_type,
|
||||
"pips": set(),
|
||||
"srcs": set(),
|
||||
"dsts": set(),
|
||||
}
|
||||
|
||||
tiledata[tile]["pips"].add((src, dst))
|
||||
tiledata[tile]["srcs"].add(src)
|
||||
tiledata[tile]["dsts"].add(dst)
|
||||
|
||||
if pdir == 0:
|
||||
tiledata[tile]["srcs"].add(dst)
|
||||
tiledata[tile]["dsts"].add(src)
|
||||
|
||||
if pnum == 1 or pdir == 0:
|
||||
print("Ignoring pip: {}".format(pip), file=log)
|
||||
ignpip.add((src, dst))
|
||||
|
||||
for tile, pips_srcs_dsts in tiledata.items():
|
||||
tile_type = pips_srcs_dsts["type"]
|
||||
|
||||
if tile_type.startswith('LIOI3'):
|
||||
tile_type = 'LIOI3'
|
||||
elif tile_type.startswith('RIOI3'):
|
||||
tile_type = 'RIOI3'
|
||||
|
||||
pips = pips_srcs_dsts["pips"]
|
||||
|
||||
for src, dst in pipdata[tile_type]:
|
||||
if (src, dst) in ignpip:
|
||||
pass
|
||||
if re.match(r'.*PHASER.*', src) or re.match(r'.*CLKDIV[PFB].*',
|
||||
dst):
|
||||
pass
|
||||
elif (src, dst) in tiledata[tile]["pips"]:
|
||||
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
|
||||
elif (src, dst) not in tiledata[tile]["pips"]:
|
||||
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
|
||||
|
||||
internal_feedback = False
|
||||
|
||||
segmk.compile(bitfilter=bitfilter)
|
||||
segmk.write()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
source "$::env(XRAY_DIR)/utils/utils.tcl"
|
||||
|
||||
proc write_pip_txtdata {filename} {
|
||||
puts "FUZ([pwd]): Writing $filename."
|
||||
set fp [open $filename w]
|
||||
set nets [get_nets -hierarchical]
|
||||
set nnets [llength $nets]
|
||||
set neti 0
|
||||
foreach net $nets {
|
||||
incr neti
|
||||
if {($neti % 100) == 0 } {
|
||||
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
|
||||
}
|
||||
foreach pip [get_pips -of_objects $net] {
|
||||
set tile [get_tiles -of_objects $pip]
|
||||
set src_wire [get_wires -uphill -of_objects $pip]
|
||||
set dst_wire [get_wires -downhill -of_objects $pip]
|
||||
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
|
||||
set dir_prop [get_property IS_DIRECTIONAL $pip]
|
||||
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
|
||||
}
|
||||
}
|
||||
close $fp
|
||||
}
|
||||
|
||||
proc load_todo {} {
|
||||
set fp [open "../todo.txt" r]
|
||||
|
||||
# Create map of pip source to remaining destinations for that pip
|
||||
set todo_map [dict create]
|
||||
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||
set parts [split $line .]
|
||||
dict lappend todo_map [lindex $parts 1] [list [lindex $parts 0] [lindex $parts 2]]
|
||||
}
|
||||
close $fp
|
||||
return $todo_map
|
||||
}
|
||||
|
||||
proc route_todo {} {
|
||||
puts "Checking TODO's"
|
||||
set todo_map [load_todo]
|
||||
|
||||
puts $todo_map
|
||||
|
||||
set nets [get_nets]
|
||||
|
||||
set todo_nets [dict create]
|
||||
set used_sources [dict create]
|
||||
|
||||
foreach net $nets {
|
||||
# Check to see if this net is one we are interested in
|
||||
set wires [get_wires -of_objects $net -filter {TILE_NAME =~ *IOI3*}]
|
||||
set is_gclk_net 0
|
||||
foreach wire $wires {
|
||||
if [regexp "IOI_\[IO\]LOGIC\[01\]_CLKB?" $wire] {
|
||||
set is_gclk_net 1
|
||||
break
|
||||
}
|
||||
if [regexp "IOI_OCLK_\[01\]" $wire] {
|
||||
set is_gclk_net 1
|
||||
break
|
||||
}
|
||||
if [regexp "IOI_\[IO\]LOGIC\[01\]_CLKDIV" $wire] {
|
||||
set is_gclk_net 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if {$is_gclk_net == 0} {
|
||||
puts "$net not going to a IOI3 port, skipping."
|
||||
continue
|
||||
}
|
||||
|
||||
foreach wire $wires {
|
||||
set tile [lindex [split $wire /] 0]
|
||||
set wire [lindex [split $wire /] 1]
|
||||
set tile_type [get_property TILE_TYPE [get_tiles $tile]]
|
||||
|
||||
if { ![dict exists $todo_map $wire] } {
|
||||
continue
|
||||
}
|
||||
|
||||
set srcs [dict get $todo_map $wire]
|
||||
|
||||
# This net is interesting, see if it is already going somewhere we
|
||||
# want.
|
||||
set found_target 0
|
||||
foreach other_wire $wires {
|
||||
if { $found_target == 1 } {
|
||||
break
|
||||
}
|
||||
|
||||
set other_wire [lindex [split $other_wire /] 1]
|
||||
|
||||
if { $wire == $other_wire } {
|
||||
continue
|
||||
}
|
||||
|
||||
foreach src $srcs {
|
||||
set src_tile_type [lindex $src 0]
|
||||
|
||||
if {$src_tile_type != $tile_type} {
|
||||
continue
|
||||
}
|
||||
|
||||
set src_wire [lindex $src 1]
|
||||
|
||||
if { $other_wire == $src } {
|
||||
set found_target 1
|
||||
puts "Interesting net $net already going from $wire to $other_wire."
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if { $found_target == 1 } {
|
||||
# Net has an interesting
|
||||
continue
|
||||
}
|
||||
|
||||
dict set todo_nets $net [list $tile $wire]
|
||||
puts "Interesting net $net (including $wire) is being rerouted."
|
||||
}
|
||||
}
|
||||
|
||||
dict for {net tile_wire} $todo_nets {
|
||||
set tile [lindex $tile_wire 0]
|
||||
set wire [lindex $tile_wire 1]
|
||||
set srcs [dict get $todo_map $wire]
|
||||
set site [lindex [get_sites -of_objects [get_tiles $tile]] 0]
|
||||
set region [get_clock_regions -of_objects [get_sites $site]]
|
||||
|
||||
puts "Rerouting net $net at $tile / $wire (type $tile_type)"
|
||||
|
||||
set tile_type [get_property TILE_TYPE [get_tiles $tile]]
|
||||
|
||||
set todos {}
|
||||
foreach src $srcs {
|
||||
set src_tile_type [lindex $src 0]
|
||||
if {$src_tile_type != $tile_type} {
|
||||
continue
|
||||
}
|
||||
|
||||
set src_wire [lindex $src 1]
|
||||
|
||||
set is_gclk_net 0
|
||||
if [regexp "IOI_LEAF_GCLK\[0-9\]+" $src_wire] {
|
||||
set is_gclk_net 1
|
||||
}
|
||||
|
||||
if {$is_gclk_net == 0} {
|
||||
continue
|
||||
}
|
||||
|
||||
lappend todos $src_wire
|
||||
}
|
||||
|
||||
puts "All todos for $tile_type / $wire"
|
||||
foreach src_wire $todos {
|
||||
puts " - $src_wire"
|
||||
}
|
||||
|
||||
route_design -unroute -nets $net
|
||||
|
||||
# Find an input in the todo list that this can can drive.
|
||||
foreach src_wire $todos {
|
||||
puts "Attempting to route to $src_wire for net $net."
|
||||
set target_wire [get_wires "$tile/$src_wire"]
|
||||
set target_node [get_nodes -of_objects $target_wire]
|
||||
|
||||
if {[llength $target_node] == 0} {
|
||||
error "Failed to find node for $tile/$src_wire."
|
||||
}
|
||||
|
||||
if { [regexp ".*TOP.*" $target_node match group] } {
|
||||
set loc TOP
|
||||
} elseif { [regexp ".*BOT.*" $target_node match group] } {
|
||||
set loc BOT
|
||||
}
|
||||
|
||||
if { [dict exists $used_sources "$region/$loc/$src_wire"] } {
|
||||
puts "Not routing to $tile / $src_wire, in use."
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
set old_nets [get_nets -of_objects $target_node]
|
||||
|
||||
if { $old_nets != {} } {
|
||||
set old_nets_property [get_property IS_ROUTE_FIXED [get_nets -of_objects $target_node]]
|
||||
if { $old_nets_property == 0 } {
|
||||
route_design -unroute -nets $old_nets
|
||||
}
|
||||
}
|
||||
|
||||
set origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
|
||||
set new_route [find_routing_path -to $target_node -from $origin_node]
|
||||
puts "Origin node: $origin_node"
|
||||
puts "Target wire: $target_wire"
|
||||
puts "Target node: $target_node"
|
||||
|
||||
# Only need to set route to one of the destinations.
|
||||
# Router will handle the rest.
|
||||
set_property FIXED_ROUTE $new_route $net
|
||||
|
||||
dict set used_sources "$region/$loc/$src_wire" 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc run {} {
|
||||
create_project -force -part $::env(XRAY_PART) design design
|
||||
read_verilog top.v
|
||||
synth_design -top top
|
||||
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-25}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-39}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-4}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-5}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-98}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-99}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-123}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-144}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-1576}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-74}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-81}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {DRC INBB-1}]
|
||||
|
||||
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
|
||||
|
||||
place_design
|
||||
route_design
|
||||
write_checkpoint -force design_before.dcp
|
||||
|
||||
route_todo
|
||||
route_design
|
||||
write_checkpoint -force design_after.dcp
|
||||
|
||||
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
|
||||
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
|
||||
|
||||
write_bitstream -force design.bit
|
||||
write_pip_txtdata design.txt
|
||||
}
|
||||
|
||||
run
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
proc print_tile_pips {tile_type filename} {
|
||||
set fp [open $filename w]
|
||||
set pips [dict create]
|
||||
foreach tile [get_tiles -filter "TYPE == $tile_type"] {
|
||||
puts "Dumping PIPs for tile $tile ($tile_type) to $filename."
|
||||
foreach pip [lsort [get_pips -of_objects $tile]] {
|
||||
set src [get_wires -uphill -of_objects $pip]
|
||||
set dst [get_wires -downhill -of_objects $pip]
|
||||
|
||||
# Skip pips with disconnected nodes
|
||||
set src_node [get_nodes -of_objects $src]
|
||||
|
||||
if { $src_node == {} } {
|
||||
continue
|
||||
}
|
||||
|
||||
set dst_node [get_nodes -of_objects $src]
|
||||
if { $dst_node == {} } {
|
||||
continue
|
||||
}
|
||||
|
||||
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} {
|
||||
set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
|
||||
if ![dict exists $pips $pip_string] {
|
||||
puts $fp $pip_string
|
||||
dict set pips $pip_string 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close $fp
|
||||
}
|
||||
|
||||
create_project -force -part $::env(XRAY_PART) design design
|
||||
set_property design_mode PinPlanning [current_fileset]
|
||||
open_io_design -name io_1
|
||||
|
||||
# Cleaning ioi3.txt pip file
|
||||
set fp [open ioi3.txt w]
|
||||
close $fp
|
||||
|
||||
print_tile_pips LIOI3 ioi3_l.txt
|
||||
print_tile_pips RIOI3 ioi3_r.txt
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
create_project -force -part $::env(XRAY_PART) design design
|
||||
set_property design_mode PinPlanning [current_fileset]
|
||||
open_io_design -name io_1
|
||||
|
||||
set fp [open "cmt_regions.csv" "w"]
|
||||
foreach site_type {MMCME2_ADV BUFHCE BUFR BUFMRCE BUFIO ILOGICE3 OLOGICE3 IDELAYE2 IDELAYCTRL PLLE2_ADV} {
|
||||
foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
|
||||
puts $fp "$site,[get_property CLOCK_REGION $site]"
|
||||
}
|
||||
}
|
||||
close $fp
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
import json
|
||||
import io
|
||||
import os
|
||||
import random
|
||||
import math
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray import lut_maker
|
||||
from prjxray import verilog
|
||||
from prjxray.db import Database
|
||||
|
||||
NOT_INCLUDED_TILES = ['LIOI3_SING', 'RIOI3_SING']
|
||||
|
||||
SITE_TYPES = ['OLOGICE3', 'ILOGICE3']
|
||||
|
||||
REGIONAL_CLOCK_BUFFERS = ['BUFHCE', 'BUFIO']
|
||||
GLOBAL_CLOCK_BUFFERS = ['BUFGCTRL']
|
||||
CLOCK_BUFFERS = REGIONAL_CLOCK_BUFFERS + GLOBAL_CLOCK_BUFFERS
|
||||
|
||||
MAX_REG_CLK_BUF = 2
|
||||
MAX_GLB_CLK_BUF = 24
|
||||
CUR_CLK = 0
|
||||
MAX_ATTEMPTS = 50
|
||||
|
||||
|
||||
def get_location(tile_name, divisor):
|
||||
y_location = int(tile_name.split("Y")[-1])
|
||||
|
||||
if math.floor(y_location / divisor) % 2 == 0:
|
||||
# Location is on the bottom of the row/tile
|
||||
return "BOT"
|
||||
else:
|
||||
return "TOP"
|
||||
|
||||
|
||||
def read_site_to_cmt():
|
||||
""" Yields clock sources and which CMT they route within. """
|
||||
with open(os.path.join(os.getenv('FUZDIR'), 'build',
|
||||
'cmt_regions.csv')) as f:
|
||||
for l in f:
|
||||
site, cmt = l.strip().split(',')
|
||||
yield (site, cmt)
|
||||
|
||||
|
||||
def gen_sites(site_types):
|
||||
'''
|
||||
Generates all sites belonging to `site_types` of
|
||||
a desired `tile`
|
||||
'''
|
||||
db = Database(util.get_db_root())
|
||||
grid = db.grid()
|
||||
|
||||
tiles = grid.tiles()
|
||||
|
||||
#Randomize tiles
|
||||
tiles_list = list(tiles)
|
||||
random.shuffle(tiles_list)
|
||||
|
||||
for tile_name in tiles:
|
||||
loc = grid.loc_of_tilename(tile_name)
|
||||
gridinfo = grid.gridinfo_at_loc(loc)
|
||||
tile_type = gridinfo.tile_type
|
||||
|
||||
for site_name, site_type in gridinfo.sites.items():
|
||||
if site_type in site_types:
|
||||
yield tile_type, tile_name, site_type, site_name
|
||||
|
||||
|
||||
def generate_mmcm(site_to_cmt, clock_region):
|
||||
mmcm_clocks = None
|
||||
|
||||
for _, _, _, site in gen_sites('MMCME2_ADV'):
|
||||
mmcm_region = site_to_cmt[site]
|
||||
|
||||
if mmcm_region == clock_region:
|
||||
mmcm_clocks = [
|
||||
'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx)
|
||||
for idx in range(3)
|
||||
]
|
||||
|
||||
print(
|
||||
"""
|
||||
wire {c0}, {c1}, {c2};
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
MMCME2_ADV mmcm_{site} (
|
||||
.CLKOUT0({c0}),
|
||||
.CLKOUT1({c1}),
|
||||
.CLKOUT2({c2})
|
||||
);""".format(
|
||||
site=site,
|
||||
c0=mmcm_clocks[0],
|
||||
c1=mmcm_clocks[1],
|
||||
c2=mmcm_clocks[2]))
|
||||
|
||||
if not mmcm_clocks:
|
||||
return None
|
||||
|
||||
return mmcm_clocks
|
||||
|
||||
|
||||
def generate_glb_clk_buf(clock_regions, mmcm_clocks_dict):
|
||||
clk_buf_count = 0
|
||||
|
||||
clock_signals = []
|
||||
|
||||
for tile_type, _, site_type, site_name in gen_sites(GLOBAL_CLOCK_BUFFERS):
|
||||
|
||||
if clk_buf_count >= MAX_GLB_CLK_BUF:
|
||||
break
|
||||
|
||||
clock_signal = "buf_clk_{site}".format(site=site_name)
|
||||
|
||||
if site_type == 'BUFGCTRL':
|
||||
mmcm_clocks = []
|
||||
|
||||
for clock_region in clock_regions:
|
||||
# BUFGCTRL must have the clock coming from the same fabric row
|
||||
if ('Y0' in clock_region and tile_type == 'CLK_BUFG_BOT_R'
|
||||
) or ('Y0' not in clock_region
|
||||
and tile_type == 'CLK_BUFG_TOP_R'):
|
||||
mmcm_clocks = mmcm_clocks_dict[clock_region]
|
||||
break
|
||||
|
||||
assert mmcm_clocks, "No clock can be produced. Buffer not instantiated"
|
||||
|
||||
print(
|
||||
'''
|
||||
wire {clk_out};
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
BUFG buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
|
||||
clk_in=random.choice(mmcm_clocks),
|
||||
clk_out=clock_signal,
|
||||
site=site_name))
|
||||
|
||||
else:
|
||||
assert False, "The site is somehow corrupted"
|
||||
|
||||
clk_buf_count += 1
|
||||
|
||||
clock_signals.append(clock_signal)
|
||||
|
||||
return clock_signals
|
||||
|
||||
|
||||
def generate_reg_clk_buf(site_to_cmt, clock_region, mmcm_clocks, buf_type):
|
||||
clk_buf_count = 0
|
||||
clock_signals = []
|
||||
|
||||
for tile_type, _, site_type, site_name in gen_sites(
|
||||
REGIONAL_CLOCK_BUFFERS):
|
||||
buf_region = site_to_cmt[site_name]
|
||||
|
||||
if clk_buf_count >= MAX_REG_CLK_BUF:
|
||||
break
|
||||
|
||||
if buf_type != site_type:
|
||||
continue
|
||||
|
||||
if buf_region != clock_region:
|
||||
continue
|
||||
|
||||
clock_signal = "buf_clk_{site}".format(site=site_name)
|
||||
|
||||
if site_type == 'BUFR':
|
||||
print(
|
||||
'''
|
||||
wire {clk_out};
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
BUFR buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
|
||||
clk_in=random.choice(mmcm_clocks),
|
||||
clk_out=clock_signal,
|
||||
site=site_name))
|
||||
|
||||
elif site_type == 'BUFIO':
|
||||
print(
|
||||
'''
|
||||
wire {clk_out};
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
BUFIO buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
|
||||
clk_in=random.choice(mmcm_clocks),
|
||||
clk_out=clock_signal,
|
||||
site=site_name))
|
||||
|
||||
elif site_type == 'BUFHCE':
|
||||
print(
|
||||
'''
|
||||
wire {clk_out};
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
BUFH buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
|
||||
clk_in=random.choice(mmcm_clocks),
|
||||
clk_out=clock_signal,
|
||||
site=site_name))
|
||||
|
||||
else:
|
||||
assert False, "The site is somehow corrupted"
|
||||
|
||||
clk_buf_count += 1
|
||||
|
||||
clock_signals.append(clock_signal)
|
||||
|
||||
return clock_signals
|
||||
|
||||
|
||||
def get_clock_signal(clock_signals, clock_types):
|
||||
'''
|
||||
Get a unique clock signals for a specific tile.
|
||||
'''
|
||||
global CUR_CLK
|
||||
|
||||
clock_signal_string = ''
|
||||
is_first_clock = True
|
||||
|
||||
for clock_type in clock_types:
|
||||
if random.choice([True, True, False]):
|
||||
continue
|
||||
|
||||
clock_signal = clock_signals[CUR_CLK]
|
||||
if is_first_clock:
|
||||
clock_signal_string += '''
|
||||
.{}({})'''.format(clock_type, clock_signal)
|
||||
else:
|
||||
clock_signal_string += ''',
|
||||
.{}({})'''.format(clock_type, clock_signal)
|
||||
|
||||
is_first_clock = False
|
||||
|
||||
CUR_CLK = (CUR_CLK + 1) % MAX_GLB_CLK_BUF
|
||||
|
||||
return clock_signal_string
|
||||
|
||||
|
||||
def run():
|
||||
|
||||
global CUR_CLK
|
||||
# One buffer type for each specimen
|
||||
buf_type = random.choice(GLOBAL_CLOCK_BUFFERS)
|
||||
|
||||
site_location = random.choice(['TOP', 'BOT'])
|
||||
|
||||
site_to_cmt = dict(read_site_to_cmt())
|
||||
clock_regions = list(dict.fromkeys(site_to_cmt.values()))
|
||||
|
||||
print("module top();")
|
||||
|
||||
clock_mmcm_dict = {}
|
||||
clock_signals_dict = {}
|
||||
site_types_dict = {}
|
||||
|
||||
# Generate MMCM Clock generator
|
||||
for clock_region in clock_regions:
|
||||
mmcm_clocks = generate_mmcm(site_to_cmt, clock_region)
|
||||
|
||||
if mmcm_clocks:
|
||||
clock_mmcm_dict[clock_region] = mmcm_clocks
|
||||
clock_signals_dict[clock_region] = []
|
||||
|
||||
if buf_type in REGIONAL_CLOCK_BUFFERS:
|
||||
clock_signals_dict[clock_region] = generate_reg_clk_buf(
|
||||
site_to_cmt, clock_region, mmcm_clocks, buf_type)
|
||||
else:
|
||||
clock_regions.remove(clock_region)
|
||||
|
||||
if buf_type in GLOBAL_CLOCK_BUFFERS:
|
||||
clock_signals = generate_glb_clk_buf(clock_regions, clock_mmcm_dict)
|
||||
|
||||
for clock_region in clock_regions:
|
||||
clock_signals_dict[clock_region] = clock_signals
|
||||
site_types_dict[clock_region] = random.choice(SITE_TYPES)
|
||||
|
||||
half_column_used_clocks = {}
|
||||
|
||||
for tile_type, tile_name, site_type, site_name in gen_sites(SITE_TYPES):
|
||||
if tile_type in NOT_INCLUDED_TILES:
|
||||
continue
|
||||
|
||||
if random.choice([True, True, False]):
|
||||
continue
|
||||
|
||||
site_region = site_to_cmt[site_name]
|
||||
|
||||
if site_type != site_types_dict[site_region]:
|
||||
continue
|
||||
|
||||
clock_signals = clock_signals_dict[site_region]
|
||||
|
||||
bot_or_top = get_location(site_name, 1)
|
||||
|
||||
half_column = '{}_{}'.format(site_region, get_location(tile_name, 25))
|
||||
|
||||
if half_column not in half_column_used_clocks:
|
||||
half_column_used_clocks[half_column] = {
|
||||
'TOP': {
|
||||
'ILOGIC':
|
||||
get_clock_signal(clock_signals, ['CLK', 'CLKB', 'CLKDIV']),
|
||||
'OLOGIC':
|
||||
get_clock_signal(clock_signals, ['CLK', 'CLKDIV'])
|
||||
},
|
||||
'BOT': {
|
||||
'ILOGIC':
|
||||
get_clock_signal(clock_signals, ['CLK', 'CLKB', 'CLKDIV']),
|
||||
'OLOGIC':
|
||||
get_clock_signal(clock_signals, ['CLK', 'CLKDIV'])
|
||||
}
|
||||
}
|
||||
|
||||
if site_type == 'ILOGICE3':
|
||||
print(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site_name}" *)
|
||||
ISERDESE2 #(
|
||||
.DATA_RATE("SDR")
|
||||
) iserdes_{site_name} ({clk});'''.format(
|
||||
site_name=site_name,
|
||||
clk=half_column_used_clocks[half_column][bot_or_top]
|
||||
['ILOGIC']))
|
||||
elif site_type == 'OLOGICE3':
|
||||
print(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site_name}" *)
|
||||
OSERDESE2 #(
|
||||
.DATA_RATE_OQ("SDR"),
|
||||
.DATA_RATE_TQ("SDR")
|
||||
) oserdes_{site_name} ({clk});'''.format(
|
||||
site_name=site_name,
|
||||
clk=half_column_used_clocks[half_column][bot_or_top]
|
||||
['OLOGIC']))
|
||||
|
||||
print("endmodule")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
|
@ -88,6 +88,7 @@ $(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid))
|
|||
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid))
|
||||
$(eval $(call fuzzer,035a-iob-idelay,005-tilegrid))
|
||||
$(eval $(call fuzzer,036-iob-ologic,005-tilegrid))
|
||||
$(eval $(call fuzzer,037-iob-pips,005-tilegrid))
|
||||
$(eval $(call fuzzer,038-cfg,005-tilegrid))
|
||||
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid))
|
||||
|
|
|
|||
|
|
@ -144,6 +144,12 @@ case "$1" in
|
|||
hclk_ioi3)
|
||||
cp "$2" "$tmp1" ;;
|
||||
|
||||
ioi3_l)
|
||||
sed < "$2" > "$tmp1" -e 's/^IOI3\./LIOI3./' ;;
|
||||
|
||||
ioi3_r)
|
||||
sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3./' ;;
|
||||
|
||||
mask_*)
|
||||
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
|
||||
ismask=true
|
||||
|
|
|
|||
Loading…
Reference in New Issue