mirror of https://github.com/openXC7/prjxray.git
Fix some bugs present timing analysis script.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
541d88c999
commit
d95eefc8de
|
|
@ -8,7 +8,7 @@ build/.touch:
|
||||||
touch build/.touch
|
touch build/.touch
|
||||||
|
|
||||||
%.json: %.json5
|
%.json: %.json5
|
||||||
python3 clean_json5.py < $< > $@
|
python3 ${XRAY_UTILS_DIR}/clean_json5.py < $< > $@
|
||||||
|
|
||||||
CURDIR=$(shell pwd)
|
CURDIR=$(shell pwd)
|
||||||
|
|
||||||
|
|
@ -18,14 +18,14 @@ define output_timing
|
||||||
# $(2) - DESIGN_NAME
|
# $(2) - DESIGN_NAME
|
||||||
# $(3) - VERILOGS
|
# $(3) - VERILOGS
|
||||||
|
|
||||||
build/$(2)_$(1)/timing_$(2)_$(1).json5: build/.touch runme.tcl $(3)
|
build/$(2)_$(1)/timing_$(2)_$(1).json5: build/.touch runme.tcl ${XRAY_UTILS_DIR}/write_timing_info.tcl $(3)
|
||||||
rm -rf build/$(2)_$(1)
|
rm -rf build/$(2)_$(1)
|
||||||
mkdir -p build/$(2)_$(1)
|
mkdir -p build/$(2)_$(1)
|
||||||
export ITER=$(1) DESIGN_NAME=$(2) VERILOGS="$(3)" && cd build/$(2)_$(1) && \
|
export ITER=$(1) DESIGN_NAME=$(2) VERILOGS="$(3)" && cd build/$(2)_$(1) && \
|
||||||
${XRAY_VIVADO} -mode batch -source ${CURDIR}/runme.tcl > design_$(2)_$(1)_vivado.log
|
${XRAY_VIVADO} -mode batch -source ${CURDIR}/runme.tcl > design_$(2)_$(1)_vivado.log
|
||||||
|
|
||||||
build/timing_$(2)_$(1).xlsx: build/$(2)_$(1)/timing_$(2)_$(1).json create_timing_worksheet_db.py
|
build/timing_$(2)_$(1).xlsx: build/$(2)_$(1)/timing_$(2)_$(1).json ${XRAY_UTILS_DIR}/create_timing_worksheet_db.py
|
||||||
python3 create_timing_worksheet_db.py \
|
python3 ${XRAY_UTILS_DIR}/create_timing_worksheet_db.py \
|
||||||
--timing_json build/$(2)_$(1)/timing_$(2)_$(1).json \
|
--timing_json build/$(2)_$(1)/timing_$(2)_$(1).json \
|
||||||
--db_root ${XRAY_FAMILY_DIR} \
|
--db_root ${XRAY_FAMILY_DIR} \
|
||||||
--part ${XRAY_PART} \
|
--part ${XRAY_PART} \
|
||||||
|
|
|
||||||
|
|
@ -1,95 +1,4 @@
|
||||||
proc write_timing_info {filename} {
|
source $::env(XRAY_UTILS_DIR)/write_timing_info.tcl
|
||||||
set fp [open $filename w]
|
|
||||||
puts $fp "\["
|
|
||||||
|
|
||||||
set nets [get_nets]
|
|
||||||
foreach net $nets {
|
|
||||||
if { $net == "<const0>" || $net == "<const1>" } {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if { [get_property ROUTE_STATUS [get_nets $net]] == "INTRASITE" } {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if { [get_property ROUTE_STATUS [get_nets $net]] == "NOLOADS" } {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
puts $fp "{"
|
|
||||||
puts $fp "\"net\":\"$net\","
|
|
||||||
|
|
||||||
set route [get_property ROUTE $net]
|
|
||||||
puts $fp "\"route\":\"$route\","
|
|
||||||
|
|
||||||
set pips [get_pips -of_objects $net]
|
|
||||||
puts $fp "\"pips\":\["
|
|
||||||
foreach pip $pips {
|
|
||||||
puts $fp "{"
|
|
||||||
puts $fp "\"name\":\"$pip\","
|
|
||||||
puts $fp "\"src_wire\":\"[get_wires -uphill -of_objects $pip]\","
|
|
||||||
puts $fp "\"dst_wire\":\"[get_wires -downhill -of_objects $pip]\","
|
|
||||||
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $pip]\","
|
|
||||||
puts $fp "\"is_directional\":\"[get_property IS_DIRECTIONAL $pip]\","
|
|
||||||
puts $fp "},"
|
|
||||||
}
|
|
||||||
puts $fp "\],"
|
|
||||||
puts $fp "\"nodes\":\["
|
|
||||||
set nodes [get_nodes -of_objects $net]
|
|
||||||
foreach node $nodes {
|
|
||||||
puts $fp "{"
|
|
||||||
puts $fp "\"name\":\"$node\","
|
|
||||||
puts $fp "\"cost_code\":\"[get_property COST_CODE $node]\","
|
|
||||||
puts $fp "\"cost_code_name\":\"[get_property COST_CODE_NAME $node]\","
|
|
||||||
puts $fp "\"speed_class\":\"[get_property SPEED_CLASS $node]\","
|
|
||||||
puts $fp "\"wires\":\["
|
|
||||||
set wires [get_wires -of_objects $node]
|
|
||||||
foreach wire $wires {
|
|
||||||
puts $fp "{"
|
|
||||||
puts $fp "\"name\":\"$wire\","
|
|
||||||
puts $fp "\"cost_code\":\"[get_property COST_CODE $wire]\","
|
|
||||||
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $wire]\","
|
|
||||||
puts $fp "},"
|
|
||||||
}
|
|
||||||
puts $fp "\],"
|
|
||||||
puts $fp "},"
|
|
||||||
}
|
|
||||||
puts $fp "\],"
|
|
||||||
|
|
||||||
set opin [get_pins -leaf -of_objects [get_nets $net] -filter {DIRECTION == OUT}]
|
|
||||||
puts $fp "\"opin\": {"
|
|
||||||
puts $fp "\"name\":\"$opin\","
|
|
||||||
set opin_site_pin [get_site_pins -of_objects $opin]
|
|
||||||
puts $fp "\"site_pin\":\"$opin_site_pin\","
|
|
||||||
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $opin_site_pin]\","
|
|
||||||
puts $fp "\"node\":\"[get_nodes -of_objects $opin_site_pin]\","
|
|
||||||
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $opin_site_pin]]\","
|
|
||||||
puts $fp "},"
|
|
||||||
set ipins [get_pins -of_objects [get_nets $net] -filter {DIRECTION == IN} -leaf]
|
|
||||||
puts $fp "\"ipins\":\["
|
|
||||||
foreach ipin $ipins {
|
|
||||||
puts $fp "{"
|
|
||||||
set delay [get_net_delays -interconnect_only -of_objects $net -to $ipin]
|
|
||||||
puts $fp "\"name\":\"$ipin\","
|
|
||||||
puts $fp "\"ic_delays\":{"
|
|
||||||
foreach prop {"FAST_MAX" "FAST_MIN" "SLOW_MAX" "SLOW_MIN"} {
|
|
||||||
puts $fp "\"$prop\":\"[get_property $prop $delay]\","
|
|
||||||
}
|
|
||||||
puts $fp "},"
|
|
||||||
set ipin_site_pin [get_site_pin -of_objects $ipin]
|
|
||||||
puts $fp "\"site_pin\":\"$ipin_site_pin\","
|
|
||||||
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $ipin_site_pin]\","
|
|
||||||
puts $fp "\"node\":\"[get_nodes -of_objects $ipin_site_pin]\","
|
|
||||||
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $ipin_site_pin]]\","
|
|
||||||
puts $fp "},"
|
|
||||||
}
|
|
||||||
puts $fp "\],"
|
|
||||||
|
|
||||||
puts $fp "},"
|
|
||||||
}
|
|
||||||
|
|
||||||
puts $fp "\]"
|
|
||||||
close $fp
|
|
||||||
}
|
|
||||||
|
|
||||||
proc create_design {design_name sig_mask verilogs} {
|
proc create_design {design_name sig_mask verilogs} {
|
||||||
create_project -part $::env(XRAY_PART) -force design_$design_name \
|
create_project -part $::env(XRAY_PART) -force design_$design_name \
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
""" This takes a JSON file generated with write_timing_info.tcl and generates
|
||||||
|
a spreadsheet with the prjxray timing model and compares it with the
|
||||||
|
interconnect timing output from Vivado.
|
||||||
|
|
||||||
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
from openpyxl import Workbook, utils
|
from openpyxl import Workbook, utils
|
||||||
|
|
@ -92,7 +97,8 @@ class Net(object):
|
||||||
self.models = {}
|
self.models = {}
|
||||||
|
|
||||||
for ipin in net['ipins']:
|
for ipin in net['ipins']:
|
||||||
self.ipin_nodes[ipin['node']] = ipin
|
for ipin_node in ipin['node'].strip().split(' '):
|
||||||
|
self.ipin_nodes[ipin_node] = ipin
|
||||||
|
|
||||||
# Map of wire name to parent node
|
# Map of wire name to parent node
|
||||||
self.wire_to_node = {}
|
self.wire_to_node = {}
|
||||||
|
|
@ -112,7 +118,7 @@ class Net(object):
|
||||||
dst_wire = pip['dst_wire'].split('/')[1]
|
dst_wire = pip['dst_wire'].split('/')[1]
|
||||||
self.pips[(src_node, dst_wire)] = pip
|
self.pips[(src_node, dst_wire)] = pip
|
||||||
|
|
||||||
if not pip['is_directional']:
|
if not int(pip['is_directional']):
|
||||||
dst_node = self.wire_to_node[pip['dst_wire']]['name']
|
dst_node = self.wire_to_node[pip['dst_wire']]['name']
|
||||||
src_wire = pip['src_wire'].split('/')[1]
|
src_wire = pip['src_wire'].split('/')[1]
|
||||||
self.pips[(dst_node, src_wire)] = pip
|
self.pips[(dst_node, src_wire)] = pip
|
||||||
|
|
@ -235,7 +241,10 @@ class Net(object):
|
||||||
self.row += 1
|
self.row += 1
|
||||||
|
|
||||||
if current_node in self.ipin_nodes:
|
if current_node in self.ipin_nodes:
|
||||||
assert route[route_idx] == '}'
|
assert route[route_idx] in ['}', 'IOB_O_OUT0', 'IOB_T_OUT0'], (
|
||||||
|
route_idx,
|
||||||
|
route[route_idx],
|
||||||
|
)
|
||||||
route_idx += 1
|
route_idx += 1
|
||||||
|
|
||||||
node = self.node_name_to_node[current_node]
|
node = self.node_name_to_node[current_node]
|
||||||
|
|
@ -251,7 +260,7 @@ class Net(object):
|
||||||
ws['A{}'.format(self.row)] = ipin['name']
|
ws['A{}'.format(self.row)] = ipin['name']
|
||||||
ws['B{}'.format(self.row)] = 'Inpin'
|
ws['B{}'.format(self.row)] = 'Inpin'
|
||||||
|
|
||||||
site_pin = timing_lookup.find_site_pin(ipin['node'], node_idx=-1)
|
site_pin = timing_lookup.find_site_pin(current_node, node_idx=-1)
|
||||||
assert isinstance(site_pin.timing, InPinTiming)
|
assert isinstance(site_pin.timing, InPinTiming)
|
||||||
|
|
||||||
cells = {}
|
cells = {}
|
||||||
|
|
@ -421,8 +430,9 @@ class Net(object):
|
||||||
|
|
||||||
|
|
||||||
def add_net(wb, net, timing_lookup):
|
def add_net(wb, net, timing_lookup):
|
||||||
|
replace_underscore = str.maketrans('[]\\:/', '_____')
|
||||||
ws = wb.create_sheet(
|
ws = wb.create_sheet(
|
||||||
title="Net {}".format(net['net'].replace('[', '_').replace(']', '_')))
|
title="Net {}".format(net['net'].translate(replace_underscore)))
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
ws['A1'] = 'Name'
|
ws['A1'] = 'Name'
|
||||||
|
|
@ -478,13 +488,14 @@ def main():
|
||||||
cur_col = chr(ord(cur_col) + 3)
|
cur_col = chr(ord(cur_col) + 3)
|
||||||
|
|
||||||
summary_row = 2
|
summary_row = 2
|
||||||
for net in timing:
|
for idx, net in enumerate(timing):
|
||||||
if '<' in net['route']:
|
if '<' in net['route']:
|
||||||
print(
|
print(
|
||||||
"WARNING: Skipping net {} because it has complicated route description."
|
"WARNING: Skipping net {} because it has complicated route description."
|
||||||
.format(net['net']))
|
.format(net['net']))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
print('Process net {} ({} / {})'.format(net['net'], idx, len(timing)))
|
||||||
for summary_cells in add_net(wb, net, timing_lookup):
|
for summary_cells in add_net(wb, net, timing_lookup):
|
||||||
summary_ws['A{}'.format(summary_row)] = summary_cells['Name']
|
summary_ws['A{}'.format(summary_row)] = summary_cells['Name']
|
||||||
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Writes a JSON5 to filename containing timing for current design.
|
||||||
|
# This can be used with create_timing_worksheet_db.py to compare prjxray model
|
||||||
|
# with Vivado timing model outputs.
|
||||||
|
proc write_timing_info {filename} {
|
||||||
|
set fp [open $filename w]
|
||||||
|
puts $fp "\["
|
||||||
|
|
||||||
|
set nets [get_nets]
|
||||||
|
set idx 0
|
||||||
|
foreach net $nets {
|
||||||
|
puts "net: $net ($idx / [llength $nets])"
|
||||||
|
incr idx
|
||||||
|
if { $net == "<const0>" || $net == "<const1>" } {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [get_property TYPE [get_nets $net]] == "GROUND" } {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if { [get_property TYPE [get_nets $net]] == "POWER" } {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if { [get_property ROUTE_STATUS [get_nets $net]] == "INTRASITE" } {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if { [get_property ROUTE_STATUS [get_nets $net]] == "NOLOADS" } {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
puts $fp "{"
|
||||||
|
puts $fp "\"net\":\"$net\","
|
||||||
|
|
||||||
|
set route [get_property ROUTE $net]
|
||||||
|
puts $fp "\"route\":\"$route\","
|
||||||
|
|
||||||
|
set pips [get_pips -of_objects $net]
|
||||||
|
puts $fp "\"pips\":\["
|
||||||
|
foreach pip $pips {
|
||||||
|
puts $fp "{"
|
||||||
|
puts $fp "\"name\":\"$pip\","
|
||||||
|
puts $fp "\"src_wire\":\"[get_wires -uphill -of_objects $pip]\","
|
||||||
|
puts $fp "\"dst_wire\":\"[get_wires -downhill -of_objects $pip]\","
|
||||||
|
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $pip]\","
|
||||||
|
puts $fp "\"is_directional\":\"[get_property IS_DIRECTIONAL $pip]\","
|
||||||
|
puts $fp "},"
|
||||||
|
}
|
||||||
|
puts $fp "\],"
|
||||||
|
puts $fp "\"nodes\":\["
|
||||||
|
set nodes [get_nodes -of_objects $net]
|
||||||
|
foreach node $nodes {
|
||||||
|
puts $fp "{"
|
||||||
|
puts $fp "\"name\":\"$node\","
|
||||||
|
puts $fp "\"cost_code\":\"[get_property COST_CODE $node]\","
|
||||||
|
puts $fp "\"cost_code_name\":\"[get_property COST_CODE_NAME $node]\","
|
||||||
|
puts $fp "\"speed_class\":\"[get_property SPEED_CLASS $node]\","
|
||||||
|
puts $fp "\"wires\":\["
|
||||||
|
set wires [get_wires -of_objects $node]
|
||||||
|
foreach wire $wires {
|
||||||
|
puts $fp "{"
|
||||||
|
puts $fp "\"name\":\"$wire\","
|
||||||
|
puts $fp "\"cost_code\":\"[get_property COST_CODE $wire]\","
|
||||||
|
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $wire]\","
|
||||||
|
puts $fp "},"
|
||||||
|
}
|
||||||
|
puts $fp "\],"
|
||||||
|
puts $fp "},"
|
||||||
|
}
|
||||||
|
puts $fp "\],"
|
||||||
|
|
||||||
|
set opin [get_pins -leaf -of_objects [get_nets $net] -filter {DIRECTION == OUT}]
|
||||||
|
puts $fp "\"opin\": {"
|
||||||
|
puts $fp "\"name\":\"$opin\","
|
||||||
|
set opin_site_pin [get_site_pins -of_objects $opin]
|
||||||
|
puts $fp "\"site_pin\":\"$opin_site_pin\","
|
||||||
|
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $opin_site_pin]\","
|
||||||
|
puts $fp "\"node\":\"[get_nodes -of_objects $opin_site_pin]\","
|
||||||
|
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $opin_site_pin]]\","
|
||||||
|
puts $fp "},"
|
||||||
|
set ipins [get_pins -of_objects [get_nets $net] -filter {DIRECTION == IN} -leaf]
|
||||||
|
puts $fp "\"ipins\":\["
|
||||||
|
foreach ipin $ipins {
|
||||||
|
set ipin_site_pin [get_site_pins -of_objects $ipin -quiet]
|
||||||
|
if { $ipin_site_pin == "" } {
|
||||||
|
# This connection is internal!
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
puts $fp "{"
|
||||||
|
set delay [get_net_delays -interconnect_only -of_objects $net -to $ipin]
|
||||||
|
puts $fp "\"name\":\"$ipin\","
|
||||||
|
puts $fp "\"ic_delays\":{"
|
||||||
|
foreach prop {"FAST_MAX" "FAST_MIN" "SLOW_MAX" "SLOW_MIN"} {
|
||||||
|
puts $fp "\"$prop\":\"[get_property $prop $delay]\","
|
||||||
|
}
|
||||||
|
puts $fp "},"
|
||||||
|
puts $fp "\"site_pin\":\"$ipin_site_pin\","
|
||||||
|
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $ipin_site_pin]\","
|
||||||
|
puts $fp "\"node\":\"[get_nodes -of_objects $ipin_site_pin]\","
|
||||||
|
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $ipin_site_pin]]\","
|
||||||
|
puts $fp "},"
|
||||||
|
}
|
||||||
|
puts $fp "\],"
|
||||||
|
|
||||||
|
puts $fp "},"
|
||||||
|
}
|
||||||
|
|
||||||
|
puts $fp "\]"
|
||||||
|
close $fp
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue