1+ // SPDX-License-Identifier: BSD-3-Clause
2+ // Copyright (c) 2019-2025, The OpenROAD Authors
3+
4+ #include " odb/3dblox.h"
5+
6+ #include " dbvParser.h"
7+ #include " objects.h"
8+ #include " odb/db.h"
9+ #include " utl/Logger.h"
10+ namespace odb {
11+ ThreeDBlox::ThreeDBlox (utl::Logger* logger, odb::dbDatabase* db)
12+ : logger_(logger), db_(db)
13+ {
14+ }
15+
16+ void ThreeDBlox::readDbv (const std::string& dbv_file)
17+ {
18+ DbvParser parser (logger_);
19+ DbvData data = parser.parseFile (dbv_file);
20+ if (db_->getDbuPerMicron () == 0 ) {
21+ db_->setDbuPerMicron (data.header .precision );
22+ } else {
23+ if (data.header .precision > db_->getDbuPerMicron ()) {
24+ logger_->error (utl::ODB,
25+ 515 ,
26+ " 3DBV Parser Error: Precision is greater than dbu per "
27+ " micron already set for database" );
28+ } else if (data.header .precision % db_->getDbuPerMicron () != 0 ) {
29+ logger_->error (
30+ utl::ODB,
31+ 516 ,
32+ " 3DBV Parser Error: Precision is not a multiple of dbu per "
33+ " micron already set for database" );
34+ }
35+ }
36+ for (const auto & [_, chiplet] : data.chiplet_defs ) {
37+ createChiplet (chiplet);
38+ }
39+ }
40+ dbChip::ChipType getChipType (const std::string& type, utl::Logger* logger)
41+ {
42+ if (type == " die" ) {
43+ return dbChip::ChipType::DIE;
44+ } else if (type == " rdl" ) {
45+ return dbChip::ChipType::RDL;
46+ } else if (type == " ip" ) {
47+ return dbChip::ChipType::IP;
48+ } else if (type == " substrate" ) {
49+ return dbChip::ChipType::SUBSTRATE;
50+ } else if (type == " hier" ) {
51+ return dbChip::ChipType::HIER;
52+ }
53+ logger->error (
54+ utl::ODB, 517 , " 3DBV Parser Error: Invalid chip type: {}" , type);
55+ }
56+ void ThreeDBlox::createChiplet (const ChipletDef& chiplet)
57+ {
58+ dbChip* chip
59+ = dbChip::create (db_, chiplet.name , getChipType (chiplet.type , logger_));
60+
61+ chip->setWidth (chiplet.design_width * db_->getDbuPerMicron ());
62+ chip->setHeight (chiplet.design_height * db_->getDbuPerMicron ());
63+ chip->setThickness (chiplet.thickness * db_->getDbuPerMicron ());
64+ chip->setShrink (chiplet.shrink );
65+ chip->setTsv (chiplet.tsv );
66+
67+ chip->setScribeLineEast (chiplet.scribe_line_right * db_->getDbuPerMicron ());
68+ chip->setScribeLineWest (chiplet.scribe_line_left * db_->getDbuPerMicron ());
69+ chip->setScribeLineNorth (chiplet.scribe_line_top * db_->getDbuPerMicron ());
70+ chip->setScribeLineSouth (chiplet.scribe_line_bottom * db_->getDbuPerMicron ());
71+
72+ chip->setSealRingEast (chiplet.seal_ring_right * db_->getDbuPerMicron ());
73+ chip->setSealRingWest (chiplet.seal_ring_left * db_->getDbuPerMicron ());
74+ chip->setSealRingNorth (chiplet.seal_ring_top * db_->getDbuPerMicron ());
75+ chip->setSealRingSouth (chiplet.seal_ring_bottom * db_->getDbuPerMicron ());
76+
77+ chip->setOffset (Point (chiplet.offset .x * db_->getDbuPerMicron (),
78+ chiplet.offset .y * db_->getDbuPerMicron ()));
79+ for (const auto & [_, region] : chiplet.regions ) {
80+ createRegion (region, chip);
81+ }
82+ }
83+ dbChipRegion::Side getChipRegionSide (const std::string& side,
84+ utl::Logger* logger)
85+ {
86+ if (side == " front" ) {
87+ return dbChipRegion::Side::FRONT;
88+ } else if (side == " back" ) {
89+ return dbChipRegion::Side::BACK;
90+ } else if (side == " internal" ) {
91+ return dbChipRegion::Side::INTERNAL;
92+ } else if (side == " internal_ext" ) {
93+ return dbChipRegion::Side::INTERNAL_EXT;
94+ }
95+ logger->error (
96+ utl::ODB, 518 , " 3DBV Parser Error: Invalid chip region side: {}" , side);
97+ }
98+ void ThreeDBlox::createRegion (const ChipletRegion& region, dbChip* chip)
99+ {
100+ dbTechLayer* layer = nullptr ;
101+ if (region.layer != " " ) {
102+ // TODO: add layer
103+ }
104+ dbChipRegion* chip_region = dbChipRegion::create (
105+ chip, region.name , getChipRegionSide (region.side , logger_), layer);
106+ Rect box;
107+ bool init = true ;
108+ for (const auto & coord : region.coords ) {
109+ if (init) {
110+ box.init (coord.x * db_->getDbuPerMicron (),
111+ coord.y * db_->getDbuPerMicron (),
112+ coord.x * db_->getDbuPerMicron (),
113+ coord.y * db_->getDbuPerMicron ());
114+ init = false ;
115+ } else {
116+ box.merge (Point (coord.x * db_->getDbuPerMicron (),
117+ coord.y * db_->getDbuPerMicron ()),
118+ box);
119+ }
120+ }
121+ chip_region->setBox (box);
122+ }
123+ } // namespace odb
0 commit comments