Skip to content

Commit 1c5263d

Browse files
authored
Merge pull request verilog-to-routing#349 from SymbiFlow/remove-wip-equivalent-sites
Remove equivalent sites branch
2 parents b4ac6ad + 0a26157 commit 1c5263d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+870
-318
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ vtr_flow/arch/titan/*.xml
3535
vtr_flow/benchmarks/titan_blif/*.blif
3636
vtr_flow/benchmarks/titan_other_blif/*.blif
3737

38+
39+
#
40+
# ISPD benchmarks
41+
#
42+
# We ignore the ISPD netlists because of thier large size.
43+
#
44+
ispd_benchmarks_vtr*.tar.gz
45+
vtr_flow/benchmarks/ispd_blif/*.blif
46+
3847
#
3948
# Cloud9 Directory
4049
#

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ add_custom_target(get_titan_benchmarks
294294
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
295295
COMMENT "Downloading (~1GB) and extracting Titan benchmarks (~10GB) into VTR source tree.")
296296

297+
#
298+
# ISPD Benchmarks
299+
#
300+
add_custom_target(get_ispd_benchmarks
301+
COMMAND ./vtr_flow/scripts/download_ispd.py --vtr_flow_dir ./vtr_flow
302+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
303+
COMMENT "Downloading (~50MB) and extracting Titan benchmarks (~0.5GB) into VTR source tree.")
304+
297305
#
298306
# Unit Testing
299307
#

vpr/scripts/compare_timing_reports.py

100644100755
File mode changed.

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
365365
RouterOpts->congested_routing_iteration_threshold_frac = Options.congested_routing_iteration_threshold_frac;
366366
RouterOpts->route_bb_update = Options.route_bb_update;
367367
RouterOpts->clock_modeling = Options.clock_modeling;
368+
RouterOpts->two_stage_clock_routing = Options.two_stage_clock_routing;
368369
RouterOpts->high_fanout_threshold = Options.router_high_fanout_threshold;
369370
RouterOpts->router_debug_net = Options.router_debug_net;
370371
RouterOpts->router_debug_sink_rr = Options.router_debug_sink_rr;

vpr/src/base/atom_netlist_utils.cpp

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ bool is_buffer_lut(const AtomNetlist& netlist, const AtomBlockId blk);
3434
bool is_removable_block(const AtomNetlist& netlist, const AtomBlockId blk, std::string* reason = nullptr);
3535
bool is_removable_input(const AtomNetlist& netlist, const AtomBlockId blk, std::string* reason = nullptr);
3636
bool is_removable_output(const AtomNetlist& netlist, const AtomBlockId blk, std::string* reason = nullptr);
37-
void remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity);
37+
38+
//Attempts to remove the specified buffer LUT blk from the netlist. Returns true if successful.
39+
bool remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity);
3840

3941
std::string make_unconn(size_t& unconn_count, PinType type);
4042
void cube_to_minterms_recurr(std::vector<vtr::LogicValue> cube, std::vector<size_t>& minterms);
@@ -663,27 +665,19 @@ void absorb_buffer_luts(AtomNetlist& netlist, int verbosity) {
663665
//we then remove those luts, replacing the net's they drove with the inputs to the
664666
//buffer lut
665667

666-
//Find buffer luts
667-
auto buffer_luts = identify_buffer_luts(netlist);
668-
669-
VTR_LOGV(verbosity > 0, "Absorbing %zu LUT buffers\n", buffer_luts.size());
668+
size_t removed_buffer_count = 0;
670669

671670
//Remove the buffer luts
672-
for (auto blk : buffer_luts) {
673-
remove_buffer_lut(netlist, blk, verbosity);
674-
}
675-
676-
//TODO: absorb inverter LUTs?
677-
}
678-
679-
std::vector<AtomBlockId> identify_buffer_luts(const AtomNetlist& netlist) {
680-
std::vector<AtomBlockId> buffer_luts;
681671
for (auto blk : netlist.blocks()) {
682672
if (is_buffer_lut(netlist, blk)) {
683-
buffer_luts.push_back(blk);
673+
if (remove_buffer_lut(netlist, blk, verbosity)) {
674+
++removed_buffer_count;
675+
}
684676
}
685677
}
686-
return buffer_luts;
678+
VTR_LOGV(verbosity > 0, "Absorbed %zu LUT buffers\n", removed_buffer_count);
679+
680+
//TODO: absorb inverter LUTs?
687681
}
688682

689683
bool is_buffer_lut(const AtomNetlist& netlist, const AtomBlockId blk) {
@@ -747,7 +741,7 @@ bool is_buffer_lut(const AtomNetlist& netlist, const AtomBlockId blk) {
747741
return false;
748742
}
749743

750-
void remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity) {
744+
bool remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity) {
751745
//General net connectivity, numbers equal pin ids
752746
//
753747
// 1 in 2 ----- m+1 out
@@ -796,8 +790,16 @@ void remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity) {
796790
auto input_net = netlist.pin_net(input_pin);
797791
auto output_net = netlist.pin_net(output_pin);
798792

793+
VTR_LOGV_WARN(verbosity > 1, "Attempting to remove buffer '%s' (%s) from net '%s' to net '%s'\n", netlist.block_name(blk).c_str(), netlist.block_model(blk)->name, netlist.net_name(input_net).c_str(), netlist.net_name(output_net).c_str());
794+
799795
//Collect the new driver and sink pins
800796
AtomPinId new_driver = netlist.net_driver(input_net);
797+
798+
if (!new_driver) {
799+
VTR_LOGV_WARN(verbosity > 2, "Buffer '%s' has no input and will not be absorbed (left to be swept)\n", netlist.block_name(blk).c_str(), netlist.block_model(blk)->name, netlist.net_name(input_net).c_str(), netlist.net_name(output_net).c_str());
800+
return false; //Dangling/undriven input, leave buffer to be swept
801+
}
802+
801803
VTR_ASSERT(netlist.pin_type(new_driver) == PinType::DRIVER);
802804

803805
std::vector<AtomPinId> new_sinks;
@@ -823,38 +825,45 @@ void remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity) {
823825
// Note that the driver can only (potentially) be an INPAD, and the sinks only (potentially) OUTPADs
824826
AtomBlockType driver_block_type = netlist.block_type(netlist.pin_block(new_driver));
825827
bool driver_is_pi = (driver_block_type == AtomBlockType::INPAD);
826-
bool po_in_sinks = std::any_of(new_sinks.begin(), new_sinks.end(),
827-
[&](AtomPinId pin_id) {
828-
VTR_ASSERT(netlist.pin_type(pin_id) == PinType::SINK);
829-
AtomBlockId blk_id = netlist.pin_block(pin_id);
830-
return netlist.block_type(blk_id) == AtomBlockType::OUTPAD;
831-
});
828+
bool po_in_input_sinks = std::any_of(input_sinks.begin(), input_sinks.end(),
829+
[&](AtomPinId pin_id) {
830+
VTR_ASSERT(netlist.pin_type(pin_id) == PinType::SINK);
831+
AtomBlockId blk_id = netlist.pin_block(pin_id);
832+
return netlist.block_type(blk_id) == AtomBlockType::OUTPAD;
833+
});
834+
bool po_in_output_sinks = std::any_of(output_sinks.begin(), output_sinks.end(),
835+
[&](AtomPinId pin_id) {
836+
VTR_ASSERT(netlist.pin_type(pin_id) == PinType::SINK);
837+
AtomBlockId blk_id = netlist.pin_block(pin_id);
838+
return netlist.block_type(blk_id) == AtomBlockType::OUTPAD;
839+
});
832840

833841
std::string new_net_name;
834-
if (!driver_is_pi && !po_in_sinks) {
842+
if (!driver_is_pi && !po_in_input_sinks && !po_in_output_sinks) {
835843
//No PIs or POs, we can choose arbitarily in this case
836844
new_net_name = netlist.net_name(output_net);
837845

838-
} else if (driver_is_pi && !po_in_sinks) {
839-
//Must use the input name to perserve primary-input name
846+
} else if ((driver_is_pi || po_in_input_sinks) && !po_in_output_sinks) {
847+
//Must use the input name to perserve primary-input or primary-output name
840848
new_net_name = netlist.net_name(input_net);
841849

842-
} else if (!driver_is_pi && po_in_sinks) {
850+
} else if ((!driver_is_pi && !po_in_input_sinks) && po_in_output_sinks) {
843851
//Must use the output name to perserve primary-output name
844852
new_net_name = netlist.net_name(output_net);
845853

846854
} else {
847-
VTR_ASSERT(driver_is_pi && po_in_sinks);
848-
//This is a buffered connection from a primary input, to primary output
855+
VTR_ASSERT((driver_is_pi || po_in_input_sinks) && po_in_output_sinks);
856+
//This is a buffered connection from a primary input to primary output, or to
857+
//more than one primary output.
849858
//TODO: consider implications of removing these...
850859

851860
//Do not remove such buffers
852-
return;
861+
return false;
853862
}
854863

855864
size_t initial_input_net_pins = netlist.net_pins(input_net).size();
856865

857-
VTR_LOGV_WARN(verbosity > 1, "%s is a LUT buffer and will be absorbed\n", netlist.block_name(blk).c_str());
866+
VTR_LOGV_WARN(verbosity > 2, "%s is a LUT buffer and will be absorbed\n", netlist.block_name(blk).c_str());
858867

859868
//Remove the buffer
860869
//
@@ -868,7 +877,10 @@ void remove_buffer_lut(AtomNetlist& netlist, AtomBlockId blk, int verbosity) {
868877
netlist.remove_net(output_net);
869878

870879
//Create the new merged net
871-
netlist.add_net(new_net_name, new_driver, new_sinks);
880+
AtomNetId new_net = netlist.add_net(new_net_name, new_driver, new_sinks);
881+
882+
VTR_ASSERT(netlist.net_pins(new_net).size() == initial_input_net_pins - 1 + output_sinks.size());
883+
return true;
872884
}
873885

874886
bool is_removable_block(const AtomNetlist& netlist, const AtomBlockId blk_id, std::string* reason) {

vpr/src/base/read_options.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -918,9 +918,7 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
918918
"Specifies how constant nets (i.e. those driven to a constant\n"
919919
"value) are handled:\n"
920920
" * global: Treat constant nets as globals (not routed)\n"
921-
" * route : Treat constant nets as normal nets (routed)\n"
922-
" * dedicated_network : Build a dedicated clock network based on the\n"
923-
" clock network specified in the architecture file\n")
921+
" * route : Treat constant nets as normal nets (routed)\n")
924922
.default_value("global")
925923
.show_in(argparse::ShowIn::HELP_ONLY);
926924

@@ -930,10 +928,21 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
930928
" * ideal: Treat clock pins as ideal\n"
931929
" (i.e. no routing delays on clocks)\n"
932930
" * route: Treat the clock pins as normal nets\n"
933-
" (i.e. routed using inter-block routing)\n")
931+
" (i.e. routed using inter-block routing)\n"
932+
" * dedicated_network : Build a dedicated clock network based on the\n"
933+
" clock network specified in the architecture file\n")
934934
.default_value("ideal")
935935
.show_in(argparse::ShowIn::HELP_ONLY);
936936

937+
gen_grp.add_argument<bool, ParseOnOff>(args.two_stage_clock_routing, "--two_stage_clock_routing")
938+
.help(
939+
"Routes clock nets in two stages if using a dedicated clock network.\n"
940+
" * First stage: From the Net source to a dedicated clock network source\n"
941+
" * Second stage: From the clock network source to net sinks\n")
942+
.default_value("off")
943+
.action(argparse::Action::STORE_TRUE)
944+
.show_in(argparse::ShowIn::HELP_ONLY);
945+
937946
gen_grp.add_argument<bool, ParseOnOff>(args.exit_before_pack, "--exit_before_pack")
938947
.help("Causes VPR to exit before packing starts (useful for statistics collection)")
939948
.default_value("off")

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct t_options {
5656
argparse::ArgValue<float> target_device_utilization;
5757
argparse::ArgValue<e_constant_net_method> constant_net_method;
5858
argparse::ArgValue<e_clock_modeling> clock_modeling;
59+
argparse::ArgValue<bool> two_stage_clock_routing;
5960
argparse::ArgValue<bool> exit_before_pack;
6061
argparse::ArgValue<bool> strict_checks;
6162
argparse::ArgValue<std::string> disable_errors;

vpr/src/base/read_route.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const ch
378378
x, y, place_ctx.block_locs[bnum].loc.x, place_ctx.block_locs[bnum].loc.y);
379379
}
380380

381-
int pin_index = net_pin_tile_index(inet, pin_counter);
381+
int pin_index = net_pin_to_tile_pin_index(inet, pin_counter);
382382
if (physical_tile_type(bnum)->pin_class[pin_index] != atoi(tokens[7].c_str())) {
383383
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
384384
"The pin class %d of %lu net does not match given ",

vpr/src/base/setup_clocks.cpp

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -129,50 +129,50 @@ void setup_clock_connections(const t_arch& Arch) {
129129
for (auto clock_connection_arch : clock_connections_arch) {
130130
if (clock_connection_arch.from == "ROUTING") {
131131
clock_connections_device.emplace_back(new RoutingToClockConnection);
132-
RoutingToClockConnection* routing_to_clock = dynamic_cast<RoutingToClockConnection*>(clock_connections_device.back().get());
133-
134-
//TODO: Add error check to check that clock name and tap name exist and that only
135-
// two names are returned by the below function
136-
auto names = vtr::split(clock_connection_arch.to, ".");
137-
VTR_ASSERT_MSG(names.size() == 2, "Invalid clock name.\n");
138-
routing_to_clock->set_clock_name_to_connect_to(names[0]);
139-
routing_to_clock->set_clock_switch_point_name(names[1]);
140-
141-
routing_to_clock->set_switch_location(
142-
parse_formula(clock_connection_arch.locationx, vars),
143-
parse_formula(clock_connection_arch.locationy, vars));
144-
routing_to_clock->set_switch(clock_connection_arch.arch_switch_idx);
145-
routing_to_clock->set_fc_val(clock_connection_arch.fc);
132+
if (RoutingToClockConnection* routing_to_clock = dynamic_cast<RoutingToClockConnection*>(clock_connections_device.back().get())) {
133+
//TODO: Add error check to check that clock name and tap name exist and that only
134+
// two names are returned by the below function
135+
auto names = vtr::split(clock_connection_arch.to, ".");
136+
VTR_ASSERT_MSG(names.size() == 2, "Invalid clock name.\n");
137+
routing_to_clock->set_clock_name_to_connect_to(names[0]);
138+
routing_to_clock->set_clock_switch_point_name(names[1]);
139+
140+
routing_to_clock->set_switch_location(
141+
parse_formula(clock_connection_arch.locationx, vars),
142+
parse_formula(clock_connection_arch.locationy, vars));
143+
routing_to_clock->set_switch(clock_connection_arch.arch_switch_idx);
144+
routing_to_clock->set_fc_val(clock_connection_arch.fc);
145+
}
146146

147147
} else if (clock_connection_arch.to == "CLOCK") {
148148
clock_connections_device.emplace_back(new ClockToPinsConnection);
149-
ClockToPinsConnection* clock_to_pins = dynamic_cast<ClockToPinsConnection*>(clock_connections_device.back().get());
150-
151-
//TODO: Add error check to check that clock name and tap name exist and that only
152-
// two names are returned by the below function
153-
auto names = vtr::split(clock_connection_arch.from, ".");
154-
VTR_ASSERT_MSG(names.size() == 2, "Invalid clock name.\n");
155-
clock_to_pins->set_clock_name_to_connect_from(names[0]);
156-
clock_to_pins->set_clock_switch_point_name(names[1]);
157-
158-
clock_to_pins->set_switch(clock_connection_arch.arch_switch_idx);
159-
clock_to_pins->set_fc_val(clock_connection_arch.fc);
149+
if (ClockToPinsConnection* clock_to_pins = dynamic_cast<ClockToPinsConnection*>(clock_connections_device.back().get())) {
150+
//TODO: Add error check to check that clock name and tap name exist and that only
151+
// two names are returned by the below function
152+
auto names = vtr::split(clock_connection_arch.from, ".");
153+
VTR_ASSERT_MSG(names.size() == 2, "Invalid clock name.\n");
154+
clock_to_pins->set_clock_name_to_connect_from(names[0]);
155+
clock_to_pins->set_clock_switch_point_name(names[1]);
156+
157+
clock_to_pins->set_switch(clock_connection_arch.arch_switch_idx);
158+
clock_to_pins->set_fc_val(clock_connection_arch.fc);
159+
}
160160
} else {
161161
clock_connections_device.emplace_back(new ClockToClockConneciton);
162-
ClockToClockConneciton* clock_to_clock = dynamic_cast<ClockToClockConneciton*>(clock_connections_device.back().get());
163-
164-
//TODO: Add error check to check that clock name and tap name exist and that only
165-
// two names are returned by the below function
166-
auto to_names = vtr::split(clock_connection_arch.to, ".");
167-
auto from_names = vtr::split(clock_connection_arch.from, ".");
168-
VTR_ASSERT_MSG(to_names.size() == 2, "Invalid clock name.\n");
169-
clock_to_clock->set_to_clock_name(to_names[0]);
170-
clock_to_clock->set_to_clock_switch_point_name(to_names[1]);
171-
clock_to_clock->set_from_clock_name(from_names[0]);
172-
clock_to_clock->set_from_clock_switch_point_name(from_names[1]);
173-
174-
clock_to_clock->set_switch(clock_connection_arch.arch_switch_idx);
175-
clock_to_clock->set_fc_val(clock_connection_arch.fc);
162+
if (ClockToClockConneciton* clock_to_clock = dynamic_cast<ClockToClockConneciton*>(clock_connections_device.back().get())) {
163+
//TODO: Add error check to check that clock name and tap name exist and that only
164+
// two names are returned by the below function
165+
auto to_names = vtr::split(clock_connection_arch.to, ".");
166+
auto from_names = vtr::split(clock_connection_arch.from, ".");
167+
VTR_ASSERT_MSG(to_names.size() == 2, "Invalid clock name.\n");
168+
clock_to_clock->set_to_clock_name(to_names[0]);
169+
clock_to_clock->set_to_clock_switch_point_name(to_names[1]);
170+
clock_to_clock->set_from_clock_name(from_names[0]);
171+
clock_to_clock->set_from_clock_switch_point_name(from_names[1]);
172+
173+
clock_to_clock->set_switch(clock_connection_arch.arch_switch_idx);
174+
clock_to_clock->set_fc_val(clock_connection_arch.fc);
175+
}
176176
}
177177
}
178178
}

vpr/src/base/vpr_api.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a
216216
vpr_setup->device_layout = options->device_layout;
217217
vpr_setup->constant_net_method = options->constant_net_method;
218218
vpr_setup->clock_modeling = options->clock_modeling;
219+
vpr_setup->two_stage_clock_routing = options->two_stage_clock_routing;
219220
vpr_setup->exit_before_pack = options->exit_before_pack;
220221

221222
VTR_LOG("\n");

vpr/src/base/vpr_context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ struct DeviceContext : public Context {
171171
std::vector<std::unique_ptr<ClockNetwork>> clock_networks;
172172
std::vector<std::unique_ptr<ClockConnection>> clock_connections;
173173

174+
// rr_node idx that connects to the input of all clock network wires
175+
// Useful for two stage clock routing
176+
// XXX: currently only one place to source the clock networks so only storing
177+
// a single value
178+
int virtual_clock_network_root_idx;
179+
174180
/** Attributes for each rr_node.
175181
* key: rr_node index
176182
* value: map of <attribute_name, attribute_value>

0 commit comments

Comments
 (0)