diff --git a/src/odb/include/odb/db.h b/src/odb/include/odb/db.h index 550108f8fcc..40c63573922 100644 --- a/src/odb/include/odb/db.h +++ b/src/odb/include/odb/db.h @@ -128,6 +128,7 @@ class dbViaParams; // Generator Code Begin ClassDeclarations class dbAccessPoint; +class dbDft; class dbGCellGrid; class dbGlobalConnect; class dbGroup; @@ -1360,6 +1361,16 @@ class dbBlock : public dbObject /// dbExtControl* getExtControl(); + /// + /// Get the dbDft object for persistent dft structs + /// + dbDft* createDft(); + + /// + /// Get the dbDft object for persistent dft structs + /// + dbDft* getDft() const; + /// /// Get the extraction corner names /// @@ -7067,6 +7078,22 @@ class dbAccessPoint : public dbObject // User Code End dbAccessPoint }; +class dbDft : public dbObject +{ + public: + void setScanInserted(bool scan_inserted); + + bool isScanInserted() const; + + dbSet getScanChains() const; + + // User Code Begin dbDft + dbId CreateScanPin(dbBTerm* bterm); + dbId CreateScanPin(dbITerm* iterm); + dbScanChain* CreateScanChain(); + // User Code End dbDft +}; + class dbGCellGrid : public dbObject { public: @@ -7701,22 +7728,91 @@ class dbPowerSwitch : public dbObject class dbScanChain : public dbObject { public: + dbSet getScanPartitions() const; + + dbSet getScanInsts() const; + + // User Code Begin dbScanChain + std::string_view getName() const; + + void setName(std::string_view name); + + void setScanIn(dbBTerm* scan_in); + dbBTerm* getScanIn() const; + + void setScanOut(dbBTerm* scan_out); + dbBTerm* getScanOut() const; + + void setScanEnable(dbBTerm* scan_enable); + + dbBTerm* getScanEnable() const; + + std::string_view getTestMode() const; + void setTestMode(std::string_view test_mode); + + dbScanPartition* createScanPartition(); + dbScanInst* createScanInst(dbInst* inst); + dbScanInst* createScanInst(const std::vector& insts); + // User Code End dbScanChain }; class dbScanInst : public dbObject { public: - enum class SCAN_INST_TYPE + struct AccessPins { - OneBit, - ShiftRegister, - BlackBox + std::variant scan_in; + std::variant scan_out; }; + enum class ClockEdge + { + Rising, + Falling + }; + + // User Code Begin dbScanInst + void setScanClock(std::string_view scan_clock); + std::string_view getScanClock() const; + + void setClockEdge(ClockEdge clock_edge); + ClockEdge getClockEdge() const; + + void setBits(uint bits); + + uint getBits() const; + + void setScanEnable(dbBTerm* scan_enable); + void setScanEnable(dbITerm* scan_enable); + std::variant getScanEnable() const; + + void setAccessPins(const AccessPins& access_pins); + + AccessPins getAccessPins() const; + + std::vector getInsts() const; + // User Code End dbScanInst }; class dbScanPartition : public dbObject { public: + // User Code Begin dbScanPartition + void setStart(dbBTerm* bterm); + + void setStart(dbITerm* iterm); + + void setStop(dbBTerm* bterm); + + void setStop(dbITerm* iterm); + + std::variant getStart() const; + + std::variant getStop() const; + + std::string_view getName() const; + + void setName(std::string_view name); + // User Code End dbScanPartition }; class dbScanPin : public dbObject diff --git a/src/odb/include/odb/dbObject.h b/src/odb/include/odb/dbObject.h index ddbf090990c..75472028193 100644 --- a/src/odb/include/odb/dbObject.h +++ b/src/odb/include/odb/dbObject.h @@ -87,6 +87,7 @@ enum dbObjectType dbBPinObj, // Generator Code Begin DbObjectType dbAccessPointObj, + dbDftObj, dbGCellGridObj, dbGlobalConnectObj, dbGroupObj, diff --git a/src/odb/src/codeGenerator/schema.json b/src/odb/src/codeGenerator/schema.json index 40c45fdd001..91f54db8ca4 100644 --- a/src/odb/src/codeGenerator/schema.json +++ b/src/odb/src/codeGenerator/schema.json @@ -182,6 +182,31 @@ "type":"1_n", "tbl_name":"wrongdir_spacing_rules_tbl_", "schema":"db_schema_wrongdir_spacing" + }, + { + "first": "dbDft", + "second": "dbScanPin", + "type": "1_n", + "tbl_name": "scan_pins_", + "flags": ["no-get"] + }, + { + "first": "dbScanChain", + "second": "dbScanPartition", + "type": "1_n", + "tbl_name": "scan_partitions_" + }, + { + "first": "dbScanChain", + "second": "dbScanInst", + "type": "1_n", + "tbl_name": "scan_insts_" + }, + { + "first": "dbDft", + "second": "dbScanChain", + "type": "1_n", + "tbl_name": "scan_chains_" } ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbDft.json b/src/odb/src/codeGenerator/schema/scan/dbDft.json new file mode 100644 index 00000000000..579f8525795 --- /dev/null +++ b/src/odb/src/codeGenerator/schema/scan/dbDft.json @@ -0,0 +1,13 @@ +{ + "name": "dbDft", + "type": "dbObject", + "fields": [ + { + "name": "scan_inserted_", + "type": "bool" + } + ], + "h_includes": [ + "dbBlock.h" + ] +} diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanChain.json b/src/odb/src/codeGenerator/schema/scan/dbScanChain.json index caa7f950bbe..ca7d34513b8 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanChain.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanChain.json @@ -7,50 +7,25 @@ "type": "std::string", "flags": ["private"] }, - { - "name": "length_", - "type": "uint", - "flags": ["private"] - }, - { - "name": "cells_", - "type": "dbVector>", - "flags": ["private"] - }, { "name": "scan_in_", - "type": "dbId", + "type": "dbId", "flags": ["private"] }, { "name": "scan_out_", - "type": "dbId", - "flags": ["private"] - }, - { - "name": "scan_clock_", - "type": "dbId", + "type": "dbId", "flags": ["private"] }, { "name": "scan_enable_", - "type": "dbId", + "type": "dbId", "flags": ["private"] }, { "name": "test_mode_", "type": "std::string", "flags": ["private"] - }, - { - "name": "partitions_", - "type": "dbVector>", - "flags": ["private"] - }, - { - "name": "scan_insts_", - "type": "dbVector>", - "flags": ["private"] } ], "h_includes": [ @@ -58,6 +33,13 @@ "dbScanPin.h" ], "cpp_includes": [ - "dbScanPin.h" + "dbScanPin.h", + "dbScanPartition.h", + "dbScanInst.h", + "dbBlock.h", + "dbDft.h" + ], + "classes": [ + "dbScanPartition" ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanInst.json b/src/odb/src/codeGenerator/schema/scan/dbScanInst.json index 29cc4f0c762..72bc050e213 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanInst.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanInst.json @@ -3,37 +3,71 @@ "type": "dbObject", "fields": [ { - "name": "bits", + "name": "bits_", "type": "uint", "flags": ["private"] }, { - "name": "scanIn", + "name": "access_pins_", + "type": "std::pair, dbId>", + "flags": ["private", "no-template"] + }, + { + "name": "scan_enable_", "type": "dbId", "flags": ["private"] }, { - "name": "scanOut", - "type": "dbId", + "name": "insts_", + "type": "dbVector>", + "flags": ["private"] + }, + { + "name": "scan_clock_", + "type": "std::string", + "flags": ["private"] + }, + { + "name": "clock_edge_", + "type": "uint", "flags": ["private"] } ], "enums": [ { - "name": "SCAN_INST_TYPE", - "public": true, + "name": "ClockEdge", "class": true, "values": [ - "OneBit", - "ShiftRegister", - "BlackBox" - ] + "Rising", + "Falling" + ], + "public": true + } + ], + "structs": [ + { + "name": "AccessPins", + "public": true, + "fields": [ + { + "name": "scan_in", + "type": "std::variant" + }, + { + "name": "scan_out", + "type": "std::variant" + } + ] } ], "h_includes": [ - "dbScanPin.h" + "dbScanPin.h", + "dbInst.h", + "dbVector.h" ], "cpp_includes": [ - "dbScanPin.h" + "dbScanPin.h", + "dbDft.h", + "dbScanChain.h" ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json b/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json index f06dec160a9..16d47805c15 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json @@ -22,6 +22,8 @@ "dbScanPin.h" ], "cpp_includes": [ - "dbScanPin.h" + "dbScanPin.h", + "dbScanChain.h", + "dbDft.h" ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanPin.json b/src/odb/src/codeGenerator/schema/scan/dbScanPin.json index 2e2aec5fb4e..29c4fb83ff0 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanPin.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanPin.json @@ -10,7 +10,15 @@ ], "h_includes": [ "dbBTerm.h", - "dbITerm.h", - "dbBlock.h" + "dbITerm.h" + ], + "cpp_includes": [ + "dbBlock.h", + "dbDft.h" + ], + "classes": [ + "dbScanPin", + "dbBTerm", + "dbITerm" ] } diff --git a/src/odb/src/db/CMakeLists.txt b/src/odb/src/db/CMakeLists.txt index f68474f7e3d..1393a5f1a49 100644 --- a/src/odb/src/db/CMakeLists.txt +++ b/src/odb/src/db/CMakeLists.txt @@ -88,6 +88,7 @@ add_library(db dbGroupGroundNetItr.cpp # Generator Code Begin cpp dbAccessPoint.cpp + dbDft.cpp dbGCellGrid.cpp dbGlobalConnect.cpp dbGroup.cpp diff --git a/src/odb/src/db/dbBlock.cpp b/src/odb/src/db/dbBlock.cpp index e2b40c22e82..acdca1bc2f5 100644 --- a/src/odb/src/db/dbBlock.cpp +++ b/src/odb/src/db/dbBlock.cpp @@ -59,6 +59,7 @@ #include "dbCapNodeItr.h" #include "dbChip.h" #include "dbDatabase.h" +#include "dbDft.h" #include "dbDiff.h" #include "dbDiff.hpp" #include "dbExtControl.h" @@ -314,6 +315,9 @@ _dbBlock::_dbBlock(_dbDatabase* db) _extControl = new dbExtControl(); + _dft_tbl = new dbTable<_dbDft>( + db, this, (GetObjTbl_t) &_dbBlock::getObjectTable, dbDftObj); + _net_hash.setTable(_net_tbl); _inst_hash.setTable(_inst_tbl); _module_hash.setTable(_module_tbl); @@ -416,7 +420,8 @@ _dbBlock::_dbBlock(_dbDatabase* db, const _dbBlock& block) _maxCCSegId(block._maxCCSegId), _children(block._children), _component_mask_shift(block._component_mask_shift), - _currentCcAdjOrder(block._currentCcAdjOrder) + _currentCcAdjOrder(block._currentCcAdjOrder), + _dft(block._dft) { if (block._name) { _name = strdup(block._name); @@ -514,6 +519,8 @@ _dbBlock::_dbBlock(_dbDatabase* db, const _dbBlock& block) _extControl = new dbExtControl(); + _dft_tbl = new dbTable<_dbDft>(db, this, *block._dft_tbl); + _net_hash.setTable(_net_tbl); _inst_hash.setTable(_inst_tbl); _module_hash.setTable(_module_tbl); @@ -654,6 +661,7 @@ _dbBlock::~_dbBlock() delete _group_ground_net_itr; delete _bpin_itr; delete _prop_itr; + delete _dft_tbl; std::list::iterator _cbitr; while (_callbacks.begin() != _callbacks.end()) { @@ -859,6 +867,10 @@ dbObjectTable* _dbBlock::getObjectTable(dbObjectType type) case dbPropertyObj: return _prop_tbl; + + case dbDftObj: + return _dft_tbl; + default: break; } @@ -954,6 +966,8 @@ dbOStream& operator<<(dbOStream& stream, const _dbBlock& block) stream << NamedTable("r_seg_tbl", block._r_seg_tbl); stream << NamedTable("cc_seg_tbl", block._cc_seg_tbl); stream << *block._extControl; + stream << block._dft; + stream << *block._dft_tbl; //---------------------------------------------------------- stream out // properties @@ -1074,6 +1088,10 @@ dbIStream& operator>>(dbIStream& stream, _dbBlock& block) stream >> *block._r_seg_tbl; // DKF stream >> *block._cc_seg_tbl; stream >> *block._extControl; + if (db->isSchema(db_schema_add_scan)) { + stream >> block._dft; + stream >> *block._dft_tbl; + } //---------------------------------------------------------- stream in // properties @@ -1361,6 +1379,12 @@ bool _dbBlock::operator==(const _dbBlock& rhs) const if (*_cc_seg_tbl != *rhs._cc_seg_tbl) return false; + if (_dft != rhs._dft) + return false; + + if (*_dft_tbl != *rhs._dft_tbl) + return false; + return true; } @@ -1446,6 +1470,8 @@ void _dbBlock::differences(dbDiff& diff, DIFF_TABLE(_layer_rule_tbl); DIFF_TABLE_NO_DEEP(_prop_tbl); DIFF_NAME_CACHE(_name_cache); + DIFF_FIELD(_dft); + DIFF_TABLE(_dft_tbl); if (*_r_val_tbl != *rhs._r_val_tbl) _r_val_tbl->differences(diff, "_r_val_tbl", *rhs._r_val_tbl); @@ -1542,6 +1568,8 @@ void _dbBlock::out(dbDiff& diff, char side, const char* field) const DIFF_OUT_TABLE(_layer_rule_tbl); DIFF_OUT_TABLE_NO_DEEP(_prop_tbl); DIFF_OUT_NAME_CACHE(_name_cache); + DIFF_OUT_FIELD(_dft); + DIFF_OUT_TABLE(_dft_tbl); _r_val_tbl->out(diff, side, "_r_val_tbl"); _c_val_tbl->out(diff, side, "_c_val_tbl"); @@ -2211,6 +2239,20 @@ dbExtControl* dbBlock::getExtControl() return (block->_extControl); } +dbDft* dbBlock::createDft() +{ + _dbBlock* block = (_dbBlock*) this; + _dbDft* dft = block->_dft_tbl->create(); + block->_dft = dft->getId(); + return (dbDft*) dft; +} + +dbDft* dbBlock::getDft() const +{ + _dbBlock* block = (_dbBlock*) this; + return (dbDft*) block->_dft_tbl->getPtr(block->_dft); +} + void dbBlock::getExtCornerNames(std::list& ecl) { _dbBlock* block = (_dbBlock*) this; diff --git a/src/odb/src/db/dbBlock.h b/src/odb/src/db/dbBlock.h index 391ce939f24..0073ff4adbd 100644 --- a/src/odb/src/db/dbBlock.h +++ b/src/odb/src/db/dbBlock.h @@ -126,6 +126,7 @@ class dbBlockSearch; class dbBlockCallBackObj; class dbGuideItr; class dbNetTrackItr; +class _dbDft; struct _dbBlockFlags { @@ -181,6 +182,7 @@ class _dbBlock : public _dbObject dbVector> _children; dbVector> _component_mask_shift; uint _currentCcAdjOrder; + dbId<_dbDft> _dft; // NON-PERSISTANT-STREAMED-MEMBERS dbTable<_dbBTerm>* _bterm_tbl; @@ -218,6 +220,7 @@ class _dbBlock : public _dbObject dbTable<_dbGuide>* _guide_tbl; dbTable<_dbNetTrack>* _net_tracks_tbl; _dbNameCache* _name_cache; + dbTable<_dbDft>* _dft_tbl; dbPagedVector* _r_val_tbl; dbPagedVector* _c_val_tbl; diff --git a/src/odb/src/db/dbDatabase.h b/src/odb/src/db/dbDatabase.h index 650e1a2214a..c1e579fc2c0 100644 --- a/src/odb/src/db/dbDatabase.h +++ b/src/odb/src/db/dbDatabase.h @@ -69,7 +69,9 @@ namespace odb { // const uint db_schema_major = 0; // Not used... const uint db_schema_initial = 57; -const uint db_schema_minor = 78; // Current revision number +const uint db_schema_minor = 79; // Current revision number + +const uint db_schema_add_scan = 79; // Revision where _dbBox / flags.mask was added const uint db_schema_dbbox_mask = 78; diff --git a/src/odb/src/db/dbDft.cpp b/src/odb/src/db/dbDft.cpp new file mode 100644 index 00000000000..e455e98b2b0 --- /dev/null +++ b/src/odb/src/db/dbDft.cpp @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (c) 2022, The Regents of the University of California +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Generator Code Begin Cpp +#include "dbDft.h" + +#include "db.h" +#include "dbDatabase.h" +#include "dbDiff.hpp" +#include "dbScanChain.h" +#include "dbScanPin.h" +#include "dbSet.h" +#include "dbTable.h" +#include "dbTable.hpp" +namespace odb { +template class dbTable<_dbDft>; + +bool _dbDft::operator==(const _dbDft& rhs) const +{ + if (scan_inserted_ != rhs.scan_inserted_) { + return false; + } + if (*scan_pins_ != *rhs.scan_pins_) { + return false; + } + if (*scan_chains_ != *rhs.scan_chains_) { + return false; + } + + return true; +} + +bool _dbDft::operator<(const _dbDft& rhs) const +{ + return true; +} + +void _dbDft::differences(dbDiff& diff, + const char* field, + const _dbDft& rhs) const +{ + DIFF_BEGIN + DIFF_FIELD(scan_inserted_); + DIFF_TABLE(scan_pins_); + DIFF_TABLE(scan_chains_); + DIFF_END +} + +void _dbDft::out(dbDiff& diff, char side, const char* field) const +{ + DIFF_OUT_BEGIN + DIFF_OUT_FIELD(scan_inserted_); + DIFF_OUT_TABLE(scan_pins_); + DIFF_OUT_TABLE(scan_chains_); + + DIFF_END +} + +_dbDft::_dbDft(_dbDatabase* db) +{ + scan_pins_ = new dbTable<_dbScanPin>( + db, this, (GetObjTbl_t) &_dbDft::getObjectTable, dbScanPinObj); + scan_chains_ = new dbTable<_dbScanChain>( + db, this, (GetObjTbl_t) &_dbDft::getObjectTable, dbScanChainObj); +} + +_dbDft::_dbDft(_dbDatabase* db, const _dbDft& r) +{ + scan_inserted_ = r.scan_inserted_; + scan_pins_ = new dbTable<_dbScanPin>(db, this, *r.scan_pins_); + scan_chains_ = new dbTable<_dbScanChain>(db, this, *r.scan_chains_); +} + +dbIStream& operator>>(dbIStream& stream, _dbDft& obj) +{ + stream >> obj.scan_inserted_; + stream >> *obj.scan_pins_; + stream >> *obj.scan_chains_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbDft& obj) +{ + stream << obj.scan_inserted_; + stream << *obj.scan_pins_; + stream << *obj.scan_chains_; + return stream; +} + +dbObjectTable* _dbDft::getObjectTable(dbObjectType type) +{ + switch (type) { + case dbScanPinObj: + return scan_pins_; + case dbScanChainObj: + return scan_chains_; + default: + break; + } + return getTable()->getObjectTable(type); +} + +_dbDft::~_dbDft() +{ + delete scan_pins_; + delete scan_chains_; +} + +//////////////////////////////////////////////////////////////////// +// +// dbDft - Methods +// +//////////////////////////////////////////////////////////////////// + +void dbDft::setScanInserted(bool scan_inserted) +{ + _dbDft* obj = (_dbDft*) this; + + obj->scan_inserted_ = scan_inserted; +} + +bool dbDft::isScanInserted() const +{ + _dbDft* obj = (_dbDft*) this; + return obj->scan_inserted_; +} + +dbSet dbDft::getScanChains() const +{ + _dbDft* obj = (_dbDft*) this; + return dbSet(obj, obj->scan_chains_); +} + +// User Code Begin dbDftPublicMethods +dbId dbDft::CreateScanPin(dbBTerm* bterm) +{ + _dbDft* obj = (_dbDft*) this; + _dbScanPin* scan_pin = (_dbScanPin*) obj->scan_pins_->create(); + ((dbScanPin*) scan_pin)->setPin(bterm); + return scan_pin->getId(); +} + +dbId dbDft::CreateScanPin(dbITerm* iterm) +{ + _dbDft* obj = (_dbDft*) this; + _dbScanPin* scan_pin = (_dbScanPin*) obj->scan_pins_->create(); + ((dbScanPin*) scan_pin)->setPin(iterm); + return scan_pin->getId(); +} + +dbScanChain* dbDft::CreateScanChain() +{ + _dbDft* obj = (_dbDft*) this; + return (dbScanChain*) obj->scan_chains_->create(); +} + +// User Code End dbDftPublicMethods +} // namespace odb +// Generator Code End Cpp diff --git a/src/odb/src/db/dbDft.h b/src/odb/src/db/dbDft.h new file mode 100644 index 00000000000..5942a0186ea --- /dev/null +++ b/src/odb/src/db/dbDft.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (c) 2022, The Regents of the University of California +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Generator Code Begin Header +#pragma once + +#include "dbBlock.h" +#include "dbCore.h" +#include "odb.h" + +namespace odb { +class dbIStream; +class dbOStream; +class dbDiff; +class _dbDatabase; +class _dbScanPin; +template +class dbTable; +class _dbScanChain; + +class _dbDft : public _dbObject +{ + public: + _dbDft(_dbDatabase*, const _dbDft& r); + _dbDft(_dbDatabase*); + + ~_dbDft(); + + bool operator==(const _dbDft& rhs) const; + bool operator!=(const _dbDft& rhs) const { return !operator==(rhs); } + bool operator<(const _dbDft& rhs) const; + void differences(dbDiff& diff, const char* field, const _dbDft& rhs) const; + void out(dbDiff& diff, char side, const char* field) const; + dbObjectTable* getObjectTable(dbObjectType type); + + bool scan_inserted_; + + dbTable<_dbScanPin>* scan_pins_; + + dbTable<_dbScanChain>* scan_chains_; +}; +dbIStream& operator>>(dbIStream& stream, _dbDft& obj); +dbOStream& operator<<(dbOStream& stream, const _dbDft& obj); +} // namespace odb +// Generator Code End Header diff --git a/src/odb/src/db/dbObject.cpp b/src/odb/src/db/dbObject.cpp index 212ecd6b80b..69160386ba6 100644 --- a/src/odb/src/db/dbObject.cpp +++ b/src/odb/src/db/dbObject.cpp @@ -91,6 +91,7 @@ static const char* name_tbl[] = {"dbDatabase", "dbBPin", // Generator Code Begin ObjectNames "dbAccessPoint", + "dbDft", "dbGCellGrid", "dbGlobalConnect", "dbGroup", diff --git a/src/odb/src/db/dbScanChain.cpp b/src/odb/src/db/dbScanChain.cpp index c73a5b6ccaf..777666200df 100644 --- a/src/odb/src/db/dbScanChain.cpp +++ b/src/odb/src/db/dbScanChain.cpp @@ -34,9 +34,14 @@ #include "dbScanChain.h" #include "db.h" +#include "dbBlock.h" #include "dbDatabase.h" +#include "dbDft.h" #include "dbDiff.hpp" +#include "dbScanInst.h" +#include "dbScanPartition.h" #include "dbScanPin.h" +#include "dbSet.h" #include "dbTable.h" #include "dbTable.hpp" namespace odb { @@ -47,24 +52,24 @@ bool _dbScanChain::operator==(const _dbScanChain& rhs) const if (name_ != rhs.name_) { return false; } - if (length_ != rhs.length_) { - return false; - } if (scan_in_ != rhs.scan_in_) { return false; } if (scan_out_ != rhs.scan_out_) { return false; } - if (scan_clock_ != rhs.scan_clock_) { - return false; - } if (scan_enable_ != rhs.scan_enable_) { return false; } if (test_mode_ != rhs.test_mode_) { return false; } + if (*scan_partitions_ != *rhs.scan_partitions_) { + return false; + } + if (*scan_insts_ != *rhs.scan_insts_) { + return false; + } return true; } @@ -80,12 +85,12 @@ void _dbScanChain::differences(dbDiff& diff, { DIFF_BEGIN DIFF_FIELD(name_); - DIFF_FIELD(length_); DIFF_FIELD(scan_in_); DIFF_FIELD(scan_out_); - DIFF_FIELD(scan_clock_); DIFF_FIELD(scan_enable_); DIFF_FIELD(test_mode_); + DIFF_TABLE(scan_partitions_); + DIFF_TABLE(scan_insts_); DIFF_END } @@ -93,66 +98,209 @@ void _dbScanChain::out(dbDiff& diff, char side, const char* field) const { DIFF_OUT_BEGIN DIFF_OUT_FIELD(name_); - DIFF_OUT_FIELD(length_); DIFF_OUT_FIELD(scan_in_); DIFF_OUT_FIELD(scan_out_); - DIFF_OUT_FIELD(scan_clock_); DIFF_OUT_FIELD(scan_enable_); DIFF_OUT_FIELD(test_mode_); + DIFF_OUT_TABLE(scan_partitions_); + DIFF_OUT_TABLE(scan_insts_); DIFF_END } _dbScanChain::_dbScanChain(_dbDatabase* db) { + scan_partitions_ = new dbTable<_dbScanPartition>( + db, + this, + (GetObjTbl_t) &_dbScanChain::getObjectTable, + dbScanPartitionObj); + scan_insts_ = new dbTable<_dbScanInst>( + db, this, (GetObjTbl_t) &_dbScanChain::getObjectTable, dbScanInstObj); } _dbScanChain::_dbScanChain(_dbDatabase* db, const _dbScanChain& r) { name_ = r.name_; - length_ = r.length_; scan_in_ = r.scan_in_; scan_out_ = r.scan_out_; - scan_clock_ = r.scan_clock_; scan_enable_ = r.scan_enable_; test_mode_ = r.test_mode_; + scan_partitions_ + = new dbTable<_dbScanPartition>(db, this, *r.scan_partitions_); + scan_insts_ = new dbTable<_dbScanInst>(db, this, *r.scan_insts_); } dbIStream& operator>>(dbIStream& stream, _dbScanChain& obj) { stream >> obj.name_; - stream >> obj.length_; - stream >> obj.cells_; stream >> obj.scan_in_; stream >> obj.scan_out_; - stream >> obj.scan_clock_; stream >> obj.scan_enable_; stream >> obj.test_mode_; - stream >> obj.partitions_; - stream >> obj.scan_insts_; + stream >> *obj.scan_partitions_; + stream >> *obj.scan_insts_; return stream; } dbOStream& operator<<(dbOStream& stream, const _dbScanChain& obj) { stream << obj.name_; - stream << obj.length_; - stream << obj.cells_; stream << obj.scan_in_; stream << obj.scan_out_; - stream << obj.scan_clock_; stream << obj.scan_enable_; stream << obj.test_mode_; - stream << obj.partitions_; - stream << obj.scan_insts_; + stream << *obj.scan_partitions_; + stream << *obj.scan_insts_; return stream; } +dbObjectTable* _dbScanChain::getObjectTable(dbObjectType type) +{ + switch (type) { + case dbScanPartitionObj: + return scan_partitions_; + case dbScanInstObj: + return scan_insts_; + default: + break; + } + return getTable()->getObjectTable(type); +} + +_dbScanChain::~_dbScanChain() +{ + delete scan_partitions_; + delete scan_insts_; +} + //////////////////////////////////////////////////////////////////// // // dbScanChain - Methods // //////////////////////////////////////////////////////////////////// +dbSet dbScanChain::getScanPartitions() const +{ + _dbScanChain* obj = (_dbScanChain*) this; + return dbSet(obj, obj->scan_partitions_); +} + +dbSet dbScanChain::getScanInsts() const +{ + _dbScanChain* obj = (_dbScanChain*) this; + return dbSet(obj, obj->scan_insts_); +} + +// User Code Begin dbScanChainPublicMethods + +std::string_view dbScanChain::getName() const +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + return scan_chain->name_; +} + +void dbScanChain::setName(std::string_view name) +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + scan_chain->name_ = name; +} + +dbBTerm* _dbScanChain::getPin(_dbScanChain* scan_chain, + dbId _dbScanChain::*field) +{ + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + _dbBlock* block = (_dbBlock*) dft->getOwner(); + + return (dbBTerm*) block->_bterm_tbl->getPtr( + (dbId<_dbBTerm>) (scan_chain->*field)); +} + +void _dbScanChain::setPin(_dbScanChain* scan_chain, + dbId _dbScanChain::*field, + dbBTerm* pin) +{ + _dbBTerm* bterm = (_dbBTerm*) pin; + scan_chain->*field = bterm->getId(); +} + +void dbScanChain::setScanIn(dbBTerm* scan_in) +{ + _dbScanChain::setPin((_dbScanChain*) this, &_dbScanChain::scan_in_, scan_in); +} + +dbBTerm* dbScanChain::getScanIn() const +{ + return _dbScanChain::getPin((_dbScanChain*) this, &_dbScanChain::scan_in_); +} + +void dbScanChain::setScanOut(dbBTerm* scan_out) +{ + _dbScanChain::setPin( + (_dbScanChain*) this, &_dbScanChain::scan_out_, scan_out); +} + +dbBTerm* dbScanChain::getScanOut() const +{ + return _dbScanChain::getPin((_dbScanChain*) this, &_dbScanChain::scan_out_); +} + +void dbScanChain::setScanEnable(dbBTerm* scan_enable) +{ + _dbScanChain::setPin( + (_dbScanChain*) this, &_dbScanChain::scan_enable_, scan_enable); +} + +dbBTerm* dbScanChain::getScanEnable() const +{ + return _dbScanChain::getPin((_dbScanChain*) this, + &_dbScanChain::scan_enable_); +} + +void dbScanChain::setTestMode(std::string_view test_mode) +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + scan_chain->test_mode_ = test_mode; +} + +std::string_view dbScanChain::getTestMode() const +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + return scan_chain->test_mode_; +} + +dbScanPartition* dbScanChain::createScanPartition() +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + return (dbScanPartition*) (scan_chain->scan_partitions_->create()); +} + +dbScanInst* dbScanChain::createScanInst(dbInst* inst) +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + _dbInst* _inst = (_dbInst*) inst; + + _dbScanInst* scan_inst = (_dbScanInst*) scan_chain->scan_insts_->create(); + scan_inst->insts_.reserve(1); + scan_inst->insts_.push_back(_inst->getId()); + + return (dbScanInst*) scan_inst; +} + +dbScanInst* dbScanChain::createScanInst(const std::vector& insts) +{ + _dbScanChain* scan_chain = (_dbScanChain*) this; + + _dbScanInst* scan_inst = (_dbScanInst*) scan_chain->scan_insts_->create(); + scan_inst->insts_.reserve(insts.size()); + + for (const dbInst* inst : insts) { + scan_inst->insts_.push_back(inst->getId()); + } + + return (dbScanInst*) scan_inst; +} + +// User Code End dbScanChainPublicMethods } // namespace odb - // Generator Code End Cpp \ No newline at end of file + // Generator Code End Cpp diff --git a/src/odb/src/db/dbScanChain.h b/src/odb/src/db/dbScanChain.h index 41a874f26b1..9f4a5f96a12 100644 --- a/src/odb/src/db/dbScanChain.h +++ b/src/odb/src/db/dbScanChain.h @@ -43,10 +43,12 @@ class dbIStream; class dbOStream; class dbDiff; class _dbDatabase; -class dbInst; -class dbScanPin; class dbScanPartition; -class dbScanInst; +class _dbScanPartition; +template +class dbTable; +class _dbScanInst; +class dbBTerm; class _dbScanChain : public _dbObject { @@ -54,7 +56,7 @@ class _dbScanChain : public _dbObject _dbScanChain(_dbDatabase*, const _dbScanChain& r); _dbScanChain(_dbDatabase*); - ~_dbScanChain() = default; + ~_dbScanChain(); bool operator==(const _dbScanChain& rhs) const; bool operator!=(const _dbScanChain& rhs) const { return !operator==(rhs); } @@ -63,19 +65,26 @@ class _dbScanChain : public _dbObject const char* field, const _dbScanChain& rhs) const; void out(dbDiff& diff, char side, const char* field) const; + dbObjectTable* getObjectTable(dbObjectType type); + // User Code Begin Methods + static dbBTerm* getPin(_dbScanChain* scan_chain, + dbId _dbScanChain::*field); + static void setPin(_dbScanChain* scan_chain, + dbId _dbScanChain::*field, + dbBTerm* pin); + // User Code End Methods std::string name_; - uint length_; - dbVector> cells_; - dbId scan_in_; - dbId scan_out_; - dbId scan_clock_; - dbId scan_enable_; + dbId scan_in_; + dbId scan_out_; + dbId scan_enable_; std::string test_mode_; - dbVector> partitions_; - dbVector> scan_insts_; + + dbTable<_dbScanPartition>* scan_partitions_; + + dbTable<_dbScanInst>* scan_insts_; }; dbIStream& operator>>(dbIStream& stream, _dbScanChain& obj); dbOStream& operator<<(dbOStream& stream, const _dbScanChain& obj); } // namespace odb - // Generator Code End Header \ No newline at end of file + // Generator Code End Header diff --git a/src/odb/src/db/dbScanInst.cpp b/src/odb/src/db/dbScanInst.cpp index 4cbe74b57be..4c08132c9d5 100644 --- a/src/odb/src/db/dbScanInst.cpp +++ b/src/odb/src/db/dbScanInst.cpp @@ -35,7 +35,9 @@ #include "db.h" #include "dbDatabase.h" +#include "dbDft.h" #include "dbDiff.hpp" +#include "dbScanChain.h" #include "dbScanPin.h" #include "dbTable.h" #include "dbTable.hpp" @@ -44,13 +46,16 @@ template class dbTable<_dbScanInst>; bool _dbScanInst::operator==(const _dbScanInst& rhs) const { - if (bits != rhs.bits) { + if (bits_ != rhs.bits_) { return false; } - if (scanIn != rhs.scanIn) { + if (scan_enable_ != rhs.scan_enable_) { return false; } - if (scanOut != rhs.scanOut) { + if (scan_clock_ != rhs.scan_clock_) { + return false; + } + if (clock_edge_ != rhs.clock_edge_) { return false; } @@ -67,18 +72,20 @@ void _dbScanInst::differences(dbDiff& diff, const _dbScanInst& rhs) const { DIFF_BEGIN - DIFF_FIELD(bits); - DIFF_FIELD(scanIn); - DIFF_FIELD(scanOut); + DIFF_FIELD(bits_); + DIFF_FIELD(scan_enable_); + DIFF_FIELD(scan_clock_); + DIFF_FIELD(clock_edge_); DIFF_END } void _dbScanInst::out(dbDiff& diff, char side, const char* field) const { DIFF_OUT_BEGIN - DIFF_OUT_FIELD(bits); - DIFF_OUT_FIELD(scanIn); - DIFF_OUT_FIELD(scanOut); + DIFF_OUT_FIELD(bits_); + DIFF_OUT_FIELD(scan_enable_); + DIFF_OUT_FIELD(scan_clock_); + DIFF_OUT_FIELD(clock_edge_); DIFF_END } @@ -89,24 +96,31 @@ _dbScanInst::_dbScanInst(_dbDatabase* db) _dbScanInst::_dbScanInst(_dbDatabase* db, const _dbScanInst& r) { - bits = r.bits; - scanIn = r.scanIn; - scanOut = r.scanOut; + bits_ = r.bits_; + scan_enable_ = r.scan_enable_; + scan_clock_ = r.scan_clock_; + clock_edge_ = r.clock_edge_; } dbIStream& operator>>(dbIStream& stream, _dbScanInst& obj) { - stream >> obj.bits; - stream >> obj.scanIn; - stream >> obj.scanOut; + stream >> obj.bits_; + stream >> obj.access_pins_; + stream >> obj.scan_enable_; + stream >> obj.insts_; + stream >> obj.scan_clock_; + stream >> obj.clock_edge_; return stream; } dbOStream& operator<<(dbOStream& stream, const _dbScanInst& obj) { - stream << obj.bits; - stream << obj.scanIn; - stream << obj.scanOut; + stream << obj.bits_; + stream << obj.access_pins_; + stream << obj.scan_enable_; + stream << obj.insts_; + stream << obj.scan_clock_; + stream << obj.clock_edge_; return stream; } @@ -116,5 +130,134 @@ dbOStream& operator<<(dbOStream& stream, const _dbScanInst& obj) // //////////////////////////////////////////////////////////////////// +// User Code Begin dbScanInstPublicMethods +void dbScanInst::setScanClock(std::string_view scan_clock) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + scan_inst->scan_clock_ = scan_clock; +} + +std::string_view dbScanInst::getScanClock() const +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + return scan_inst->scan_clock_; +} + +void dbScanInst::setClockEdge(ClockEdge clock_edge) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + scan_inst->clock_edge_ = static_cast(clock_edge); +} + +dbScanInst::ClockEdge dbScanInst::getClockEdge() const +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + return static_cast(scan_inst->clock_edge_); +} + +void dbScanInst::setBits(uint bits) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + scan_inst->bits_ = bits; +} + +uint dbScanInst::getBits() const +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + return scan_inst->bits_; +} + +void dbScanInst::setScanEnable(dbBTerm* scan_enable) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_inst->scan_enable_ = dft->CreateScanPin(scan_enable); +} + +void dbScanInst::setScanEnable(dbITerm* scan_enable) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_inst->scan_enable_ = dft->CreateScanPin(scan_enable); +} + +std::variant dbScanInst::getScanEnable() const +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + const dbScanPin* scan_enable = (dbScanPin*) dft->scan_pins_->getPtr( + (dbId<_dbScanPin>) scan_inst->scan_enable_); + return scan_enable->getPin(); +} + +std::string_view getName(odb::dbBTerm* bterm) +{ + return bterm->getConstName(); +} + +std::string_view getName(odb::dbITerm* iterm) +{ + return iterm->getMTerm()->getConstName(); +} + +void dbScanInst::setAccessPins(const AccessPins& access_pins) +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + + std::visit( + [&access_pins, scan_inst, dft](auto&& scan_in_pin) { + const dbId scan_in = dft->CreateScanPin(scan_in_pin); + std::visit( + [scan_inst, dft, &scan_in](auto&& scan_out_pin) { + const dbId scan_out = dft->CreateScanPin(scan_out_pin); + scan_inst->access_pins_ = std::make_pair(scan_in, scan_out); + }, + access_pins.scan_out); + }, + access_pins.scan_in); +} + +dbScanInst::AccessPins dbScanInst::getAccessPins() const +{ + AccessPins access_pins; + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + + const auto& [scan_in_id, scan_out_id] = scan_inst->access_pins_; + + dbScanPin* scan_in + = (dbScanPin*) dft->scan_pins_->getPtr((dbId<_dbScanPin>) scan_in_id); + dbScanPin* scan_out + = (dbScanPin*) dft->scan_pins_->getPtr((dbId<_dbScanPin>) scan_out_id); + + access_pins.scan_in = scan_in->getPin(); + access_pins.scan_out = scan_out->getPin(); + + return access_pins; +} + +std::vector dbScanInst::getInsts() const +{ + _dbScanInst* scan_inst = (_dbScanInst*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_inst->getOwner(); + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + _dbBlock* block = (_dbBlock*) dft->getOwner(); + + std::vector insts; + + for (dbId id : scan_inst->insts_) { + insts.push_back((dbInst*) block->_inst_tbl->getPtr((dbId<_dbInst>) id)); + } + + return insts; +} + +// User Code End dbScanInstPublicMethods } // namespace odb - // Generator Code End Cpp \ No newline at end of file + // Generator Code End Cpp diff --git a/src/odb/src/db/dbScanInst.h b/src/odb/src/db/dbScanInst.h index 1fe94580dcd..81411abf7ad 100644 --- a/src/odb/src/db/dbScanInst.h +++ b/src/odb/src/db/dbScanInst.h @@ -34,7 +34,9 @@ #pragma once #include "dbCore.h" +#include "dbInst.h" #include "dbScanPin.h" +#include "dbVector.h" #include "odb.h" namespace odb { @@ -43,6 +45,7 @@ class dbOStream; class dbDiff; class _dbDatabase; class dbScanPin; +class dbInst; class _dbScanInst : public _dbObject { @@ -60,9 +63,12 @@ class _dbScanInst : public _dbObject const _dbScanInst& rhs) const; void out(dbDiff& diff, char side, const char* field) const; - uint bits; - dbId scanIn; - dbId scanOut; + uint bits_; + std::pair, dbId> access_pins_; + dbId scan_enable_; + dbVector> insts_; + std::string scan_clock_; + uint clock_edge_; }; dbIStream& operator>>(dbIStream& stream, _dbScanInst& obj); dbOStream& operator<<(dbOStream& stream, const _dbScanInst& obj); diff --git a/src/odb/src/db/dbScanPartition.cpp b/src/odb/src/db/dbScanPartition.cpp index ed2d921a518..776b629e731 100644 --- a/src/odb/src/db/dbScanPartition.cpp +++ b/src/odb/src/db/dbScanPartition.cpp @@ -35,7 +35,9 @@ #include "db.h" #include "dbDatabase.h" +#include "dbDft.h" #include "dbDiff.hpp" +#include "dbScanChain.h" #include "dbScanPin.h" #include "dbTable.h" #include "dbTable.hpp" @@ -116,5 +118,72 @@ dbOStream& operator<<(dbOStream& stream, const _dbScanPartition& obj) // //////////////////////////////////////////////////////////////////// +// User Code Begin dbScanPartitionPublicMethods + +void dbScanPartition::setStart(dbBTerm* bterm) +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_partition->start_ = dft->CreateScanPin(bterm); +} + +void dbScanPartition::setStart(dbITerm* iterm) +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_partition->start_ = dft->CreateScanPin(iterm); +} + +void dbScanPartition::setStop(dbBTerm* bterm) +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_partition->stop_ = dft->CreateScanPin(bterm); +} + +void dbScanPartition::setStop(dbITerm* iterm) +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + dbDft* dft = (dbDft*) scan_chain->getOwner(); + scan_partition->stop_ = dft->CreateScanPin(iterm); +} + +std::variant dbScanPartition::getStart() const +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + dbScanPin* scan_pin = (dbScanPin*) dft->scan_pins_->getPtr( + (dbId<_dbScanPin>) scan_partition->start_); + return scan_pin->getPin(); +} + +std::variant dbScanPartition::getStop() const +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); + _dbDft* dft = (_dbDft*) scan_chain->getOwner(); + dbScanPin* scan_pin = (dbScanPin*) dft->scan_pins_->getPtr( + (dbId<_dbScanPin>) scan_partition->stop_); + return scan_pin->getPin(); +} + +std::string_view dbScanPartition::getName() const +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + return scan_partition->name_; +} + +void dbScanPartition::setName(std::string_view name) +{ + _dbScanPartition* scan_partition = (_dbScanPartition*) this; + scan_partition->name_ = name; +} + +// User Code End dbScanPartitionPublicMethods } // namespace odb - // Generator Code End Cpp \ No newline at end of file + // Generator Code End Cpp diff --git a/src/odb/src/db/dbScanPartition.h b/src/odb/src/db/dbScanPartition.h index 17c7bdc8b54..a0832dd6817 100644 --- a/src/odb/src/db/dbScanPartition.h +++ b/src/odb/src/db/dbScanPartition.h @@ -70,4 +70,4 @@ class _dbScanPartition : public _dbObject dbIStream& operator>>(dbIStream& stream, _dbScanPartition& obj); dbOStream& operator<<(dbOStream& stream, const _dbScanPartition& obj); } // namespace odb - // Generator Code End Header \ No newline at end of file + // Generator Code End Header diff --git a/src/odb/src/db/dbScanPin.cpp b/src/odb/src/db/dbScanPin.cpp index 51380bd4896..4af2489182b 100644 --- a/src/odb/src/db/dbScanPin.cpp +++ b/src/odb/src/db/dbScanPin.cpp @@ -34,11 +34,12 @@ #include "dbScanPin.h" #include "db.h" +#include "dbBlock.h" #include "dbDatabase.h" +#include "dbDft.h" #include "dbDiff.hpp" #include "dbTable.h" #include "dbTable.hpp" - // User Code Begin Includes namespace { template @@ -131,15 +132,18 @@ dbOStream& operator<<(dbOStream& stream, const _dbScanPin& obj) std::variant dbScanPin::getPin() const { const _dbScanPin* scan_pin = (_dbScanPin*) this; - const _dbBlock* block = (_dbBlock*) scan_pin->getOwner(); + const _dbDft* dft = (_dbDft*) scan_pin->getOwner(); + const _dbBlock* block = (_dbBlock*) dft->getOwner(); return std::visit( [block](auto&& pin) { using T = std::decay_t; if constexpr (std::is_same_v>) { - return (dbBTerm*) block->_bterm_tbl->getPtr(pin); + return std::variant( + (dbBTerm*) block->_bterm_tbl->getPtr(pin)); } else if constexpr (std::is_same_v>) { - return (dbBTerm*) block->_iterm_tbl->getPtr(pin); + return std::variant( + (dbITerm*) block->_iterm_tbl->getPtr(pin)); } else { static_assert(always_false_v, "non-exhaustive visitor!"); } @@ -150,13 +154,13 @@ std::variant dbScanPin::getPin() const void dbScanPin::setPin(dbBTerm* bterm) { _dbScanPin* scan_pin = (_dbScanPin*) this; - scan_pin->pin_.emplace>(((_dbBTerm*) this)->getId()); + scan_pin->pin_.emplace>(((_dbBTerm*) bterm)->getId()); } void dbScanPin::setPin(dbITerm* iterm) { _dbScanPin* scan_pin = (_dbScanPin*) this; - scan_pin->pin_.emplace>(((_dbITerm*) this)->getId()); + scan_pin->pin_.emplace>(((_dbITerm*) iterm)->getId()); } // User Code End dbScanPinPublicMethods diff --git a/src/odb/src/db/dbScanPin.h b/src/odb/src/db/dbScanPin.h index 84cf20d5b77..3ad6b5e0c51 100644 --- a/src/odb/src/db/dbScanPin.h +++ b/src/odb/src/db/dbScanPin.h @@ -34,7 +34,6 @@ #pragma once #include "dbBTerm.h" -#include "dbBlock.h" #include "dbCore.h" #include "dbITerm.h" #include "odb.h" @@ -47,6 +46,9 @@ class dbIStream; class dbOStream; class dbDiff; class _dbDatabase; +class dbScanPin; +class dbBTerm; +class dbITerm; class _dbScanPin : public _dbObject { diff --git a/src/odb/test/cpp/CMakeLists.txt b/src/odb/test/cpp/CMakeLists.txt index 4be59afa646..577543969c9 100644 --- a/src/odb/test/cpp/CMakeLists.txt +++ b/src/odb/test/cpp/CMakeLists.txt @@ -69,5 +69,5 @@ add_dependencies(build_and_test TestMaster OdbGTests ) - add_subdirectory(helper) +add_subdirectory(scan) diff --git a/src/odb/test/cpp/scan/CMakeLists.txt b/src/odb/test/cpp/scan/CMakeLists.txt new file mode 100644 index 00000000000..6fdb2543226 --- /dev/null +++ b/src/odb/test/cpp/scan/CMakeLists.txt @@ -0,0 +1,27 @@ +include(openroad) + +set(TEST_LIBS + odb + zutil + lef + defin + defout + lefin + lefout + cdl + ${TCL_LIBRARY} + Boost::boost + utl_lib gtest + gmock + gtest_main + odb_test_helper +) + +add_executable(TestScanChain TestScanChain.cpp) +target_link_libraries(TestScanChain ${TEST_LIBS}) + +gtest_discover_tests(TestScanChain + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_dependencies(build_and_test TestScanChain) diff --git a/src/odb/test/cpp/scan/TestScanChain.cpp b/src/odb/test/cpp/scan/TestScanChain.cpp new file mode 100644 index 00000000000..68e5673c4fb --- /dev/null +++ b/src/odb/test/cpp/scan/TestScanChain.cpp @@ -0,0 +1,202 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (c) 2023, Google LLC +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "db.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "helper.h" + +namespace { + +using namespace odb; + +constexpr std::string_view kPartition1 = "CHAIN_1_FALLING_1"; +constexpr std::string_view kPartition2 = "CHAIN_1_RISING_1"; + +template +inline constexpr bool always_false_v = false; + +std::string_view GetName(const std::variant& pin) { + return std::visit([](auto&& pin) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return pin->getName(); + } else if constexpr (std::is_same_v) { + return pin->getMTerm()->getName(); + } else { + static_assert(always_false_v, "non-exhaustive visitor"); + } + }, pin); +} + +class TestScanChain : public testing::Test +{ + protected: + TestScanChain() + { + db_ = create2LevetDbWithBTerms(); + block_ = db_->getChip()->getBlock(); + tmp_path_ = std::string(std::getenv("BASE_DIR")) + "/results/TestScanChain"; + dft_ = block_->createDft(); + + std::vector instances_names = {"i1", "i2", "i3"}; + + for (const auto& name: instances_names) { + instances_.push_back(block_->findInst(name.c_str())); + } + } + + dbDatabase* writeReadDb() + { + writeDb(); + return readDb(); + } + + void writeDb() + { + std::ofstream write; + write.exceptions(std::ifstream::failbit | std::ifstream::badbit + | std::ios::eofbit); + write.open(tmp_path_, std::ios::binary); + db_->write(write); + } + + dbDatabase* readDb() + { + dbDatabase* db = dbDatabase::create(); + std::ifstream read; + read.exceptions(std::ifstream::failbit | std::ifstream::badbit + | std::ios::eofbit); + read.open(tmp_path_, std::ios::binary); + db->read(read); + return db; + } + + dbDatabase* db_; + dbBlock* block_; + std::string tmp_path_; + dbDft* dft_; + std::vector instances_; +}; + +TEST_F(TestScanChain, CreateScanChain) +{ + dbInst* inst = block_->findInst("i1"); + dbITerm* iterm = inst->findITerm("a"); + dbBTerm* bterm = block_->findBTerm("IN1"); + + dbScanChain* scan_chain = dft_->CreateScanChain(); + + dbScanInst* scan_inst = scan_chain->createScanInst(inst); + scan_inst->setBits(1234); + scan_inst->setAccessPins({.scan_in = iterm, .scan_out = bterm}); + + //***************************** + dbDatabase* db2 = writeReadDb(); + dbBlock* block2 = db2->getChip()->getBlock(); + dbDft* dft2 = block2->getDft(); + + odb::dbSet scan_chains2 = dft2->getScanChains(); + EXPECT_THAT(scan_chains2.size(), 1); + + dbScanChain* scan_chain2 = *scan_chains2.begin(); + + odb::dbSet scan_insts2 = scan_chain2->getScanInsts(); + EXPECT_THAT(scan_insts2.size(), 1); +} + +TEST_F(TestScanChain, CreateScanChainWithPartition) +{ + dbScanChain* scan_chain = dft_->CreateScanChain(); + + for (dbInst* inst: instances_) { + dbScanInst* scan_inst = scan_chain->createScanInst(inst); + scan_inst->setBits(1); + dbITerm* iterm = inst->findITerm("a"); + dbITerm* iterm2 = inst->findITerm("o"); + scan_inst->setAccessPins({.scan_in = iterm, .scan_out = iterm2}); + } + + // 2 partitions, one for the first instance and a second one for the second + // instance. The partition 1 start at a bterm (chain scan in) and ends in the + // scan out of the first instance. + // + // The second partition starts at the scan in of the second instance and ends + // in the bterm scan out of the chain. The second partition contains 2 + // elements. + // + // Partition 1: [chain scan_in, i1 scan_out] + // Partition 2: [i2 scan_in, chain scan out] + + dbScanPartition* partition1 = scan_chain->createScanPartition(); + dbScanPartition* partition2 = scan_chain->createScanPartition(); + + dbBTerm* chain_scan_in = block_->findBTerm("IN1"); + dbBTerm* chain_scan_out = block_->findBTerm("IN3"); + + partition1->setStart(chain_scan_in); + partition1->setStop(instances_[0]->findITerm("o")); + partition1->setName(kPartition1); + + partition2->setStart(instances_[1]->findITerm("a")); + partition2->setStop(chain_scan_out); + partition2->setName(kPartition2); + + //***************************** + dbDatabase* db2 = writeReadDb(); + + dbBlock* block2 = db2->getChip()->getBlock(); + dbDft* dft2 = block2->getDft(); + + dbSet scan_chains2 = dft2->getScanChains(); + EXPECT_THAT(scan_chains2.size(), 1); + + dbSet scan_partitions2 = scan_chains2.begin()->getScanPartitions(); + EXPECT_THAT(scan_partitions2.size(), 2); + + auto iterator = scan_partitions2.begin(); + + dbScanPartition* partition12 = *iterator; + ++iterator; + dbScanPartition* partition22 = *iterator; + + EXPECT_THAT(partition12->getName(), kPartition1); + EXPECT_THAT(partition22->getName(), kPartition2); + + EXPECT_THAT(GetName(partition12->getStart()), "IN1"); + EXPECT_THAT(GetName(partition12->getStop()), "o"); + + EXPECT_THAT(GetName(partition22->getStart()), "a"); + EXPECT_THAT(GetName(partition22->getStop()), "IN3"); +} + +} // namespace diff --git a/src/odb/test/data/design.odb b/src/odb/test/data/design.odb index a47c216f635..65e7d432d53 100644 Binary files a/src/odb/test/data/design.odb and b/src/odb/test/data/design.odb differ