Skip to content

Commit 465c716

Browse files
authored
Merge pull request #8885 from braydenlouie/tapcell
ram: added tapcell placement and spacing
2 parents 7039789 + e900c0c commit 465c716

File tree

10 files changed

+3086
-2997
lines changed

10 files changed

+3086
-2997
lines changed

src/ram/include/ram/ram.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ class RamGen
4646
int read_ports,
4747
odb::dbMaster* storage_cell,
4848
odb::dbMaster* tristate_cell,
49-
odb::dbMaster* inv_cell);
49+
odb::dbMaster* inv_cell,
50+
odb::dbMaster* tapcell,
51+
int max_tap_dist);
5052

5153
private:
5254
void findMasters();
@@ -84,6 +86,8 @@ class RamGen
8486

8587
odb::dbBTerm* makeBTerm(const std::string& name, odb::dbIoType io_type);
8688

89+
std::unique_ptr<Layout> generateTapColumn(int word_count, int tapcell_col);
90+
8791
std::unique_ptr<Cell> makeDecoder(const std::string& prefix,
8892
int num_word,
8993
int read_ports,
@@ -104,6 +108,7 @@ class RamGen
104108
odb::dbMaster* and2_cell_{nullptr};
105109
odb::dbMaster* clock_gate_cell_{nullptr};
106110
odb::dbMaster* buffer_cell_{nullptr};
111+
odb::dbMaster* tapcell_{nullptr};
107112
};
108113

109114
} // namespace ram

src/ram/src/layout.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ void Cell::addInst(dbInst* inst)
3434

3535
void Cell::cellInit()
3636
{
37+
width_ = 0;
38+
height_ = 0;
3739
for (auto& inst : insts_) {
3840
Rect inst_box = inst->getBBox()->getBox();
3941
width_ += inst_box.dx();
@@ -166,6 +168,18 @@ void Grid::addLayout(std::unique_ptr<Layout> layout)
166168
layouts_.push_back(std::move(layout));
167169
}
168170

171+
bool Grid::insertLayout(std::unique_ptr<Layout> layout, int index)
172+
{
173+
if (index == layouts_.size()) {
174+
layouts_.push_back(std::move(layout));
175+
} else if (index < layouts_.size()) {
176+
layouts_.insert(layouts_.begin() + index, std::move(layout));
177+
} else if (index > layouts_.size()) {
178+
return false;
179+
}
180+
return true;
181+
}
182+
169183
void Grid::addCell(std::unique_ptr<Cell> cell, int track)
170184
{
171185
if (track >= layouts_.size()) {
@@ -226,6 +240,16 @@ int Grid::numLayouts() const
226240
return layouts_.size();
227241
}
228242

243+
int Grid::getLayoutWidth(int index) const
244+
{
245+
return layouts_[index]->getWidth();
246+
}
247+
248+
int Grid::getLayoutHeight(int index) const
249+
{
250+
return layouts_[index]->getHeight();
251+
}
252+
229253
int Grid::getRowWidth() const
230254
{
231255
int row_width = 0;

src/ram/src/layout.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class Grid
8282

8383
void addLayout(std::unique_ptr<Layout> layout);
8484

85+
bool insertLayout(std::unique_ptr<Layout> layout, int index);
86+
8587
void addCell(std::unique_ptr<Cell> cell, int track);
8688

8789
void gridInit();
@@ -96,6 +98,10 @@ class Grid
9698

9799
int numLayouts() const;
98100

101+
int getLayoutWidth(int index) const;
102+
103+
int getLayoutHeight(int index) const;
104+
99105
int getRowWidth() const;
100106

101107
private:

src/ram/src/ram.cpp

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,22 @@ void RamGen::makeCellByte(Grid& ram_grid,
173173
ram_grid.addCell(std::move(sel_cell), (byte_number * 9) + 8);
174174
}
175175

176+
std::unique_ptr<Layout> RamGen::generateTapColumn(const int word_count,
177+
const int tapcell_col)
178+
{
179+
auto tapcell_layout = std::make_unique<Layout>(odb::vertical);
180+
for (int i = 0; i <= word_count; ++i) {
181+
auto tapcell_cell = std::make_unique<Cell>();
182+
makeCellInst(tapcell_cell.get(),
183+
"tapcell",
184+
fmt::format("cell{}_{}", tapcell_col, i),
185+
tapcell_,
186+
{});
187+
tapcell_layout->addCell(std::move(tapcell_cell));
188+
}
189+
return tapcell_layout;
190+
}
191+
176192
std::unique_ptr<Cell> RamGen::makeDecoder(
177193
const std::string& prefix,
178194
const int num_word,
@@ -371,7 +387,9 @@ void RamGen::generate(const int bytes_per_word,
371387
const int read_ports,
372388
dbMaster* storage_cell,
373389
dbMaster* tristate_cell,
374-
dbMaster* inv_cell)
390+
dbMaster* inv_cell,
391+
dbMaster* tapcell,
392+
int max_tap_dist)
375393
{
376394
const int bits_per_word = bytes_per_word * 8;
377395
const std::string ram_name
@@ -382,6 +400,7 @@ void RamGen::generate(const int bytes_per_word,
382400
storage_cell_ = storage_cell;
383401
tristate_cell_ = tristate_cell;
384402
inv_cell_ = inv_cell;
403+
tapcell_ = tapcell;
385404
and2_cell_ = nullptr;
386405
clock_gate_cell_ = nullptr;
387406
buffer_cell_ = nullptr;
@@ -503,40 +522,40 @@ void RamGen::generate(const int bytes_per_word,
503522
}
504523

505524
for (int bit = 0; bit < 8; ++bit) {
506-
auto buffer_cell = std::make_unique<Cell>();
507-
makeCellInst(buffer_cell.get(),
525+
auto buffer_grid_cell = std::make_unique<Cell>();
526+
makeCellInst(buffer_grid_cell.get(),
508527
"buffer",
509528
fmt::format("in[{}]", bit),
510529
buffer_cell_,
511530
{{"A", D_bTerms[bit]->getNet()}, {"X", D_nets[bit]}});
512-
ram_grid.addCell(std::move(buffer_cell), bit);
531+
ram_grid.addCell(std::move(buffer_grid_cell), bit);
513532
}
514533
}
515534

516535
auto cell_inv_layout = std::make_unique<Layout>(odb::vertical);
517536
// check for AND gate, specific case for 2 words
518537
if (num_inputs > 1) {
519538
for (int i = num_inputs - 1; i >= 0; --i) {
520-
auto inv_cell = std::make_unique<Cell>();
521-
makeCellInst(inv_cell.get(),
539+
auto inv_grid_cell = std::make_unique<Cell>();
540+
makeCellInst(inv_grid_cell.get(),
522541
"decoder",
523542
fmt::format("inv_{}", i),
524543
inv_cell_,
525544
{{"A", addr[i]->getNet()}, {"Y", inv_addr[i]}});
526-
cell_inv_layout->addCell(std::move(inv_cell));
545+
cell_inv_layout->addCell(std::move(inv_grid_cell));
527546
for (int filler_count = 0; filler_count < num_inputs - 1;
528547
++filler_count) {
529548
cell_inv_layout->addCell(nullptr);
530549
}
531550
}
532551
} else {
533-
auto inv_cell = std::make_unique<Cell>();
534-
makeCellInst(inv_cell.get(),
552+
auto inv_grid_cell = std::make_unique<Cell>();
553+
makeCellInst(inv_grid_cell.get(),
535554
"decoder",
536555
fmt::format("inv_{}", 0),
537556
inv_cell_,
538557
{{"A", addr[0]->getNet()}, {"Y", inv_addr[0]}});
539-
cell_inv_layout->addCell(std::move(inv_cell));
558+
cell_inv_layout->addCell(std::move(inv_grid_cell));
540559
}
541560

542561
ram_grid.addLayout(std::move(cell_inv_layout));
@@ -546,6 +565,38 @@ void RamGen::generate(const int bytes_per_word,
546565
ram_grid.setOrigin(ram_origin);
547566
ram_grid.gridInit();
548567

568+
if (tapcell_) {
569+
// max tap distance specified is greater than the length of ram
570+
if (ram_grid.getRowWidth() <= max_tap_dist) {
571+
auto tapcell_layout = generateTapColumn(word_count, 0);
572+
ram_grid.insertLayout(std::move(tapcell_layout), 0);
573+
} else {
574+
// needed this calculation so first cells have right distance
575+
int nearest_tap
576+
= (max_tap_dist / ram_grid.getWidth()) * ram_grid.getLayoutWidth(0);
577+
int tapcell_count = 0;
578+
// iterates through each of the columns
579+
for (int col = 0; col < ram_grid.numLayouts(); ++col) {
580+
if (nearest_tap + ram_grid.getLayoutWidth(col) >= max_tap_dist) {
581+
// if the nearest_tap is too far, generate tap column
582+
auto tapcell_layout = generateTapColumn(word_count, tapcell_count);
583+
ram_grid.insertLayout(std::move(tapcell_layout), col);
584+
++col; // col adjustment after insertion
585+
nearest_tap = 0;
586+
++tapcell_count;
587+
}
588+
nearest_tap += ram_grid.getLayoutWidth(col);
589+
}
590+
// check for last column in the grid
591+
if (nearest_tap >= max_tap_dist) {
592+
auto tapcell_layout = generateTapColumn(word_count, tapcell_count);
593+
ram_grid.addLayout(std::move(tapcell_layout));
594+
}
595+
}
596+
}
597+
598+
ram_grid.gridInit();
599+
549600
auto db_libs = db_->getLibs().begin();
550601
auto db_sites = *(db_libs->getSites().begin());
551602
auto sites_width = db_sites->getWidth();

src/ram/src/ram.i

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ generate_ram_netlist_cmd(int bytes_per_word,
2020
const char* storage_cell_name,
2121
const char* tristate_cell_name,
2222
const char* inv_cell_name,
23-
const int read_ports)
23+
const int read_ports,
24+
const char* tapcell_name,
25+
const int max_tap_dist)
2426
{
2527
auto* app = ord::OpenRoad::openRoad();
2628
auto* ram_gen = app->getRamGen();
@@ -58,8 +60,21 @@ generate_ram_netlist_cmd(int bytes_per_word,
5860
inv_cell_name);
5961
}
6062
}
63+
64+
odb::dbMaster* tapcell = nullptr;
65+
if (tapcell_name[0] != '\0') {
66+
tapcell = db->findMaster(tapcell_name);
67+
if (!tapcell) {
68+
app->getLogger()->error(utl::RAM,
69+
19,
70+
"Tapcell {} can't be found",
71+
tapcell_name);
72+
}
73+
}
74+
6175
ram_gen->generate(bytes_per_word, word_count, read_ports,
62-
storage_cell, tristate_cell, inv_cell);
76+
storage_cell, tristate_cell, inv_cell, tapcell,
77+
max_tap_dist);
6378
}
6479

6580
} //namespace_ram

src/ram/src/ram.tcl

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ sta::define_cmd_args "generate_ram_netlist" {-bytes_per_word bits
66
[-storage_cell name]
77
[-tristate_cell name]
88
[-inv_cell name]
9-
[-read_ports count]}
9+
[-read_ports count]
10+
[-tapcell name]
11+
[-max_tap_dist value]}
1012

1113
proc generate_ram_netlist { args } {
1214
sta::parse_key_args "generate_ram_netlist" args \
13-
keys {-bytes_per_word -word_count -storage_cell -tristate_cell -inv_cell
14-
-read_ports } flags {}
15+
keys { -bytes_per_word -word_count -storage_cell -tristate_cell -inv_cell
16+
-read_ports -tapcell -max_tap_dist } flags {}
1517

1618
if { [info exists keys(-bytes_per_word)] } {
1719
set bytes_per_word $keys(-bytes_per_word)
@@ -45,8 +47,23 @@ proc generate_ram_netlist { args } {
4547
set read_ports $keys(-read_ports)
4648
}
4749

50+
set tapcell ""
51+
set max_tap_dist 0
52+
if { [info exists keys(-tapcell)] } {
53+
if { [info exists keys(-max_tap_dist)] } {
54+
set max_tap_dist $keys(-max_tap_dist)
55+
set max_tap_dist [ord::microns_to_dbu $max_tap_dist]
56+
} else {
57+
utl::error RAM 21 "The -max_tap_dist argument must be specified with tapcell."
58+
}
59+
set tapcell $keys(-tapcell)
60+
} else {
61+
utl::warn RAM 22 "No tapcell is specified.
62+
The generated layout may not pass Design Rule Checks."
63+
}
64+
4865
ram::generate_ram_netlist_cmd $bytes_per_word $word_count $storage_cell \
49-
$tristate_cell $inv_cell $read_ports
66+
$tristate_cell $inv_cell $read_ports $tapcell $max_tap_dist
5067
}
5168

5269
sta::define_cmd_args "generate_ram" {-bytes_per_word bits
@@ -60,13 +77,16 @@ sta::define_cmd_args "generate_ram" {-bytes_per_word bits
6077
-routing_layer config
6178
-ver_layer config
6279
-hor_layer config
63-
-filler_cells fillers}
80+
-filler_cells fillers
81+
[-tapcell name]
82+
[-max_tap_dist value]}
6483

6584
# user arguments for generate ram arguments
6685
proc generate_ram { args } {
6786
sta::parse_key_args "generate_ram" args \
68-
keys {-bytes_per_word -word_count -storage_cell -tristate_cell -inv_cell -read_ports
69-
-power_pin -ground_pin -routing_layer -ver_layer -hor_layer -filler_cells} flags {}
87+
keys { -bytes_per_word -word_count -storage_cell -tristate_cell -inv_cell -read_ports
88+
-power_pin -ground_pin -routing_layer -ver_layer -hor_layer -filler_cells
89+
-tapcell -max_tap_dist} flags {}
7090

7191
sta::check_argc_eq0 "generate_ram" $args
7292

@@ -95,6 +115,14 @@ proc generate_ram { args } {
95115
lappend ram_netlist_args -inv_cell $keys(-inv_cell)
96116
}
97117

118+
if { [info exists keys(-tapcell)] } {
119+
lappend ram_netlist_args -tapcell $keys(-tapcell)
120+
}
121+
122+
if { [info exists keys(-max_tap_dist)] } {
123+
lappend ram_netlist_args -max_tap_dist $keys(-max_tap_dist)
124+
}
125+
98126
generate_ram_netlist {*}$ram_netlist_args
99127

100128
ord::design_created

0 commit comments

Comments
 (0)