Placing a Macro by Hand
Everything in this section so far, halo, orientation, channel spacing, has been reasoning on paper. This article turns it into a file: regfile_8x8, positioned, oriented and haloed, as you would hand it to OpenLane before placement.
Why place macros explicitly at all
OpenLane can auto-place hard macros with the same placement engine that handles standard cells. For a design with one or two macros and a floorplan you already understand, explicit placement is almost always worth the effort. You already reasoned through orientation in the previous article to get the pins facing the right way, and an automatic placer has no way to know that reasoning unless you encode it as a fixed position and orientation. Auto-placement optimises for a general objective, usually wirelength or area, not the pin-alignment reasoning you would apply by hand. For anything beyond a handful of easy, low-stakes macros, explicit placement keeps the decision in your control.
The macro placement file
OpenLane’s MACRO_PLACEMENT_CFG takes a plain text file with one line per macro instance:
<instance_name> <x> <y> <orientation>
where x and y are the macro’s lower-left corner in die coordinates (microns) and the orientation is one of the eight codes from the previous article. For regfile_8x8 (60 by 40 µm, 5 µm halo), in N so its east pins face right, at a position leaving room for its halo and a channel to whatever sits beside it:
# macro_placement.cfg
# regfile_8x8: 60 x 40 um footprint, 5 um halo (effective 70 x 50 um keep-out)
# Placed at (20, 30) in N: east-side output pins face right, toward alu_macro.
regfile_8x8 20.0 30.0 N
Wired into config.json with the halo:
{
"DESIGN_NAME": "counter8",
"MACRO_PLACEMENT_CFG": "dir::macro_placement.cfg",
"FP_MACRO_HORIZONTAL_HALO": 5,
"FP_MACRO_VERTICAL_HALO": 5
}
To be clear: counter8 as defined in this course has no hard macros. It is entirely sky130_fd_sc_hd standard cells. regfile_8x8 and alu_macro are illustrative stand-ins used across this section to teach the mechanics, foreshadowing Module 10, where a real SRAM macro is integrated into a larger design with exactly this mechanism. Section 3.5 shows what a floorplan config looks like when a design genuinely has no macros.
What OpenLane does with it
With a MACRO_PLACEMENT_CFG present, the macro is placed at its fixed location before standard cell placement begins, and its keep-out rectangle (footprint plus halo) is registered as a blockage that Module 4’s placement respects automatically:
% run_floorplan
[INFO]: Generating floorplan...
[INFO]: Placing macros from MACRO_PLACEMENT_CFG...
[INFO]: regfile_8x8 placed at (20.00, 30.00), orientation N
[INFO]: Registering macro halo blockage: (15.00, 25.00) to (85.00, 75.00)
[INFO]: Generating power distribution network...
[INFO]: Placing I/O pins...
Note the blockage coordinates: (15.00, 25.00) to (85.00, 75.00) is exactly the 70 by 50 µm keep-out from the first article of this section, anchored round the placed position. Everything reasoned by hand shows up as tool-registered geometry.
Practice Exercise
Write a MACRO_PLACEMENT_CFG line for a macro named sram_block, 90 by 50 µm, placed with its lower-left corner at (10, 10), mirrored vertically (FS) so its north-edge pins end up facing south.
Solution
sram_block 10.0 10.0 FS
The format is unchanged: instance name, x, y, orientation. FS comes directly from the requirement (mirror so north-facing pins face south), the kind of lookup the previous article introduced: match the required pin-facing outcome to the right one of the eight codes.
Every knob this module has introduced, utilisation, aspect ratio, margin, PDN, pin order, macro placement, is still scattered across separate articles. In the next section we assemble them into one real config.json and run the OpenLane floorplan stage.