Skip to content

Commit afd2740

Browse files
authored
Merge pull request #8049 from QuantamHD/pointer_tagging
dbSta: Use pointer tagging instead of getObjectType()
2 parents b97ddde + 9d3bd1f commit afd2740

File tree

7 files changed

+101
-37
lines changed

7 files changed

+101
-37
lines changed

src/dbSta/src/dbNetwork.cc

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,22 @@ ObjectId dbNetwork::getDbNwkObjectId(const dbObject* object) const
165165
return 0;
166166
}
167167

168+
// We have exactly 8 values available in the lower 3 bits of the
169+
// pointer due to these classes all having 8 byte alignment. Used
170+
// to avoid having to call into the database to figure out the
171+
// type information, which requires a lot of pointer indirection.
172+
173+
// Used to get the value of the pointer tag.
174+
static constexpr std::uintptr_t kPointerTagMask = std::uintptr_t(0b111U);
175+
176+
enum class PinPointerTags : std::uintptr_t
177+
{
178+
kNone = 0U,
179+
kDbIterm = 1U,
180+
kDbBterm = 2U,
181+
kDbModIterm = 3U,
182+
};
183+
168184
class DbLibraryIterator1 : public Iterator<Library*>
169185
{
170186
public:
@@ -470,14 +486,14 @@ bool DbNetPinIterator::hasNext()
470486
while (iitr_ != iitr_end_) {
471487
dbITerm* iterm = *iitr_;
472488
if (!iterm->getSigType().isSupply()) {
473-
next_ = reinterpret_cast<Pin*>(*iitr_);
489+
next_ = network_->dbToSta(*iitr_);
474490
++iitr_;
475491
return true;
476492
}
477493
iitr_++;
478494
}
479495
if ((mitr_ != mitr_end_) && (network_->hasHierarchy())) {
480-
next_ = reinterpret_cast<Pin*>(*mitr_);
496+
next_ = network_->dbToSta(*mitr_);
481497
++mitr_;
482498
return true;
483499
}
@@ -1212,14 +1228,20 @@ ObjectId dbNetwork::id(const Pin* pin) const
12121228

12131229
if (hierarchy_) {
12141230
// get the id for hierarchical objects using dbid.
1215-
const dbObject* obj = reinterpret_cast<const dbObject*>(pin);
1231+
std::uintptr_t tag_value
1232+
= reinterpret_cast<std::uintptr_t>(pin) & kPointerTagMask;
1233+
// Need to cast to char pin to avoid compiler error for pointer
1234+
// arithmetic on incomplete types
1235+
const char* char_pin = reinterpret_cast<const char*>(pin);
1236+
const dbObject* obj
1237+
= reinterpret_cast<const dbObject*>(char_pin - tag_value);
12161238
return getDbNwkObjectId(obj);
12171239
}
12181240
if (iterm != nullptr) {
12191241
return iterm->getId() << 1;
12201242
}
12211243
if (bterm != nullptr) {
1222-
return (bterm->getId() << 1) + 1;
1244+
return (bterm->getId() << 1) | 1U;
12231245
}
12241246
return 0;
12251247
}
@@ -2765,17 +2787,32 @@ void dbNetwork::staToDb(const Pin* pin,
27652787
iterm = nullptr;
27662788
bterm = nullptr;
27672789
moditerm = nullptr;
2768-
if (pin) {
2769-
dbObject* obj = reinterpret_cast<dbObject*>(const_cast<Pin*>(pin));
2770-
dbObjectType type = obj->getObjectType();
2771-
if (type == dbITermObj) {
2772-
iterm = static_cast<dbITerm*>(obj);
2773-
} else if (type == dbBTermObj) {
2774-
bterm = static_cast<dbBTerm*>(obj);
2775-
} else if (type == dbModITermObj) {
2776-
moditerm = static_cast<dbModITerm*>(obj);
2777-
} else {
2778-
logger_->error(ORD, 2018, "Pin is not ITerm or BTerm or modITerm.");
2790+
2791+
// Get the value of the tag
2792+
std::uintptr_t pointer_with_tag = reinterpret_cast<std::uintptr_t>(pin);
2793+
PinPointerTags tag_value
2794+
= static_cast<PinPointerTags>(pointer_with_tag & kPointerTagMask);
2795+
2796+
// Cast to char* and avoid casting an integral type to pointer type
2797+
// by doing pointer arithmetic. Compiler apparently prefer this sytle.
2798+
const char* char_pointer_pin = reinterpret_cast<const char*>(pin);
2799+
char* pointer_without_tag = const_cast<char*>(
2800+
char_pointer_pin - static_cast<std::uintptr_t>(tag_value));
2801+
2802+
if (pointer_without_tag) {
2803+
switch (tag_value) {
2804+
case PinPointerTags::kDbIterm:
2805+
iterm = reinterpret_cast<dbITerm*>(pointer_without_tag);
2806+
break;
2807+
case PinPointerTags::kDbBterm:
2808+
bterm = reinterpret_cast<dbBTerm*>(pointer_without_tag);
2809+
break;
2810+
case PinPointerTags::kDbModIterm:
2811+
moditerm = reinterpret_cast<dbModITerm*>(pointer_without_tag);
2812+
break;
2813+
case PinPointerTags::kNone:
2814+
logger_->error(ORD, 2018, "Pin is not ITerm or BTerm or modITerm.");
2815+
break;
27792816
}
27802817
}
27812818
}
@@ -2938,7 +2975,10 @@ Instance* dbNetwork::dbToSta(dbModInst* inst) const
29382975

29392976
Pin* dbNetwork::dbToSta(dbModITerm* mod_iterm) const
29402977
{
2941-
return reinterpret_cast<Pin*>(mod_iterm);
2978+
char* unaligned_pointer = reinterpret_cast<char*>(mod_iterm);
2979+
return reinterpret_cast<Pin*>(
2980+
unaligned_pointer
2981+
+ static_cast<std::uintptr_t>(PinPointerTags::kDbModIterm));
29422982
}
29432983

29442984
Net* dbNetwork::dbToSta(dbModNet* net) const
@@ -2983,12 +3023,18 @@ const Net* dbNetwork::dbToSta(const dbModNet* net) const
29833023

29843024
Pin* dbNetwork::dbToSta(dbBTerm* bterm) const
29853025
{
2986-
return reinterpret_cast<Pin*>(bterm);
3026+
char* unaligned_pointer = reinterpret_cast<char*>(bterm);
3027+
return reinterpret_cast<Pin*>(
3028+
unaligned_pointer
3029+
+ static_cast<std::uintptr_t>(PinPointerTags::kDbBterm));
29873030
}
29883031

29893032
Pin* dbNetwork::dbToSta(dbITerm* iterm) const
29903033
{
2991-
return reinterpret_cast<Pin*>(iterm);
3034+
char* unaligned_pointer = reinterpret_cast<char*>(iterm);
3035+
return reinterpret_cast<Pin*>(
3036+
unaligned_pointer
3037+
+ static_cast<std::uintptr_t>(PinPointerTags::kDbIterm));
29923038
}
29933039

29943040
Term* dbNetwork::dbToStaTerm(dbBTerm* bterm) const
@@ -3572,9 +3618,10 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin,
35723618
dest_mod_net = dest_moditerm->getModNet();
35733619
}
35743620
if (dest_mod_net) {
3575-
dbNet* dest_flat_net = flatNet((Pin*) dest_pin);
3576-
disconnectPin((Pin*) dest_pin);
3577-
connectPin((Pin*) dest_pin, (Net*) dest_flat_net, (Net*) dest_mod_net);
3621+
Pin* sta_dest_pin = dbToSta(dest_pin);
3622+
dbNet* dest_flat_net = flatNet(sta_dest_pin);
3623+
disconnectPin(sta_dest_pin);
3624+
connectPin(sta_dest_pin, (Net*) dest_flat_net, (Net*) dest_mod_net);
35783625
return;
35793626
}
35803627
}
@@ -3610,11 +3657,12 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin,
36103657

36113658
// at leaf level make connection
36123659
if (level == 0) {
3613-
dbModNet* source_pin_mod_net = hierNet((Pin*) source_pin);
3660+
Pin* sta_source_pin = dbToSta(source_pin);
3661+
dbModNet* source_pin_mod_net = hierNet(sta_source_pin);
36143662
if (source_pin_mod_net) {
3615-
disconnectPin((Pin*) source_pin, (Net*) source_pin_mod_net);
3663+
disconnectPin(sta_source_pin, (Net*) source_pin_mod_net);
36163664
}
3617-
connectPin((Pin*) source_pin, (Net*) source_db_mod_net);
3665+
connectPin(sta_source_pin, (Net*) source_db_mod_net);
36183666
}
36193667

36203668
dbModInst* parent_inst = cur_module->getModInst();
@@ -3642,11 +3690,12 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin,
36423690
mod_bterm->setSigType(dbSigType::SIGNAL);
36433691

36443692
if (level == 0) {
3645-
dbModNet* dest_pin_mod_net = hierNet((Pin*) dest_pin);
3693+
Pin* sta_dest_pin = dbToSta(dest_pin);
3694+
dbModNet* dest_pin_mod_net = hierNet(sta_dest_pin);
36463695
if (dest_pin_mod_net) {
3647-
disconnectPin((Pin*) dest_pin, (Net*) dest_pin_mod_net);
3696+
disconnectPin(sta_dest_pin, (Net*) dest_pin_mod_net);
36483697
}
3649-
connectPin((Pin*) dest_pin, (Net*) dest_db_mod_net);
3698+
connectPin(sta_dest_pin, (Net*) dest_db_mod_net);
36503699
}
36513700

36523701
dbModInst* parent_inst = cur_module->getModInst();
@@ -3670,9 +3719,10 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin,
36703719
= dbModNet::create(highest_common_module, connection_name);
36713720
top_mod_dest->connect(source_db_mod_net);
36723721

3673-
dbNet* source_pin_flat_net = flatNet((Pin*) source_pin);
3674-
disconnectPin((Pin*) source_pin);
3675-
connectPin((Pin*) source_pin,
3722+
Pin* sta_source_pin = dbToSta(source_pin);
3723+
dbNet* source_pin_flat_net = flatNet(sta_source_pin);
3724+
disconnectPin(sta_source_pin);
3725+
connectPin(sta_source_pin,
36763726
(Net*) source_pin_flat_net,
36773727
(Net*) source_db_mod_net);
36783728
// source_pin->connect(source_db_mod_net);
@@ -3693,20 +3743,22 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin,
36933743

36943744
// reassociate the dest pin
36953745

3696-
dbModNet* dest_pin_mod_net = hierNet((Pin*) dest_pin);
3746+
Pin* sta_dest_pin = dbToSta(dest_pin);
3747+
dbModNet* dest_pin_mod_net = hierNet(sta_dest_pin);
36973748
if (dest_pin_mod_net) {
3698-
dbNet* dest_pin_flat_net = flatNet((Pin*) dest_pin);
3749+
dbNet* dest_pin_flat_net = flatNet(sta_dest_pin);
36993750
dest_pin->disconnect();
37003751
connectPin(
3701-
(Pin*) dest_pin, (Net*) dest_pin_flat_net, (Net*) dest_pin_mod_net);
3752+
sta_dest_pin, (Net*) dest_pin_flat_net, (Net*) dest_pin_mod_net);
37023753
}
37033754

37043755
// reassociate the source pin
3705-
dbModNet* source_pin_mod_net = hierNet((Pin*) source_pin);
3756+
Pin* sta_source_pin = dbToSta(source_pin);
3757+
dbModNet* source_pin_mod_net = hierNet(sta_source_pin);
37063758
if (source_pin_mod_net) {
3707-
dbNet* source_pin_flat_net = flatNet((Pin*) source_pin);
3759+
dbNet* source_pin_flat_net = flatNet(sta_source_pin);
37083760
source_pin->disconnect();
3709-
connectPin((Pin*) source_pin,
3761+
connectPin(sta_source_pin,
37103762
(Net*) source_pin_flat_net,
37113763
(Net*) source_pin_mod_net);
37123764
}

src/odb/src/codeGenerator/schema/chip/dbModITerm.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name":"dbModITerm",
33
"needs_non_default_destructor" : "true",
4+
"assert_alignment_is_multiple_of": 8,
45
"fields":[
56
{
67
"name":"_name",

src/odb/src/codeGenerator/templates/impl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ namespace odb {
8484

8585
_{{klass.name}}::_{{klass.name}}(_dbDatabase* db)
8686
{
87+
{% if klass.assert_alignment_is_multiple_of %}
88+
// For pointer tagging the bottom log_2({{klass.assert_alignment_is_multiple_of}}) bits.
89+
static_assert(alignof(_{{klass.name}}) % {{klass.assert_alignment_is_multiple_of}} == 0);
90+
{% endif%}
8791
{% for field in klass.fields %}
8892
{% if field.bitFields %}
8993
{{field.name}} = {};

src/odb/src/db/dbBTerm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ template class dbTable<_dbBTerm>;
3737

3838
_dbBTerm::_dbBTerm(_dbDatabase*)
3939
{
40+
// For pointer tagging the bottom 3 bits.
41+
static_assert(alignof(_dbBTerm) % 8 == 0);
4042
_flags._io_type = dbIoType::INPUT;
4143
_flags._sig_type = dbSigType::SIGNAL;
4244
_flags._orient = 0;

src/odb/src/db/dbITerm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class _dbITerm : public _dbObject
7272

7373
inline _dbITerm::_dbITerm(_dbDatabase*)
7474
{
75+
// For pointer tagging the bottom 3 bits.
76+
static_assert(alignof(_dbITerm) % 8 == 0);
7577
_flags._mterm_idx = 0;
7678
_flags._spare_bits = 0;
7779
_flags._clocked = 0;

src/odb/src/db/dbModITerm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ bool _dbModITerm::operator<(const _dbModITerm& rhs) const
5757

5858
_dbModITerm::_dbModITerm(_dbDatabase* db)
5959
{
60+
// For pointer tagging the bottom log_2(8) bits.
61+
static_assert(alignof(_dbModITerm) % 8 == 0);
6062
_name = nullptr;
6163
}
6264

src/rsz/src/Rebuffer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1933,8 +1933,9 @@ int Rebuffer::exportBufferTree(const BufferedNetPtr& choice,
19331933
return 0;
19341934
}
19351935

1936+
Pin* mod_net_drvr_pin = db_network_->dbToSta(mod_net_drvr);
19361937
dbNet* db_load_net = db_network_->flatNet(load_pin);
1937-
odb::dbNet* db_net = db_network_->flatNet((Pin*) mod_net_drvr);
1938+
odb::dbNet* db_net = db_network_->flatNet(mod_net_drvr_pin);
19381939
if ((Net*) db_load_net != net) {
19391940
odb::dbITerm* load_iterm = nullptr;
19401941
odb::dbBTerm* load_bterm = nullptr;

0 commit comments

Comments
 (0)