Skip to content

Commit 372f0dc

Browse files
authored
Merge pull request #2749 from AlexandreSinger/feature-ap-read-atom-netlist
[AP] Added Ability to Read The Atom Netlist
2 parents 13f37a6 + 86f8af1 commit 372f0dc

File tree

5 files changed

+234
-6
lines changed

5 files changed

+234
-6
lines changed

vpr/src/analytical_place/analytical_placement_flow.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
*/
77

88
#include "analytical_placement_flow.h"
9+
#include "ap_netlist.h"
910
#include "atom_netlist.h"
11+
#include "gen_ap_netlist_from_atoms.h"
1012
#include "globals.h"
1113
#include "prepack.h"
14+
#include "user_place_constraints.h"
1215
#include "vpr_context.h"
1316
#include "vpr_error.h"
1417
#include "vpr_types.h"
@@ -22,11 +25,18 @@ void run_analytical_placement_flow(t_vpr_setup& vpr_setup) {
2225
// The global state used/modified by this flow.
2326
const AtomNetlist& atom_nlist = g_vpr_ctx.atom().nlist;
2427
const DeviceContext& device_ctx = g_vpr_ctx.device();
28+
const UserPlaceConstraints& constraints = g_vpr_ctx.floorplanning().constraints;
2529

2630
// Run the prepacker
2731
Prepacker prepacker;
2832
prepacker.init(atom_nlist, device_ctx.logical_block_types);
2933

34+
// Create the ap netlist from the atom netlist using the result from the
35+
// prepacker.
36+
APNetlist ap_netlist = gen_ap_netlist_from_atoms(atom_nlist,
37+
prepacker,
38+
constraints);
39+
3040
// AP is currently under-construction. Fail gracefully just in case this
3141
// is somehow being called.
3242
VPR_FATAL_ERROR(VPR_ERROR_AP,

vpr/src/analytical_place/ap_netlist.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,20 @@ APBlockId APNetlist::create_block(const std::string& name, const t_pack_molecule
5858
void APNetlist::set_block_loc(const APBlockId id, const APFixedBlockLoc& loc) {
5959
VTR_ASSERT_SAFE(valid_block_id(id));
6060

61-
// Check that the location is fixed, if all values are -1 then it is not fixed.
62-
if (loc.x == -1 && loc.y == -1 && loc.sub_tile == -1 && loc.layer_num == -1)
61+
// Check that the location is fixed; if all dims are unfixed then it is not fixed.
62+
if (loc.x == APFixedBlockLoc::UNFIXED_DIM &&
63+
loc.y == APFixedBlockLoc::UNFIXED_DIM &&
64+
loc.sub_tile == APFixedBlockLoc::UNFIXED_DIM &&
65+
loc.layer_num == APFixedBlockLoc::UNFIXED_DIM)
6366
return;
6467

68+
// Ensure that the block is fixed to a single position on the grid (x, y, layer).
69+
// sub-tile is allowed to be unfixed.
70+
VTR_ASSERT(loc.x != APFixedBlockLoc::UNFIXED_DIM &&
71+
loc.y != APFixedBlockLoc::UNFIXED_DIM &&
72+
loc.layer_num != APFixedBlockLoc::UNFIXED_DIM &&
73+
"AP: Currently, AP assumes block is locked down to a single position on the device grid.");
74+
6575
block_locs_[id] = loc;
6676
block_mobilities_[id] = APBlockMobility::FIXED;
6777
}

vpr/src/analytical_place/ap_netlist.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ class t_pack_molecule;
3636
* -1 implies that the block is not fixed in that dimension.
3737
*/
3838
struct APFixedBlockLoc {
39-
int x = -1;
40-
int y = -1;
41-
int layer_num = -1;
42-
int sub_tile = -1;
39+
// Value that represents an unfixed dimension.
40+
static constexpr int UNFIXED_DIM = -1;
41+
// The dimensions to fix.
42+
int x = UNFIXED_DIM;
43+
int y = UNFIXED_DIM;
44+
int layer_num = UNFIXED_DIM;
45+
int sub_tile = UNFIXED_DIM;
4346
};
4447

4548
/**
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/**
2+
* @file
3+
* @author Alex Singer
4+
* @date September 2024
5+
* @brief Definition of the gen_ap_netlist_from_atoms method, used for
6+
* generating an APNetlist from the results of the Prepacker.
7+
*/
8+
9+
#include "gen_ap_netlist_from_atoms.h"
10+
#include "ap_netlist.h"
11+
#include "atom_netlist.h"
12+
#include "atom_netlist_fwd.h"
13+
#include "netlist_fwd.h"
14+
#include "partition.h"
15+
#include "partition_region.h"
16+
#include "prepack.h"
17+
#include "region.h"
18+
#include "user_place_constraints.h"
19+
#include "vpr_types.h"
20+
#include "vtr_assert.h"
21+
#include "vtr_geometry.h"
22+
#include "vtr_time.h"
23+
#include <unordered_set>
24+
#include <vector>
25+
26+
APNetlist gen_ap_netlist_from_atoms(const AtomNetlist& atom_netlist,
27+
const Prepacker& prepacker,
28+
const UserPlaceConstraints& constraints) {
29+
// Create a scoped timer for reading the atom netlist.
30+
vtr::ScopedStartFinishTimer timer("Read Atom Netlist to AP Netlist");
31+
32+
// FIXME: What to do about the name and ID in this context? For now just
33+
// using empty strings.
34+
APNetlist ap_netlist;
35+
36+
// Add the APBlocks based on the atom block molecules. This essentially
37+
// creates supernodes.
38+
// Each AP block has the name of the first atom block in the molecule.
39+
// Each port is named "<atom_blk_name>_<atom_port_name>"
40+
// Each net has the exact same name as in the atom netlist
41+
for (AtomBlockId atom_blk_id : atom_netlist.blocks()) {
42+
// Get the molecule of this block
43+
t_pack_molecule* mol = prepacker.get_atom_molecule(atom_blk_id);
44+
// Create the AP block (if not already done)
45+
const std::string& first_blk_name = atom_netlist.block_name(mol->atom_block_ids[0]);
46+
APBlockId ap_blk_id = ap_netlist.create_block(first_blk_name, mol);
47+
// Add the ports and pins of this block to the supernode
48+
for (AtomPortId atom_port_id : atom_netlist.block_ports(atom_blk_id)) {
49+
BitIndex port_width = atom_netlist.port_width(atom_port_id);
50+
PortType port_type = atom_netlist.port_type(atom_port_id);
51+
const std::string& port_name = atom_netlist.port_name(atom_port_id);
52+
const std::string& block_name = atom_netlist.block_name(atom_blk_id);
53+
// The port name needs to be made unique for the supernode (two
54+
// joined blocks may have the same port name)
55+
std::string ap_port_name = block_name + "_" + port_name;
56+
APPortId ap_port_id = ap_netlist.create_port(ap_blk_id, ap_port_name, port_width, port_type);
57+
for (AtomPinId atom_pin_id : atom_netlist.port_pins(atom_port_id)) {
58+
BitIndex port_bit = atom_netlist.pin_port_bit(atom_pin_id);
59+
PinType pin_type = atom_netlist.pin_type(atom_pin_id);
60+
bool pin_is_const = atom_netlist.pin_is_constant(atom_pin_id);
61+
AtomNetId pin_atom_net_id = atom_netlist.pin_net(atom_pin_id);
62+
const std::string& pin_atom_net_name = atom_netlist.net_name(pin_atom_net_id);
63+
APNetId pin_ap_net_id = ap_netlist.create_net(pin_atom_net_name);
64+
ap_netlist.create_pin(ap_port_id, port_bit, pin_ap_net_id, pin_type, pin_is_const);
65+
}
66+
}
67+
}
68+
69+
// Fix the block locations given by the VPR constraints
70+
for (APBlockId ap_blk_id : ap_netlist.blocks()) {
71+
const t_pack_molecule* mol = ap_netlist.block_molecule(ap_blk_id);
72+
for (AtomBlockId mol_atom_blk_id : mol->atom_block_ids) {
73+
PartitionId part_id = constraints.get_atom_partition(mol_atom_blk_id);
74+
if (!part_id.is_valid())
75+
continue;
76+
// We should not fix a block twice. This would imply that a molecule
77+
// contains two fixed blocks. This would only make sense if the blocks
78+
// were fixed to the same location. I am not sure if that is even
79+
// possible.
80+
VTR_ASSERT(ap_netlist.block_mobility(ap_blk_id) == APBlockMobility::MOVEABLE);
81+
// Get the partition region.
82+
const PartitionRegion& partition_pr = constraints.get_partition_pr(part_id);
83+
// TODO: Either handle the union of legal locations or turn into a
84+
// proper error.
85+
VTR_ASSERT(partition_pr.get_regions().size() == 1 && "AP: Each partition should contain only one region for AP right now.");
86+
const Region& region = partition_pr.get_regions()[0];
87+
// Get the x and y.
88+
const vtr::Rect<int>& region_rect = region.get_rect();
89+
VTR_ASSERT(region_rect.xmin() == region_rect.xmax() && "AP: Expect each region to be a single point in x!");
90+
VTR_ASSERT(region_rect.ymin() == region_rect.ymax() && "AP: Expect each region to be a single point in y!");
91+
int blk_x_loc = region_rect.xmin();
92+
int blk_y_loc = region_rect.ymin();
93+
// Get the layer.
94+
VTR_ASSERT(region.get_layer_range().first == region.get_layer_range().second && "AP: Expect each region to be a single point in layer!");
95+
int blk_layer_num = region.get_layer_range().first;
96+
// Get the sub_tile (if fixed).
97+
int blk_sub_tile = APFixedBlockLoc::UNFIXED_DIM;
98+
if (region.get_sub_tile() != NO_SUBTILE)
99+
blk_sub_tile = region.get_sub_tile();
100+
// Set the fixed block location.
101+
APFixedBlockLoc loc = {blk_x_loc, blk_y_loc, blk_layer_num, blk_sub_tile};
102+
ap_netlist.set_block_loc(ap_blk_id, loc);
103+
}
104+
}
105+
106+
// Cleanup the netlist by removing undesirable nets.
107+
// Currently undesirable nets are nets that are:
108+
// - ignored for placement
109+
// - a global net
110+
// - connected to 1 or fewer unique blocks
111+
// - connected to only fixed blocks
112+
// TODO: Allow the user to pass a threshold so we can remove high-fanout nets.
113+
auto remove_net = [&](APNetId net_id) {
114+
// Remove all pins associated with this net
115+
for (APPinId pin_id : ap_netlist.net_pins(net_id))
116+
ap_netlist.remove_pin(pin_id);
117+
// Remove the net
118+
ap_netlist.remove_net(net_id);
119+
};
120+
for (APNetId ap_net_id : ap_netlist.nets()) {
121+
// Is the net ignored for placement, if so remove
122+
const std::string& net_name = ap_netlist.net_name(ap_net_id);
123+
AtomNetId atom_net_id = atom_netlist.find_net(net_name);
124+
VTR_ASSERT(atom_net_id.is_valid());
125+
if (atom_netlist.net_is_ignored(atom_net_id)) {
126+
remove_net(ap_net_id);
127+
continue;
128+
}
129+
// Is the net global, if so remove
130+
if (atom_netlist.net_is_global(atom_net_id)) {
131+
remove_net(ap_net_id);
132+
continue;
133+
}
134+
// Get the unique blocks connectioned to this net
135+
std::unordered_set<APBlockId> net_blocks;
136+
for (APPinId ap_pin_id : ap_netlist.net_pins(ap_net_id)) {
137+
net_blocks.insert(ap_netlist.pin_block(ap_pin_id));
138+
}
139+
// If connected to 1 or fewer unique blocks, remove
140+
if (net_blocks.size() <= 1) {
141+
remove_net(ap_net_id);
142+
continue;
143+
}
144+
// If all the connected blocks are fixed, remove
145+
bool is_all_fixed = true;
146+
for (APBlockId ap_blk_id : net_blocks) {
147+
if (ap_netlist.block_mobility(ap_blk_id) == APBlockMobility::MOVEABLE) {
148+
is_all_fixed = false;
149+
break;
150+
}
151+
}
152+
if (is_all_fixed) {
153+
remove_net(ap_net_id);
154+
continue;
155+
}
156+
}
157+
ap_netlist.remove_and_compress();
158+
159+
// TODO: Should we cleanup the blocks? For example if there is no path
160+
// from a fixed block to a given moveable block, then that moveable
161+
// block can be removed (since it can literally go anywhere).
162+
// - This would be useful to detect and use throughout; but may cause some
163+
// issues if we just remove them. When and where will they eventually
164+
// be placed?
165+
// - Perhaps we can add a flag in the netlist to each of these blocks and
166+
// during the solving stage we can ignore them.
167+
// For now, leave this alone; but should check if the matrix becomes
168+
// ill-formed and causes problems.
169+
170+
// Verify that the netlist was created correctly.
171+
VTR_ASSERT(ap_netlist.verify());
172+
173+
return ap_netlist;
174+
}
175+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @file
3+
* @author Alex Singer
4+
* @date September 2024
5+
* @brief Declaration of the gen_ap_netlist_from_atoms function which uses the
6+
* results of the prepacker to generate an APNetlist.
7+
*/
8+
9+
#pragma once
10+
11+
// Forward declarations
12+
class APNetlist;
13+
class AtomNetlist;
14+
class Prepacker;
15+
class UserPlaceConstraints;
16+
17+
/**
18+
* @brief Use the results from prepacking the atom netlist to generate an APNetlist.
19+
*
20+
* @param atom_netlist The atom netlist for the input design.
21+
* @param prepacker The prepacker, initialized on the provided atom netlist.
22+
* @param constraints The placement constraints on the Atom blocks, provided
23+
* by the user.
24+
*
25+
* @return An APNetlist object, generated from the prepacker results.
26+
*/
27+
APNetlist gen_ap_netlist_from_atoms(const AtomNetlist& atom_netlist,
28+
const Prepacker& prepacker,
29+
const UserPlaceConstraints& constraints);
30+

0 commit comments

Comments
 (0)