Skip to content

Commit ca7d60a

Browse files
committed
Merge branch 'master' into generate_test_constraints_files
2 parents 39b78b5 + d15ed67 commit ca7d60a

14 files changed

+452
-29
lines changed

.github/kokoro/steps/hostsetup.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ export PATH="$PATH:/home/kbuilder/.local/bin"
9999
export CC=gcc-9
100100
export CXX=g++-9
101101

102-
pyenv install -f 3.6.3
103-
pyenv global 3.6.3
102+
pyenv install -f 3.7.0
103+
pyenv global 3.7.0
104104
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
105105
python3 get-pip.py
106106
rm get-pip.py

doc/src/vpr/command_line_usage.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,12 @@ For people not working on CAD, you can probably leave all the options to their d
626626

627627
**Default:** ``2``
628628

629+
.. option:: --write_block_usage <file>
630+
631+
Writes out to the file under path <file> cluster-level block usage summary in machine
632+
readable (JSON or XML) or human readable (TXT) format. Format is selected
633+
based on the extension of <file>.
634+
629635
.. _placer_options:
630636

631637
Placer Options
@@ -1035,6 +1041,17 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout
10351041

10361042
**Default:** ``off``
10371043

1044+
.. option:: --write_timing_summary <file>
1045+
1046+
Writes out to the file under path <file> final timing summary in machine
1047+
readable (JSON or XML) or human readable (TXT) format. Format is selected
1048+
based on the extension of <file>. The summary consists of parameters:
1049+
1050+
* `cpd` - Final critical path delay (least slack) [ns]
1051+
* `fmax` - Maximal frequency of the implemented circuit [MHz]
1052+
* `swns` - setup Worst Negative Slack (sWNS) [ns]
1053+
* `stns` - Setup Total Negative Slack (sTNS) [ns]
1054+
10381055
.. _timing_driven_router_options:
10391056

10401057
Timing-Driven Router Options

doc/src/vpr/file_formats.rst

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,3 +1046,159 @@ An example of what a generated routing resource graph file would look like is sh
10461046
</rr_edges>
10471047
</rr_graph>
10481048
.. _end:
1049+
1050+
Block types usage summary (.txt .xml or .json)
1051+
-----------------------------------------
1052+
1053+
Block types usage summary is a file written in human or machine readable format.
1054+
It describes types and the amount of cluster-level FPGA resources that are used
1055+
by implemented design. This file is generated after the placement step with
1056+
option: `--write_block_usage <filename>`. It can be saved as a human readable
1057+
text file or in XML or JSON file to provide machine readable output. Format is
1058+
selected based on the extension of the `<filename>`.
1059+
1060+
The summary consists of 4 parameters:
1061+
1062+
* `nets number` - the amount of created nets
1063+
* `blocks number` - sum of blocks used to implement the design
1064+
* `input pins` - sum of input pins
1065+
* `output pins` - sum of output pins
1066+
1067+
and a list of `block types` followed by the number of specific block types that
1068+
are used in the design.
1069+
1070+
TXT
1071+
~~~
1072+
1073+
Presents the information in human readable format, the same as in log output:
1074+
1075+
.. code-block:: none
1076+
:caption: TXT format of block types usage summary
1077+
:linenos:
1078+
1079+
Netlist num_nets: <int>
1080+
Netlist num_blocks: <int>
1081+
Netlist <block_type_name_0> blocks: <int>
1082+
Netlist <block_type_name_1> blocks: <int>
1083+
...
1084+
Netlist <block_type_name_n> blocks: <int>
1085+
Netlist inputs pins: <int>
1086+
Netlist output pins: <int>
1087+
1088+
.. _end:
1089+
1090+
JSON
1091+
~~~~
1092+
1093+
One of two available machine readable formats. The information is written as follows:
1094+
1095+
.. code-block:: json
1096+
:caption: JSON format of block types usage summary
1097+
:linenos:
1098+
1099+
{
1100+
"num_nets": "<int>",
1101+
"num_blocks": "<int>",
1102+
"input_pins": "<int>",
1103+
"output_pins": "<int>",
1104+
"blocks": {
1105+
"<block_type_name_0>": <int>,
1106+
"<block_type_name_1>": <int>,
1107+
...
1108+
"<block_type_name_n>": <int>
1109+
}
1110+
}
1111+
1112+
.. _end:
1113+
1114+
XML
1115+
~~~
1116+
1117+
Second machine readable format. The information is written as follows:
1118+
1119+
.. code-block:: xml
1120+
:caption: XML format of block types usage summary
1121+
:linenos:
1122+
1123+
<?xml version="1.0" encoding="UTF-8"?>
1124+
<block_usage_report>
1125+
<nets num="<int>"></nets>
1126+
<blocks num="<int>">
1127+
<block type="<block_type_name_0>" usage="<int>"></block>
1128+
<block type="<block_type_name_1>" usage="<int>"></block>
1129+
...
1130+
<block type="<block_type_name_n>" usage="<int>"></block>
1131+
</blocks>
1132+
<input_pins num="<int>"></input_pins>
1133+
<output_pins num="<int>"></output_pins>
1134+
</block_usage_report>
1135+
1136+
.. _end:
1137+
1138+
Timing summary (.txt .xml or .json)
1139+
-----------------------------------------
1140+
1141+
Timing summary is a file written in human or machine readable format.
1142+
It describes final timing parameters of design implemented for the FPGA device.
1143+
This file is generated after the routing step with option: `--write_timing_summary <filename>`.
1144+
It can be saved as a human readable text file or in XML or JSON file to provide
1145+
machine readable output. Format is selected based on the extension of the `<filename>`.
1146+
1147+
The summary consists of 4 parameters:
1148+
1149+
* `Critical Path Delay (cpd) [ns]`
1150+
* `Max Circuit Frequency (Fmax) [MHz]`
1151+
* `setup Worst Negative Slack (sWNS) [ns]`
1152+
* `setup Total Negative Slack (sTNS) [ns]`
1153+
1154+
TXT
1155+
~~~
1156+
1157+
Presents the information in human readable format, the same as in log output:
1158+
1159+
.. code-block:: none
1160+
:caption: TXT format of timing summary
1161+
:linenos:
1162+
1163+
Final critical path delay (least slack): <double> ns, Fmax: <double> MHz
1164+
Final setup Worst Negative Slack (sWNS): <double> ns
1165+
Final setup Total Negative Slack (sTNS): <double> ns
1166+
1167+
.. _end:
1168+
1169+
JSON
1170+
~~~~
1171+
1172+
One of two available machine readable formats. The information is written as follows:
1173+
1174+
.. code-block:: json
1175+
:caption: JSON format of timing summary
1176+
:linenos:
1177+
1178+
{
1179+
"cpd": <double>,
1180+
"fmax": <double>,
1181+
"swns": <double>,
1182+
"stns": <double>
1183+
}
1184+
1185+
.. _end:
1186+
1187+
XML
1188+
~~~
1189+
1190+
Second machine readable format. The information is written as follows:
1191+
1192+
.. code-block:: xml
1193+
:caption: XML format of timing summary
1194+
:linenos:
1195+
1196+
<?xml version="1.0" encoding="UTF-8"?>
1197+
<timing_summary_report>
1198+
<cpd value="<double>" unit="ns" description="Final critical path delay"></nets>
1199+
<fmax value="<double>" unit="MHz" description="Max circuit frequency"></fmax>
1200+
<swns value="<double>" unit="ns" description="setup Worst Negative Slack (sWNS)"></swns>
1201+
<stns value="<double>" unit="ns" description="setup Total Negative Slack (sTNS)"></stns>
1202+
</block_usage_report>
1203+
1204+
.. _end:

vpr/src/analysis/timing_reports.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ void generate_setup_timing_stats(const std::string& prefix, const SetupTimingInf
1616
auto& timing_ctx = g_vpr_ctx.timing();
1717
auto& atom_ctx = g_vpr_ctx.atom();
1818

19-
print_setup_timing_summary(*timing_ctx.constraints, *timing_info.setup_analyzer(), "Final ");
19+
print_setup_timing_summary(*timing_ctx.constraints, *timing_info.setup_analyzer(), "Final ", analysis_opts.write_timing_summary);
2020

2121
VprTimingGraphResolver resolver(atom_ctx.nlist, atom_ctx.lookup, *timing_ctx.graph, delay_calc);
2222
resolver.set_detail_level(analysis_opts.timing_report_detail);

vpr/src/base/SetupVPR.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ void SetupVPR(const t_options* Options,
9898
FileNameOpts->out_file_prefix = Options->out_file_prefix;
9999
FileNameOpts->read_vpr_constraints_file = Options->read_vpr_constraints_file;
100100
FileNameOpts->write_vpr_constraints_file = Options->write_vpr_constraints_file;
101+
FileNameOpts->write_block_usage = Options->write_block_usage;
101102

102103
FileNameOpts->verify_file_digests = Options->verify_file_digests;
103104

@@ -632,6 +633,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi
632633
analysis_opts.post_synth_netlist_unconn_output_handling = Options.post_synth_netlist_unconn_output_handling;
633634

634635
analysis_opts.timing_update_type = Options.timing_update_type;
636+
analysis_opts.write_timing_summary = Options.write_timing_summary;
635637
}
636638

637639
static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) {

vpr/src/base/ShowSetup.cpp

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <fstream>
2+
13
#include "vtr_assert.h"
24
#include "vtr_log.h"
35
#include "vtr_memory.h"
@@ -61,21 +63,70 @@ void ShowSetup(const t_vpr_setup& vpr_setup) {
6163
}
6264
}
6365

64-
void printClusteredNetlistStats() {
65-
auto& device_ctx = g_vpr_ctx.device();
66-
auto& cluster_ctx = g_vpr_ctx.clustering();
66+
void ClusteredNetlistStats::writeHuman(std::ostream& output) const {
67+
output << "Cluster level netlist and block usage statistics\n";
68+
output << "Netlist num_nets: " << num_nets << "\n";
69+
output << "Netlist num_blocks: " << num_blocks << "\n";
70+
for (const auto& type : logical_block_types) {
71+
output << "Netlist " << type.name << " blocks: " << num_blocks_type[type.index] << ".\n";
72+
}
73+
74+
output << "Netlist inputs pins: " << L_num_p_inputs << "\n";
75+
output << "Netlist output pins: " << L_num_p_outputs << "\n";
76+
}
77+
void ClusteredNetlistStats::writeJSON(std::ostream& output) const {
78+
output << "{\n";
6779

68-
int j, L_num_p_inputs, L_num_p_outputs;
69-
std::vector<int> num_blocks_type(device_ctx.logical_block_types.size(), 0);
80+
output << " \"num_nets\": \"" << num_nets << "\",\n";
81+
output << " \"num_blocks\": \"" << num_blocks << "\",\n";
7082

71-
VTR_LOG("\n");
72-
VTR_LOG("Netlist num_nets: %d\n", (int)cluster_ctx.clb_nlist.nets().size());
73-
VTR_LOG("Netlist num_blocks: %d\n", (int)cluster_ctx.clb_nlist.blocks().size());
83+
output << " \"input_pins\": \"" << L_num_p_inputs << "\",\n";
84+
output << " \"output_pins\": \"" << L_num_p_outputs << "\",\n";
7485

75-
/* Count I/O input and output pads */
86+
output << " \"blocks\": {\n";
87+
88+
for (const auto& type : logical_block_types) {
89+
output << " \"" << type.name << "\": " << num_blocks_type[type.index];
90+
if ((int)type.index < (int)logical_block_types.size() - 1)
91+
output << ",\n";
92+
else
93+
output << "\n";
94+
}
95+
output << " }\n";
96+
output << "}\n";
97+
}
98+
99+
void ClusteredNetlistStats::writeXML(std::ostream& output) const {
100+
output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
101+
output << "<block_usage_report>\n";
102+
103+
output << " <nets num=\"" << num_nets << "\"></nets>\n";
104+
output << " <blocks num=\"" << num_blocks << "\">\n";
105+
106+
for (const auto& type : logical_block_types) {
107+
output << " <block type=\"" << type.name << "\" usage=\"" << num_blocks_type[type.index] << "\"></block>\n";
108+
}
109+
output << " </blocks>\n";
110+
111+
output << " <input_pins num=\"" << L_num_p_inputs << "\"></input_pins>\n";
112+
output << " <output_pins num=\"" << L_num_p_outputs << "\"></output_pins>\n";
113+
114+
output << "</block_usage_report>\n";
115+
}
116+
117+
ClusteredNetlistStats::ClusteredNetlistStats() {
118+
auto& device_ctx = g_vpr_ctx.device();
119+
auto& cluster_ctx = g_vpr_ctx.clustering();
120+
121+
int j;
76122
L_num_p_inputs = 0;
77123
L_num_p_outputs = 0;
124+
num_blocks_type = std::vector<int>(device_ctx.logical_block_types.size(), 0);
125+
num_nets = (int)cluster_ctx.clb_nlist.nets().size();
126+
num_blocks = (int)cluster_ctx.clb_nlist.blocks().size();
127+
logical_block_types = device_ctx.logical_block_types;
78128

129+
/* Count I/O input and output pads */
79130
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
80131
auto logical_block = cluster_ctx.clb_nlist.block_type(blk_id);
81132
auto physical_tile = pick_physical_type(logical_block);
@@ -97,16 +148,52 @@ void printClusteredNetlistStats() {
97148
}
98149
}
99150
}
151+
}
100152

101-
for (const auto& type : device_ctx.logical_block_types) {
102-
VTR_LOG("Netlist %s blocks: %d.\n", type.name, num_blocks_type[type.index]);
153+
void ClusteredNetlistStats::write(OutputFormat fmt, std::ostream& output) const {
154+
switch (fmt) {
155+
case HumanReadable:
156+
writeHuman(output);
157+
break;
158+
case JSON:
159+
writeJSON(output);
160+
break;
161+
case XML:
162+
writeXML(output);
163+
break;
164+
default:
165+
VPR_FATAL_ERROR(VPR_ERROR_PACK,
166+
"Unknown extension on in block usage summary file");
167+
break;
103168
}
169+
}
104170

105-
/* Print out each block separately instead */
106-
VTR_LOG("Netlist inputs pins: %d\n", L_num_p_inputs);
107-
VTR_LOG("Netlist output pins: %d\n", L_num_p_outputs);
108-
VTR_LOG("\n");
109-
num_blocks_type.clear();
171+
void writeClusteredNetlistStats(std::string block_usage_filename) {
172+
const auto stats = ClusteredNetlistStats();
173+
174+
// Print out the human readable version to stdout
175+
176+
stats.write(ClusteredNetlistStats::OutputFormat::HumanReadable, std::cout);
177+
178+
if (block_usage_filename.size() > 0) {
179+
ClusteredNetlistStats::OutputFormat fmt;
180+
181+
if (vtr::check_file_name_extension(block_usage_filename.c_str(), ".json")) {
182+
fmt = ClusteredNetlistStats::OutputFormat::JSON;
183+
} else if (vtr::check_file_name_extension(block_usage_filename.c_str(), ".xml")) {
184+
fmt = ClusteredNetlistStats::OutputFormat::XML;
185+
} else if (vtr::check_file_name_extension(block_usage_filename.c_str(), ".txt")) {
186+
fmt = ClusteredNetlistStats::OutputFormat::HumanReadable;
187+
} else {
188+
VPR_FATAL_ERROR(VPR_ERROR_PACK, "Unknown extension on output %s", block_usage_filename.c_str());
189+
}
190+
191+
std::fstream fp;
192+
193+
fp.open(block_usage_filename, std::fstream::out | std::fstream::trunc);
194+
stats.write(fmt, fp);
195+
fp.close();
196+
}
110197
}
111198

112199
static void ShowAnnealSched(const t_annealing_sched& AnnealSched) {

0 commit comments

Comments
 (0)