Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions designs/gt2n/gemmini/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load("//:defs.bzl", "hightide_design")

hightide_design(
name = "gemmini",
platform = "gt2n",
verilog_files = ["//designs/src/gemmini:rtl"],
sources = {
"SDC_FILE": [":constraint.sdc"],
"FOOTPRINT_TCL": [":io.tcl"],
},
arguments = {
"CORE_UTILIZATION": "87",
"PLACE_DENSITY": "0.94",
"MAX_ROUTING_LAYER": "M11",
"MIN_CLK_ROUTING_LAYER": "M4",
"TNS_END_PERCENT": "100",
},
)
15 changes: 15 additions & 0 deletions designs/gt2n/gemmini/constraint.sdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
current_design gemmini

set clk_name clk
set clk_port_name clock
set clk_period 1450
set clk_io_pct 0.2

set clk_port [get_ports $clk_port_name]

create_clock -name $clk_name -period $clk_period $clk_port

set non_clock_inputs [lsearch -inline -all -not -exact [all_inputs] $clk_port]

set_input_delay [expr $clk_period * $clk_io_pct + 67] -clock $clk_name $non_clock_inputs
set_output_delay [expr $clk_period * $clk_io_pct] -clock $clk_name [all_outputs]
166 changes: 166 additions & 0 deletions designs/gt2n/gemmini/io.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# IO pin placement for Gemmini 16x16x2x2 systolic mesh (gt2n)
# Ported from designs/asap7/gemmini/io.tcl: same bus-grouped, evenly-spaced
# pin ordering (keeps each bus's bits contiguous per mesh row/column to
# limit wirelength/congestion), but retargeted to gt2n's IO placer layers
# and pitch instead of asap7's M4/M5. Placed edge_margin inside the die
# boundary rather than -force_to_die_boundary — see designs/gt2n/floonoc/io.tcl,
# which hit GRT-0209 "pin completely outside die" with the boundary-forced form.
#
# ── gt2n layer config (from platforms/gt2n/config.mk + lef/gt2_tech.lef) ──
#
# IO_PLACER_H = M2 (HORIZONTAL layer → left/right edge pins)
# M2: WIDTH 0.012 um, PITCH 0.024 um
# hor_offset = WIDTH/2 = 0.006 um
#
# IO_PLACER_V = M3 (VERTICAL layer → top/bottom edge pins)
# M3: WIDTH 0.014 um, PITCH 0.028 um
# ver_offset = WIDTH/2 = 0.007 um

set hor_layer M2
set ver_layer M3
set hor_offset 0.006
set hor_pitch 0.024
set ver_offset 0.007
set ver_pitch 0.028

set edge_margin 5.0 ;# distance inward from die edge (avoids GRT-0209)
set end_margin 2.0 ;# distance from corner along the edge

# ── Expand a port name into physical pin names ──
proc expand_port {name width} {
set pins {}
if {$width == 1} {
lappend pins $name
} else {
for {set b 0} {$b < $width} {incr b} {
lappend pins "${name}\[${b}\]"
}
}
return $pins
}

# ── Build ordered list of physical pin names for a 16x2 bus ──
proc bus_pins {prefix width} {
set pins {}
for {set i 0} {$i < 16} {incr i} {
for {set j 0} {$j < 2} {incr j} {
foreach p [expand_port "${prefix}_${i}_${j}" $width] {
lappend pins $p
}
}
}
return $pins
}

# ── Build ordered list for control signals (dataflow:1, propagate:1, shift:5) ──
proc ctrl_pins {prefix} {
set pins {}
for {set i 0} {$i < 16} {incr i} {
for {set j 0} {$j < 2} {incr j} {
foreach p [expand_port "${prefix}_${i}_${j}_dataflow" 1] {
lappend pins $p
}
foreach p [expand_port "${prefix}_${i}_${j}_propagate" 1] {
lappend pins $p
}
foreach p [expand_port "${prefix}_${i}_${j}_shift" 5] {
lappend pins $p
}
}
}
return $pins
}

proc snap_track {val offset pitch} {
set n [expr {round(($val - $offset) / $pitch)}]
return [expr {$offset + $n * $pitch}]
}

# ── Place pins evenly along an edge, edge_margin inside the die boundary ──
proc place_edge {edge layer pins} {
upvar edge_margin em end_margin sm
upvar hor_offset ho hor_pitch hp ver_offset vo ver_pitch vp

set n [llength $pins]
if {$n == 0} return
lassign [ord::get_die_area] lx ly ux uy

switch $edge {
left - right {
set fixed_x [expr {$edge eq "left" ? $lx + $em : $ux - $em}]
set lo [expr {$ly + $sm}]
set hi [expr {$uy - $sm}]
for {set i 0} {$i < $n} {incr i} {
set frac [expr {($i + 0.5) / double($n)}]
set raw_y [expr {$lo + $frac * ($hi - $lo)}]
set y [snap_track $raw_y $ho $hp]
place_pin -pin_name [lindex $pins $i] -layer $layer \
-location [list $fixed_x $y]
}
}
top - bottom {
set fixed_y [expr {$edge eq "top" ? $uy - $em : $ly + $em}]
set lo [expr {$lx + $sm}]
set hi [expr {$ux - $sm}]
for {set i 0} {$i < $n} {incr i} {
set frac [expr {($i + 0.5) / double($n)}]
set raw_x [expr {$lo + $frac * ($hi - $lo)}]
set x [snap_track $raw_x $vo $vp]
place_pin -pin_name [lindex $pins $i] -layer $layer \
-location [list $x $fixed_y]
}
}
}
}

# ── Assemble pin lists per edge (same bus grouping as asap7) ──

# LEFT (512 pins, M2): in_a(8b x 32), in_d(8b x 32)
set left_pins [concat \
[bus_pins io_in_a 8] \
[bus_pins io_in_d 8] \
]

# RIGHT (512 pins, M2): interleave by mesh row (i, j) so high-fanout control
# signals (io_in_id, io_out_id, io_in_valid/last, io_out_valid/last) are
# spread along the full edge instead of clustered in the vertical middle.
set right_pins {}
for {set i 0} {$i < 16} {incr i} {
for {set j 0} {$j < 2} {incr j} {
foreach p [expand_port "io_in_b_${i}_${j}" 8] { lappend right_pins $p }
foreach p [expand_port "io_in_valid_${i}_${j}" 1] { lappend right_pins $p }
foreach p [expand_port "io_in_last_${i}_${j}" 1] { lappend right_pins $p }
foreach p [expand_port "io_in_id_${i}_${j}" 2] { lappend right_pins $p }
foreach p [expand_port "io_out_valid_${i}_${j}" 1] { lappend right_pins $p }
foreach p [expand_port "io_out_id_${i}_${j}" 2] { lappend right_pins $p }
foreach p [expand_port "io_out_last_${i}_${j}" 1] { lappend right_pins $p }
}
}

# TOP (866 pins, M3): out_b(20b x 32), in_control(7b x 32), clock, reset
set top_pins [concat \
[bus_pins io_out_b 20] \
[ctrl_pins io_in_control] \
{clock reset} \
]

# BOTTOM (864 pins, M3): out_c(20b x 32), out_control(7b x 32)
set bottom_pins [concat \
[bus_pins io_out_c 20] \
[ctrl_pins io_out_control] \
]

# ── Place all pins ──
puts "Placing [llength $left_pins] pins on LEFT edge ($hor_layer)"
place_edge left $hor_layer $left_pins

puts "Placing [llength $right_pins] pins on RIGHT edge ($hor_layer)"
place_edge right $hor_layer $right_pins

puts "Placing [llength $top_pins] pins on TOP edge ($ver_layer)"
place_edge top $ver_layer $top_pins

puts "Placing [llength $bottom_pins] pins on BOTTOM edge ($ver_layer)"
place_edge bottom $ver_layer $bottom_pins

puts "Total pins placed: [expr {[llength $left_pins] + [llength $right_pins] + [llength $top_pins] + [llength $bottom_pins]}]"
17 changes: 16 additions & 1 deletion designs/src/gemmini/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,22 @@ Large macro-heavy ML accelerator with FakeRAM black-boxes for the accumulator an
### Known issues / open questions
- None.

## sky130hd
## gt2n

**Status**: finishing
**Last updated**: 2026-08-30 (commit `369d583`)

### Configuration
- `CORE_UTILIZATION = 87` (`PLACE_DENSITY = 0.94`) — much higher than the other platforms' 30-35%; unlike asap7/nangate45/sky130hd, gt2n handles this design's macro pin density well at high utilization. 40% was tried and performed far worse (timing-repair non-convergence, 3.3x cell-count blowup); 90% failed outright (GPL-0301, real GP utilization hit 103% against the 90% nominal target).
- `MAX_ROUTING_LAYER = M11`, `MIN_CLK_ROUTING_LAYER = M4`
- Clock: `1450 ps` (Fmax 689.7 MHz)
- Input delay set to standard `clk_io_pct * period` + 67 ps (357 ps vs 290 ps) to relieve hold at the IO boundary — the worst hold violations are on input port feedthrough paths, not reg to reg (which closes clean).

### Decisions
- **2026-08-30 `369d583`**: initial gt2n port. Setup closes cleanly (WNS +2.38 ps, 0 violations). Hold has 15 residual violations (worst -9.83 ps, TNS -31.85 ps). `HOLD_SLACK_MARGIN` was evaluated as an alternative to the input-delay bump but any value large enough to help (e.g. 67) caused CTS-time repair to insert tens of thousands of hold buffers, congesting detailed placement to a hard failure (DPL-0036); smaller values (5, 10) avoided the crash but didn't reliably improve on the input-delay-only result.

### Known issues / open questions
- Hold not fully closed (15 violations, worst -9.83 ps). Further input-delay tuning showed diminishing/non-monotonic returns; not yet resolved.

**Status**: finishing
**Last updated**: 2026-05-03 (commit `45b54bd1`)
Expand Down