From bf027eb9d7ee5cffd776572b0ac6831e424fe3c7 Mon Sep 17 00:00:00 2001 From: Felipe Garay Date: Wed, 3 Apr 2024 17:24:28 -0700 Subject: [PATCH] odb: adding comments to the scan structs Signed-off-by: Felipe Garay --- src/odb/include/odb/db.h | 51 ++++--- src/odb/src/codeGenerator/schema.json | 5 +- .../src/codeGenerator/schema/scan/dbDft.json | 1 + .../schema/scan/dbScanChain.json | 5 + .../codeGenerator/schema/scan/dbScanInst.json | 12 +- .../codeGenerator/schema/scan/dbScanList.json | 9 +- .../schema/scan/dbScanPartition.json | 18 ++- .../codeGenerator/schema/scan/dbScanPin.json | 7 + src/odb/src/codeGenerator/templates/db.h | 5 + src/odb/src/db/dbScanChain.cpp | 20 --- src/odb/src/db/dbScanChain.h | 3 - src/odb/src/db/dbScanInst.cpp | 16 ++- src/odb/src/db/dbScanList.cpp | 5 +- src/odb/src/db/dbScanPartition.cpp | 96 +++++-------- src/odb/src/db/dbScanPartition.h | 11 +- src/odb/test/cpp/scan/TestScanChain.cpp | 126 +++++++----------- 16 files changed, 184 insertions(+), 206 deletions(-) diff --git a/src/odb/include/odb/db.h b/src/odb/include/odb/db.h index 4d6716d7802..25471731721 100644 --- a/src/odb/include/odb/db.h +++ b/src/odb/include/odb/db.h @@ -7091,6 +7091,7 @@ class dbAccessPoint : public dbObject // User Code End dbAccessPoint }; +// Top level DFT (Design for Testing) class class dbDft : public dbObject { public: @@ -7757,13 +7758,16 @@ class dbPowerSwitch : public dbObject // User Code End dbPowerSwitch }; +// A scan chain is a collection of dbScanLists that contains dbScanInsts. Here, +// scan_in, scan_out and scan_enable are the top level ports/pins to where this +// scan chain is connected. Each scan chain is also associated with a +// particular test mode and test mode pin that puts the Circuit Under Test (CUT) +// in test. The Scan Enable port/pin puts the scan chain into shifting mode. class dbScanChain : public dbObject { public: dbSet getScanPartitions() const; - dbSet getScanLists() const; - // User Code Begin dbScanChain const std::string& getName() const; @@ -7792,6 +7796,14 @@ class dbScanChain : public dbObject // User Code End dbScanChain }; +// A scan inst is a cell with a scan in, scan out and an optional scan enable. +// If no scan enable is provided, then this is an stateless component (because +// we don't need to enable scan for it) and the number of bits is set to 0. It +// may be possible that two or more dbScanInst contains the same dbInst if the +// dbInst has more than one scan_in/scan_out pair. Examples of those cases are +// multibit cells with external scan or black boxes. In this case, the scan_in, +// scan_out and scan enables are pins in the dbInst. The scan clock is the pin +// that we use to shift patterns in and out of the scan chain. class dbScanInst : public dbObject { public: @@ -7831,6 +7843,11 @@ class dbScanInst : public dbObject // User Code End dbScanInst }; +// A scan list is a collection of dbScanInsts in a particular order that must be +// respected when performing scan reordering and repartitioning. For ScanList +// with two or more elements we say that they are ORDERED. If the ScanList +// contains only one element then they are FLOATING elements that don't have any +// restriccion when optimizing the scan chain. class dbScanList : public dbObject { public: @@ -7838,34 +7855,34 @@ class dbScanList : public dbObject // User Code Begin dbScanList dbScanInst* add(dbInst* inst); - static dbScanList* create(dbScanChain* scan_chain); + static dbScanList* create(dbScanPartition* scan_partition); // User Code End dbScanList }; +// A scan partition is way to split the scan chains into sub chains with +// compatible scan flops (same clock, edge and voltage). The biggest partition +// possible is the whole chain if all the scan flops inside it are compatible +// between them for reordering and repartitioning. The name of this partition is +// not unique, as multiple partitions may have the same same and therefore +// contain the same type of flops. 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; + dbSet getScanLists() const; + // User Code Begin dbScanPartition const std::string& getName() const; - - void setName(std::string_view name); + void setName(const std::string& name); static dbScanPartition* create(dbScanChain* chain); // User Code End dbScanPartition }; +// This is a helper class to contain dbBTerms and dbITerms in the same field. We +// need this difference because some pins may need to be conected to top level +// ports or cell's pins. For example: a scan chain may be connected to a top +// level design port (dbBTerm) or to an output/input pin of a cell that is part +// of a decompressor/compressor class dbScanPin : public dbObject { public: diff --git a/src/odb/src/codeGenerator/schema.json b/src/odb/src/codeGenerator/schema.json index 59c964a6340..63fa0b54740 100644 --- a/src/odb/src/codeGenerator/schema.json +++ b/src/odb/src/codeGenerator/schema.json @@ -253,7 +253,8 @@ "type":"1_n", "tbl_name":"two_wires_forbidden_spc_rules_tbl_", "schema":"db_schema_lef58_two_wires_forbidden_spacing" - } + }, + { "first": "dbDft", "second": "dbScanPin", "type": "1_n", @@ -267,7 +268,7 @@ "tbl_name": "scan_partitions_" }, { - "first": "dbScanChain", + "first": "dbScanPartition", "second": "dbScanList", "type": "1_n", "tbl_name": "scan_lists_" diff --git a/src/odb/src/codeGenerator/schema/scan/dbDft.json b/src/odb/src/codeGenerator/schema/scan/dbDft.json index 579f8525795..ab7fbfe2cc9 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbDft.json +++ b/src/odb/src/codeGenerator/schema/scan/dbDft.json @@ -1,6 +1,7 @@ { "name": "dbDft", "type": "dbObject", + "description": ["Top level DFT (Design for Testing) class"], "fields": [ { "name": "scan_inserted_", diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanChain.json b/src/odb/src/codeGenerator/schema/scan/dbScanChain.json index ca565760b0b..783c3542690 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanChain.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanChain.json @@ -1,6 +1,11 @@ { "name": "dbScanChain", "type": "dbObject", + "description": ["A scan chain is a collection of dbScanLists that contains dbScanInsts. Here,", + "scan_in, scan_out and scan_enable are the top level ports/pins to where this", + "scan chain is connected. Each scan chain is also associated with a particular", + "test mode and test mode pin that puts the Circuit Under Test (CUT) in test. The", + "Scan Enable port/pin puts the scan chain into shifting mode."], "fields": [ { "name": "name_", diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanInst.json b/src/odb/src/codeGenerator/schema/scan/dbScanInst.json index eb8c416d025..1e005add7a6 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanInst.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanInst.json @@ -1,6 +1,15 @@ { "name": "dbScanInst", "type": "dbObject", + "description": + ["A scan inst is a cell with a scan in, scan out and an optional scan enable. If", + "no scan enable is provided, then this is an stateless component (because we", + "don't need to enable scan for it) and the number of bits is set to 0. It may", + "be possible that two or more dbScanInst contains the same dbInst if the dbInst", + "has more than one scan_in/scan_out pair. Examples of those cases are multibit", + "cells with external scan or black boxes. In this case, the scan_in, scan_out", + "and scan enables are pins in the dbInst. The scan clock is the pin that we use", + "to shift patterns in and out of the scan chain."], "fields": [ { "name": "bits_", @@ -73,6 +82,7 @@ "dbScanPin.h", "dbDft.h", "dbScanChain.h", - "dbScanList.h" + "dbScanList.h", + "dbScanPartition.h" ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanList.json b/src/odb/src/codeGenerator/schema/scan/dbScanList.json index 7c259d554a1..c7dc7371cfb 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanList.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanList.json @@ -1,7 +1,14 @@ { "name": "dbScanList", "type": "dbObject", + "description": [ + "A scan list is a collection of dbScanInsts in a particular order that must be", + "respected when performing scan reordering and repartitioning. For ScanList with", + "two or more elements we say that they are ORDERED. If the ScanList contains only", + "one element then they are FLOATING elements that don't have any restriccion when", + "optimizing the scan chain."], "cpp_includes": [ - "dbScanChain.h" + "dbScanChain.h", + "dbScanPartition.h" ] } diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json b/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json index 16d47805c15..964b9654bb0 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanPartition.json @@ -1,17 +1,15 @@ { "name": "dbScanPartition", "type": "dbObject", + "description": [ + "A scan partition is way to split the scan chains into sub chains with compatible", + "scan flops (same clock, edge and voltage). The biggest partition possible is the", + "whole chain if all the scan flops inside it are compatible between them for", + "reordering and repartitioning. The name of this partition is not unique, as", + "multiple partitions may have the same same and therefore contain the same type", + "of flops." + ], "fields": [ - { - "name": "start_", - "type": "dbId", - "flags": ["private"] - }, - { - "name": "stop_", - "type": "dbId", - "flags": ["private"] - }, { "name": "name_", "type": "std::string", diff --git a/src/odb/src/codeGenerator/schema/scan/dbScanPin.json b/src/odb/src/codeGenerator/schema/scan/dbScanPin.json index 29c4fb83ff0..94e89c6a02e 100644 --- a/src/odb/src/codeGenerator/schema/scan/dbScanPin.json +++ b/src/odb/src/codeGenerator/schema/scan/dbScanPin.json @@ -1,6 +1,13 @@ { "name": "dbScanPin", "type": "dbObject", + "description": [ + "This is a helper class to contain dbBTerms and dbITerms in the same field. We", + "need this difference because some pins may need to be conected to top level", + "ports or cell's pins. For example: a scan chain may be connected to a top level", + "design port (dbBTerm) or to an output/input pin of a cell that is part of a", + "decompressor/compressor" + ], "fields": [ { "name": "pin_", diff --git a/src/odb/src/codeGenerator/templates/db.h b/src/odb/src/codeGenerator/templates/db.h index 04ac32e092e..2ccb19a8234 100644 --- a/src/odb/src/codeGenerator/templates/db.h +++ b/src/odb/src/codeGenerator/templates/db.h @@ -6,6 +6,11 @@ class {{klass.name}}; //Generator Code Begin ClassDefinition {% for klass in schema.classes|sort(attribute='name') %} +{% if klass.description %} + {% for line in klass.description %} + // {{ line }} + {% endfor %} +{% endif %} class {{klass.name}} : public dbObject { public: diff --git a/src/odb/src/db/dbScanChain.cpp b/src/odb/src/db/dbScanChain.cpp index 762988a2473..626f2d2fa07 100644 --- a/src/odb/src/db/dbScanChain.cpp +++ b/src/odb/src/db/dbScanChain.cpp @@ -39,7 +39,6 @@ #include "dbDft.h" #include "dbDiff.hpp" #include "dbScanInst.h" -#include "dbScanList.h" #include "dbScanPartition.h" #include "dbScanPin.h" #include "dbSet.h" @@ -71,9 +70,6 @@ bool _dbScanChain::operator==(const _dbScanChain& rhs) const if (*scan_partitions_ != *rhs.scan_partitions_) { return false; } - if (*scan_lists_ != *rhs.scan_lists_) { - return false; - } return true; } @@ -95,7 +91,6 @@ void _dbScanChain::differences(dbDiff& diff, DIFF_FIELD(test_mode_); DIFF_FIELD(test_mode_name_); DIFF_TABLE(scan_partitions_); - DIFF_TABLE(scan_lists_); DIFF_END } @@ -109,7 +104,6 @@ void _dbScanChain::out(dbDiff& diff, char side, const char* field) const DIFF_OUT_FIELD(test_mode_); DIFF_OUT_FIELD(test_mode_name_); DIFF_OUT_TABLE(scan_partitions_); - DIFF_OUT_TABLE(scan_lists_); DIFF_END } @@ -121,8 +115,6 @@ _dbScanChain::_dbScanChain(_dbDatabase* db) this, (GetObjTbl_t) &_dbScanChain::getObjectTable, dbScanPartitionObj); - scan_lists_ = new dbTable<_dbScanList>( - db, this, (GetObjTbl_t) &_dbScanChain::getObjectTable, dbScanListObj); } _dbScanChain::_dbScanChain(_dbDatabase* db, const _dbScanChain& r) @@ -135,7 +127,6 @@ _dbScanChain::_dbScanChain(_dbDatabase* db, const _dbScanChain& r) test_mode_name_ = r.test_mode_name_; scan_partitions_ = new dbTable<_dbScanPartition>(db, this, *r.scan_partitions_); - scan_lists_ = new dbTable<_dbScanList>(db, this, *r.scan_lists_); } dbIStream& operator>>(dbIStream& stream, _dbScanChain& obj) @@ -147,7 +138,6 @@ dbIStream& operator>>(dbIStream& stream, _dbScanChain& obj) stream >> obj.test_mode_; stream >> obj.test_mode_name_; stream >> *obj.scan_partitions_; - stream >> *obj.scan_lists_; return stream; } @@ -160,7 +150,6 @@ dbOStream& operator<<(dbOStream& stream, const _dbScanChain& obj) stream << obj.test_mode_; stream << obj.test_mode_name_; stream << *obj.scan_partitions_; - stream << *obj.scan_lists_; return stream; } @@ -169,8 +158,6 @@ dbObjectTable* _dbScanChain::getObjectTable(dbObjectType type) switch (type) { case dbScanPartitionObj: return scan_partitions_; - case dbScanListObj: - return scan_lists_; default: break; } @@ -180,7 +167,6 @@ dbObjectTable* _dbScanChain::getObjectTable(dbObjectType type) _dbScanChain::~_dbScanChain() { delete scan_partitions_; - delete scan_lists_; } //////////////////////////////////////////////////////////////////// @@ -195,12 +181,6 @@ dbSet dbScanChain::getScanPartitions() const return dbSet(obj, obj->scan_partitions_); } -dbSet dbScanChain::getScanLists() const -{ - _dbScanChain* obj = (_dbScanChain*) this; - return dbSet(obj, obj->scan_lists_); -} - // User Code Begin dbScanChainPublicMethods const std::string& dbScanChain::getName() const diff --git a/src/odb/src/db/dbScanChain.h b/src/odb/src/db/dbScanChain.h index 9cba7dd6638..0744efcc07a 100644 --- a/src/odb/src/db/dbScanChain.h +++ b/src/odb/src/db/dbScanChain.h @@ -47,7 +47,6 @@ class dbScanPartition; class _dbScanPartition; template class dbTable; -class _dbScanList; class dbScanPin; class _dbScanChain : public _dbObject @@ -80,8 +79,6 @@ class _dbScanChain : public _dbObject std::string test_mode_name_; dbTable<_dbScanPartition>* scan_partitions_; - - dbTable<_dbScanList>* scan_lists_; }; dbIStream& operator>>(dbIStream& stream, _dbScanChain& obj); dbOStream& operator<<(dbOStream& stream, const _dbScanChain& obj); diff --git a/src/odb/src/db/dbScanInst.cpp b/src/odb/src/db/dbScanInst.cpp index 9fb11da7293..a993a43ebbb 100644 --- a/src/odb/src/db/dbScanInst.cpp +++ b/src/odb/src/db/dbScanInst.cpp @@ -39,6 +39,7 @@ #include "dbDiff.hpp" #include "dbScanChain.h" #include "dbScanList.h" +#include "dbScanPartition.h" #include "dbScanPin.h" #include "dbTable.h" #include "dbTable.hpp" @@ -186,7 +187,8 @@ void dbScanInst::setScanEnable(dbITerm* scan_enable) { _dbScanInst* scan_inst = (_dbScanInst*) this; _dbScanList* scan_list = (_dbScanList*) scan_inst->getOwner(); - _dbScanChain* scan_chain = (_dbScanChain*) scan_list->getOwner(); + _dbScanPartition* scan_partition = (_dbScanPartition*) scan_list->getOwner(); + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); dbDft* dft = (dbDft*) scan_chain->getOwner(); scan_inst->scan_enable_ = dbScanPin::create(dft, scan_enable); } @@ -195,7 +197,8 @@ std::variant dbScanInst::getScanEnable() const { _dbScanInst* scan_inst = (_dbScanInst*) this; _dbScanList* scan_list = (_dbScanList*) scan_inst->getOwner(); - _dbScanChain* scan_chain = (_dbScanChain*) scan_list->getOwner(); + _dbScanPartition* scan_partition = (_dbScanPartition*) scan_list->getOwner(); + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); _dbDft* dft = (_dbDft*) scan_chain->getOwner(); const dbScanPin* scan_enable = (dbScanPin*) dft->scan_pins_->getPtr( (dbId<_dbScanPin>) scan_inst->scan_enable_); @@ -216,7 +219,8 @@ void dbScanInst::setAccessPins(const AccessPins& access_pins) { _dbScanInst* scan_inst = (_dbScanInst*) this; _dbScanList* scan_list = (_dbScanList*) scan_inst->getOwner(); - _dbScanChain* scan_chain = (_dbScanChain*) scan_list->getOwner(); + _dbScanPartition* scan_partition = (_dbScanPartition*) scan_list->getOwner(); + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); dbDft* dft = (dbDft*) scan_chain->getOwner(); std::visit( @@ -238,7 +242,8 @@ dbScanInst::AccessPins dbScanInst::getAccessPins() const AccessPins access_pins; _dbScanInst* scan_inst = (_dbScanInst*) this; _dbScanList* scan_list = (_dbScanList*) scan_inst->getOwner(); - _dbScanChain* scan_chain = (_dbScanChain*) scan_list->getOwner(); + _dbScanPartition* scan_partition = (_dbScanPartition*) scan_list->getOwner(); + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); _dbDft* dft = (_dbDft*) scan_chain->getOwner(); const auto& [scan_in_id, scan_out_id] = scan_inst->access_pins_; @@ -258,7 +263,8 @@ dbInst* dbScanInst::getInst() const { _dbScanInst* scan_inst = (_dbScanInst*) this; _dbScanList* scan_list = (_dbScanList*) scan_inst->getOwner(); - _dbScanChain* scan_chain = (_dbScanChain*) scan_list->getOwner(); + _dbScanPartition* scan_partition = (_dbScanPartition*) scan_list->getOwner(); + _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); _dbDft* dft = (_dbDft*) scan_chain->getOwner(); _dbBlock* block = (_dbBlock*) dft->getOwner(); diff --git a/src/odb/src/db/dbScanList.cpp b/src/odb/src/db/dbScanList.cpp index 64ae564b7cd..305730c431c 100644 --- a/src/odb/src/db/dbScanList.cpp +++ b/src/odb/src/db/dbScanList.cpp @@ -38,6 +38,7 @@ #include "dbDiff.hpp" #include "dbScanChain.h" #include "dbScanInst.h" +#include "dbScanPartition.h" #include "dbSet.h" #include "dbTable.h" #include "dbTable.hpp" @@ -132,9 +133,9 @@ dbScanInst* dbScanList::add(dbInst* inst) return dbScanInst::create(this, inst); } -dbScanList* dbScanList::create(dbScanChain* scan_chain) +dbScanList* dbScanList::create(dbScanPartition* scan_partition) { - _dbScanChain* obj = (_dbScanChain*) scan_chain; + _dbScanPartition* obj = (_dbScanPartition*) scan_partition; return (dbScanList*) obj->scan_lists_->create(); } // User Code End dbScanListPublicMethods diff --git a/src/odb/src/db/dbScanPartition.cpp b/src/odb/src/db/dbScanPartition.cpp index 5b651cbc65b..a01647dbcfd 100644 --- a/src/odb/src/db/dbScanPartition.cpp +++ b/src/odb/src/db/dbScanPartition.cpp @@ -38,7 +38,9 @@ #include "dbDft.h" #include "dbDiff.hpp" #include "dbScanChain.h" +#include "dbScanList.h" #include "dbScanPin.h" +#include "dbSet.h" #include "dbTable.h" #include "dbTable.hpp" namespace odb { @@ -46,13 +48,10 @@ template class dbTable<_dbScanPartition>; bool _dbScanPartition::operator==(const _dbScanPartition& rhs) const { - if (start_ != rhs.start_) { - return false; - } - if (stop_ != rhs.stop_) { + if (name_ != rhs.name_) { return false; } - if (name_ != rhs.name_) { + if (*scan_lists_ != *rhs.scan_lists_) { return false; } @@ -69,108 +68,75 @@ void _dbScanPartition::differences(dbDiff& diff, const _dbScanPartition& rhs) const { DIFF_BEGIN - DIFF_FIELD(start_); - DIFF_FIELD(stop_); DIFF_FIELD(name_); + DIFF_TABLE(scan_lists_); DIFF_END } void _dbScanPartition::out(dbDiff& diff, char side, const char* field) const { DIFF_OUT_BEGIN - DIFF_OUT_FIELD(start_); - DIFF_OUT_FIELD(stop_); DIFF_OUT_FIELD(name_); + DIFF_OUT_TABLE(scan_lists_); DIFF_END } _dbScanPartition::_dbScanPartition(_dbDatabase* db) { + scan_lists_ = new dbTable<_dbScanList>( + db, this, (GetObjTbl_t) &_dbScanPartition::getObjectTable, dbScanListObj); } _dbScanPartition::_dbScanPartition(_dbDatabase* db, const _dbScanPartition& r) { - start_ = r.start_; - stop_ = r.stop_; name_ = r.name_; + scan_lists_ = new dbTable<_dbScanList>(db, this, *r.scan_lists_); } dbIStream& operator>>(dbIStream& stream, _dbScanPartition& obj) { - stream >> obj.start_; - stream >> obj.stop_; stream >> obj.name_; + stream >> *obj.scan_lists_; return stream; } dbOStream& operator<<(dbOStream& stream, const _dbScanPartition& obj) { - stream << obj.start_; - stream << obj.stop_; stream << obj.name_; + stream << *obj.scan_lists_; return stream; } -//////////////////////////////////////////////////////////////////// -// -// dbScanPartition - Methods -// -//////////////////////////////////////////////////////////////////// - -// 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_ = dbScanPin::create(dft, bterm); -} - -void dbScanPartition::setStart(dbITerm* iterm) +dbObjectTable* _dbScanPartition::getObjectTable(dbObjectType type) { - _dbScanPartition* scan_partition = (_dbScanPartition*) this; - _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); - dbDft* dft = (dbDft*) scan_chain->getOwner(); - scan_partition->start_ = dbScanPin::create(dft, iterm); + switch (type) { + case dbScanListObj: + return scan_lists_; + default: + break; + } + return getTable()->getObjectTable(type); } -void dbScanPartition::setStop(dbBTerm* bterm) +_dbScanPartition::~_dbScanPartition() { - _dbScanPartition* scan_partition = (_dbScanPartition*) this; - _dbScanChain* scan_chain = (_dbScanChain*) scan_partition->getOwner(); - dbDft* dft = (dbDft*) scan_chain->getOwner(); - scan_partition->stop_ = dbScanPin::create(dft, bterm); + delete scan_lists_; } -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_ = dbScanPin::create(dft, iterm); -} +//////////////////////////////////////////////////////////////////// +// +// dbScanPartition - Methods +// +//////////////////////////////////////////////////////////////////// -std::variant dbScanPartition::getStart() const +dbSet dbScanPartition::getScanLists() 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(); + _dbScanPartition* obj = (_dbScanPartition*) this; + return dbSet(obj, obj->scan_lists_); } -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(); -} +// User Code Begin dbScanPartitionPublicMethods const std::string& dbScanPartition::getName() const { @@ -178,7 +144,7 @@ const std::string& dbScanPartition::getName() const return scan_partition->name_; } -void dbScanPartition::setName(std::string_view name) +void dbScanPartition::setName(const std::string& name) { _dbScanPartition* scan_partition = (_dbScanPartition*) this; scan_partition->name_ = name; diff --git a/src/odb/src/db/dbScanPartition.h b/src/odb/src/db/dbScanPartition.h index a0832dd6817..c91db33286e 100644 --- a/src/odb/src/db/dbScanPartition.h +++ b/src/odb/src/db/dbScanPartition.h @@ -42,7 +42,9 @@ class dbIStream; class dbOStream; class dbDiff; class _dbDatabase; -class dbScanPin; +class _dbScanList; +template +class dbTable; class _dbScanPartition : public _dbObject { @@ -50,7 +52,7 @@ class _dbScanPartition : public _dbObject _dbScanPartition(_dbDatabase*, const _dbScanPartition& r); _dbScanPartition(_dbDatabase*); - ~_dbScanPartition() = default; + ~_dbScanPartition(); bool operator==(const _dbScanPartition& rhs) const; bool operator!=(const _dbScanPartition& rhs) const @@ -62,10 +64,11 @@ class _dbScanPartition : public _dbObject const char* field, const _dbScanPartition& rhs) const; void out(dbDiff& diff, char side, const char* field) const; + dbObjectTable* getObjectTable(dbObjectType type); - dbId start_; - dbId stop_; std::string name_; + + dbTable<_dbScanList>* scan_lists_; }; dbIStream& operator>>(dbIStream& stream, _dbScanPartition& obj); dbOStream& operator<<(dbOStream& stream, const _dbScanPartition& obj); diff --git a/src/odb/test/cpp/scan/TestScanChain.cpp b/src/odb/test/cpp/scan/TestScanChain.cpp index 07fb2344f4e..35e46289c65 100644 --- a/src/odb/test/cpp/scan/TestScanChain.cpp +++ b/src/odb/test/cpp/scan/TestScanChain.cpp @@ -41,8 +41,8 @@ namespace odb { namespace { -constexpr std::string_view kPartition1 = "CHAIN_1_FALLING_1"; -constexpr std::string_view kPartition2 = "CHAIN_1_RISING_1"; +constexpr char kPartition1[] = "CHAIN_1_FALLING_1"; +constexpr char kPartition2[] = "CHAIN_1_RISING_1"; template inline constexpr bool always_false_v = false; @@ -123,7 +123,9 @@ TEST_F(TestScanChain, CreateScanChain) dbScanChain* scan_chain = dbScanChain::create(dft_); - dbScanList* scan_list = dbScanList::create(scan_chain); + dbScanPartition* scan_partition = dbScanPartition::create(scan_chain); + scan_partition->setName(kPartition1); + dbScanList* scan_list = dbScanList::create(scan_partition); dbScanInst* scan_inst = scan_list->add(inst); scan_inst->setBits(1234); @@ -139,7 +141,12 @@ TEST_F(TestScanChain, CreateScanChain) dbScanChain* scan_chain2 = *scan_chains2.begin(); - odb::dbSet scan_lists2 = scan_chain2->getScanLists(); + odb::dbSet scan_partition2 + = scan_chain2->getScanPartitions(); + EXPECT_THAT(scan_partition2.size(), 1); + EXPECT_THAT(scan_partition2.begin()->getName(), kPartition1); + + odb::dbSet scan_lists2 = scan_partition2.begin()->getScanLists(); EXPECT_THAT(scan_lists2.size(), 1); odb::dbSet scan_insts2 = scan_lists2.begin()->getScanInsts(); @@ -149,9 +156,18 @@ TEST_F(TestScanChain, CreateScanChain) TEST_F(TestScanChain, CreateScanChainWithPartition) { dbScanChain* scan_chain = dbScanChain::create(dft_); - dbScanList* scan_list = dbScanList::create(scan_chain); - for (dbInst* inst : instances_) { + std::vector instances_partition1 = {instances_[0], instances_[1]}; + std::vector instances_partition2 = {instances_[2]}; + + dbScanPartition* partition1 = dbScanPartition::create(scan_chain); + dbScanPartition* partition2 = dbScanPartition::create(scan_chain); + + partition1->setName(kPartition1); + partition2->setName(kPartition2); + + for (dbInst* inst : instances_partition1) { + dbScanList* scan_list = dbScanList::create(partition1); dbScanInst* scan_inst = scan_list->add(inst); scan_inst->setBits(1); dbITerm* iterm = inst->findITerm("a"); @@ -159,30 +175,19 @@ TEST_F(TestScanChain, CreateScanChainWithPartition) 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 = dbScanPartition::create(scan_chain); - dbScanPartition* partition2 = dbScanPartition::create(scan_chain); - - 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); + for (dbInst* inst : instances_partition2) { + dbScanList* scan_list = dbScanList::create(partition2); + dbScanInst* scan_inst = scan_list->add(inst); + scan_inst->setBits(1); + dbITerm* iterm = inst->findITerm("a"); + dbITerm* iterm2 = inst->findITerm("o"); + scan_inst->setAccessPins({.scan_in = iterm, .scan_out = iterm2}); + } - partition2->setStart(instances_[1]->findITerm("a")); - partition2->setStop(chain_scan_out); - partition2->setName(kPartition2); + // 2 partitions, one for the first two instances and one for the last one + // + // Partition 1: [i1, i2] + // Partition 2: [i3] //***************************** dbDatabase* db2 = writeReadDb(); @@ -206,62 +211,31 @@ TEST_F(TestScanChain, CreateScanChainWithPartition) 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"); - // check the created instances - dbSet scan_lists2 = scan_chains2.begin()->getScanLists(); - dbSet scan_insts2 = scan_lists2.begin()->getScanInsts(); - - int i = 0; - for (dbScanInst* scan_inst : scan_insts2) { - const dbScanInst::AccessPins& access_pins = scan_inst->getAccessPins(); - EXPECT_THAT(GetName(access_pins.scan_in), "a"); - EXPECT_THAT(GetName(access_pins.scan_out), "o"); - EXPECT_THAT(instances_[i]->getName(), scan_inst->getInst()->getName()); - ++i; - } -} -TEST_F(TestScanChain, CreateScanChainWithMultipleScanLists) -{ - dbScanChain* scan_chain = dbScanChain::create(dft_); - dbScanList* scan_list1 = dbScanList::create(scan_chain); - dbScanList* scan_list2 = dbScanList::create(scan_chain); - - scan_list1->add(instances_[0]); - scan_list2->add(instances_[1]); - scan_list2->add(instances_[2]); - - dbDatabase* db2 = writeReadDb(); - - dbBlock* block2 = db2->getChip()->getBlock(); - dbDft* dft2 = block2->getDft(); - - dbSet scan_chains2 = dft2->getScanChains(); - EXPECT_THAT(scan_chains2.size(), 1); - // check the created instances - dbSet scan_lists2 = scan_chains2.begin()->getScanLists(); - EXPECT_THAT(scan_lists2.size(), 2); + dbSet scan_lists12 = partition12->getScanLists(); + dbSet scan_lists22 = partition22->getScanLists(); int i = 0; - for (dbScanList* scan_list : scan_lists2) { + for (dbScanList* scan_list : scan_lists12) { for (dbScanInst* scan_inst : scan_list->getScanInsts()) { - EXPECT_THAT(scan_inst->getInst()->getName(), instances_[i]->getName()); + const dbScanInst::AccessPins& access_pins = scan_inst->getAccessPins(); + EXPECT_THAT(GetName(access_pins.scan_in), "a"); + EXPECT_THAT(GetName(access_pins.scan_out), "o"); + EXPECT_THAT(instances_[i]->getName(), scan_inst->getInst()->getName()); ++i; } } - auto it = scan_lists2.begin(); - dbScanList* scan_list21 = *it; - ++it; - dbScanList* scan_list22 = *it; - - EXPECT_THAT(scan_list21->getScanInsts().size(), 1); - EXPECT_THAT(scan_list22->getScanInsts().size(), 2); + for (dbScanList* scan_list : scan_lists22) { + for (dbScanInst* scan_inst : scan_list->getScanInsts()) { + const dbScanInst::AccessPins& access_pins = scan_inst->getAccessPins(); + EXPECT_THAT(GetName(access_pins.scan_in), "a"); + EXPECT_THAT(GetName(access_pins.scan_out), "o"); + EXPECT_THAT(instances_[i]->getName(), scan_inst->getInst()->getName()); + ++i; + } + } } } // namespace