timfuz: utility to create tile to speed model database

Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
John McMaster 2018-08-29 17:36:00 -07:00
parent 5176374817
commit fb69b9f045
6 changed files with 346 additions and 0 deletions

74
timfuz/tile_txt2json.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python3
import sys
import os
import time
import json
SI_NONE = 0xFFFF
def load_speed_json(f):
j = json.load(f)
# Index speed indexes to names
speed_i2s = {}
for k, v in j['speed_model'].items():
i = v['speed_index']
if i != SI_NONE:
speed_i2s[i] = k
return j, speed_i2s
def gen_tiles(fnin, speed_i2s):
for l in open(fnin):
# lappend items pip $name $speed_index
# puts $fp "$type $tile $grid_x $grid_y $items"
parts = l.strip().split()
tile_type, tile_name, grid_x, grid_y = parts[0:4]
grid_x, grid_y = int(grid_x), int(grid_y)
tuples = parts[4:]
assert len(tuples) % 3 == 0
pips = {}
wires = {}
for i in range(0, len(tuples), 3):
ttype, name, speed_index = tuples[i:i+3]
name_local = name.split('/')[1]
{
'pip': pips,
'wire': wires,
}[ttype][name_local] = speed_i2s[int(speed_index)]
yield (tile_type, tile_name, grid_x, grid_y, pips, wires)
def run(fnin, fnout, speed_json_fn, verbose=False):
speedj, speed_i2s = load_speed_json(open(speed_json_fn, 'r'))
tiles = {}
for tile in gen_tiles(fnin, speed_i2s):
(tile_type, tile_name, grid_x, grid_y, pips, wires) = tile
this_dat = {'pips': pips, 'wires': wires}
if tile_type not in tiles:
tiles[tile_type] = this_dat
else:
if tiles[tile_type] != this_dat:
print(tile_name, tile_type)
print(this_dat)
print(tiles[tile_type])
assert 0
j = {'tiles': tiles}
json.dump(j, open(fnout, 'w'), sort_keys=True, indent=4, separators=(',', ': '))
def main():
import argparse
parser = argparse.ArgumentParser(
description=
'Solve timing solution'
)
parser.add_argument('--speed-json', default='build_speed/speed.json',
help='Provides speed index to name translation')
parser.add_argument('fnin', default=None, help='input tcl output .txt')
parser.add_argument('fnout', default=None, help='output .json')
args = parser.parse_args()
run(args.fnin, args.fnout, speed_json_fn=args.speed_json, verbose=False)
if __name__ == '__main__':
main()

26
timfuz/timgrid/Makefile Normal file
View File

@ -0,0 +1,26 @@
N := 1
SPECIMENS := $(addprefix specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
database: $(SPECIMENS_OK)
cp specimen_001/tilegrid.json tilegrid.json
pushdb:
cp tilegrid.json ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/tilegrid.json
$(SPECIMENS_OK):
bash generate.sh $(subst /OK,,$@)
touch $@
run:
$(MAKE) clean
$(MAKE) database
$(MAKE) pushdb
touch run.ok
clean:
rm -rf specimen_[0-9][0-9][0-9]/ tilegrid.json run.ok
.PHONY: database pushdb clean run

View File

@ -0,0 +1,16 @@
#!/bin/bash -x
source ${XRAY_GENHEADER}
vivado -mode batch -source ../generate.tcl
for x in design*.bit; do
${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${x}s -z -y $x
done
for x in design_*.bits; do
diff -u design.bits $x | grep '^[-+]bit' > ${x%.bits}.delta
done
python3 ../generate.py design_*.delta > tilegrid.json

119
timfuz/timgrid/generate.tcl Normal file
View File

@ -0,0 +1,119 @@
proc create_project {} {
if 0 {
set grid_min_x -1
set grid_max_x -1
set grid_min_y -1
set grid_max_y -1
} {
set grid_min_x $::env(XRAY_ROI_GRID_X1)
set grid_max_x $::env(XRAY_ROI_GRID_X2)
set grid_min_y $::env(XRAY_ROI_GRID_Y1)
set grid_max_y $::env(XRAY_ROI_GRID_Y2)
}
create_project -force -part $::env(XRAY_PART) design design
read_verilog ../top.v
synth_design -top top
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports do]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports stb]
create_pblock roi
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_param tcl.collectionResultDisplayLimit 0
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
set luts [get_bels -of_objects [get_sites -of_objects [get_pblocks roi]] -filter {TYPE =~ LUT*} */A6LUT]
set selected_luts {}
set lut_index 0
# LOC one LUT (a "selected_lut") into each CLB segment configuration column (ie 50 per column)
# Also, if GRID_MIN/MAX is not defined, automatically create it based on used CLBs
# See caveat in README on automatic creation
foreach lut $luts {
set tile [get_tile -of_objects $lut]
set grid_x [get_property GRID_POINT_X $tile]
set grid_y [get_property GRID_POINT_Y $tile]
if [expr $grid_min_x < 0 || $grid_x < $grid_min_x] {set grid_min_x $grid_x}
if [expr $grid_max_x < 0 || $grid_x > $grid_max_x] {set grid_max_x $grid_x}
if [expr $grid_min_y < 0 || $grid_y < $grid_min_y] {set grid_min_y $grid_y}
if [expr $grid_max_y < 0 || $grid_y > $grid_max_y] {set grid_max_y $grid_y}
# 50 per column => 50, 100, 150, etc
if [regexp "Y(0|[0-9]*[05]0)/" $lut] {
set cell [get_cells roi/is[$lut_index].lut]
set_property LOC [get_sites -of_objects $lut] $cell
set lut_index [expr $lut_index + 1]
lappend selected_luts $lut
}
}
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
proc write_data {} {
if 0 {
set grid_min_x -1
set grid_max_x -1
set grid_min_y -1
set grid_max_y -1
} {
set grid_min_x $::env(XRAY_ROI_GRID_X1)
set grid_max_x $::env(XRAY_ROI_GRID_X2)
set grid_min_y $::env(XRAY_ROI_GRID_Y1)
set grid_max_y $::env(XRAY_ROI_GRID_Y2)
}
# Get all tiles in ROI, ie not just the selected LUTs
set tiles [get_tiles -filter "GRID_POINT_X >= $grid_min_x && GRID_POINT_X <= $grid_max_x && GRID_POINT_Y >= $grid_min_y && GRID_POINT_Y <= $grid_max_y"]
# Write tiles.txt with site metadata
set fp [open "tiles.txt" w]
foreach tile $tiles {
set type [get_property TYPE $tile]
set grid_x [get_property GRID_POINT_X $tile]
set grid_y [get_property GRID_POINT_Y $tile]
set items {}
set wires [get_wires -of_objects $tile]
if [llength $wires] {
foreach wire $wires {
set name [get_property NAME $wire]
set speed_index [get_property SPEED_INDEX $wire]
lappend items wire $name $speed_index
}
}
set pips [get_pips -of_objects $tile]
if [llength $pips] {
foreach pip $pips {
set name [get_property NAME $pip]
set speed_index [get_property SPEED_INDEX $pip]
lappend items pip $name $speed_index
}
}
puts $fp "$type $tile $grid_x $grid_y $items"
}
close $fp
}
create_project
write_data

49
timfuz/timgrid/top.v Normal file
View File

@ -0,0 +1,49 @@
//Need at least one LUT per frame base address we want
`define N 100
module top(input clk, stb, di, output do);
localparam integer DIN_N = 6;
localparam integer DOUT_N = `N;
reg [DIN_N-1:0] din;
wire [DOUT_N-1:0] dout;
reg [DIN_N-1:0] din_shr;
reg [DOUT_N-1:0] dout_shr;
always @(posedge clk) begin
din_shr <= {din_shr, di};
dout_shr <= {dout_shr, din_shr[DIN_N-1]};
if (stb) begin
din <= din_shr;
dout_shr <= dout;
end
end
assign do = dout_shr[DOUT_N-1];
roi roi (
.clk(clk),
.din(din),
.dout(dout)
);
endmodule
module roi(input clk, input [5:0] din, output [`N-1:0] dout);
genvar i;
generate
for (i = 0; i < `N; i = i+1) begin:is
LUT6 #(
.INIT(64'h8000_0000_0000_0001 + (i << 16))
) lut (
.I0(din[0]),
.I1(din[1]),
.I2(din[2]),
.I3(din[3]),
.I4(din[4]),
.I5(din[5]),
.O(dout[i])
);
end
endgenerate
endmodule

62
timfuz/timgrid/top_bram.v Normal file
View File

@ -0,0 +1,62 @@
`define N 100
module top(input clk, stb, di, output do);
localparam integer DIN_N = 8;
localparam integer DOUT_N = `N;
reg [DIN_N-1:0] din;
wire [DOUT_N-1:0] dout;
reg [DIN_N-1:0] din_shr;
reg [DOUT_N-1:0] dout_shr;
always @(posedge clk) begin
din_shr <= {din_shr, di};
dout_shr <= {dout_shr, din_shr[DIN_N-1]};
if (stb) begin
din <= din_shr;
dout_shr <= dout;
end
end
assign do = dout_shr[DOUT_N-1];
roi roi (
.clk(clk),
.din(din),
.dout(dout)
);
endmodule
module roi(input clk, input [7:0] din, output [`N-1:0] dout);
genvar i;
generate
for (i = 0; i < `N; i = i+1) begin:is
(* KEEP, DONT_TOUCH *)
RAMB36E1 #(.INIT_00(256'h0000000000000000000000000000000000000000000000000000000000000000)) ram (
.CLKARDCLK(din[0]),
.CLKBWRCLK(din[1]),
.ENARDEN(din[2]),
.ENBWREN(din[3]),
.REGCEAREGCE(din[4]),
.REGCEB(din[5]),
.RSTRAMARSTRAM(din[6]),
.RSTRAMB(din[7]),
.RSTREGARSTREG(din[0]),
.RSTREGB(din[1]),
.ADDRARDADDR(din[2]),
.ADDRBWRADDR(din[3]),
.DIADI(din[4]),
.DIBDI(din[5]),
.DIPADIP(din[6]),
.DIPBDIP(din[7]),
.WEA(din[0]),
.WEBWE(din[1]),
.DOADO(dout[0]),
.DOBDO(),
.DOPADOP(),
.DOPBDOP());
end
endgenerate
endmodule