Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dft: implementing interface to support different test modes #6533

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions src/dft/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ target_link_libraries(dft
dft_clock_domain_lib
dft_utils_lib
dft_stitch_lib
dft_utils_macros_lib
)


Expand Down
28 changes: 25 additions & 3 deletions src/dft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,33 @@ A simple DFT insertion consist of the following parts:
- Parameters without square brackets `-param2 param2` are required.
```

### Create a test mode

You can create test modes with the command ```create_dft_test_mode```. Each test
mode is architected and stitched independenly.

```{note}
Usually, you can select what cells or subset of the scan cells you can to be in
each test mode. This is currently not implemented as this is WIP.
```

```tcl
create_dft_test_mode
[-test_mode <string>]
```

| Switch Name | Description |
| ---- | ---- |
| `-test_mode` | The name of the test mode to create. |


### Set DFT Config

The command `set_dft_config` sets the DFT configuration variables.

```tcl
set_dft_config
[-test_mode <string>]
[-max_length <int>]
[-max_chains <int>]
[-clock_mixing <string>]
Expand All @@ -35,9 +56,10 @@ set_dft_config

#### Options

| Switch Name | Description |
| ---- | ---- |
| `-max_length` | The maximum number of bits that can be in each scan chain. |
| Switch Name | Description |
| ---- | ---- |
| `-test_mode` | The test mode where to apply this config. By default it will apply the config to the "default" test mode. |
| `-max_length` | The maximum number of bits that can be in each scan chain. |
| `-max_chains` | The maximum number of scan chains that will be generated. This takes priority over `max_length`,
in `no_mix` clock mode it specifies a maximum number of chains per clock-edge pair. |
| `-clock_mixing` | How architect will mix the scan flops based on the clock driver. `no_mix`: Creates scan chains with only one type of clock and edge. This may create unbalanced chains. `clock_mix`: Creates scan chains mixing clocks and edges. Falling edge flops are going to be stitched before rising edge. |
Expand Down
8 changes: 8 additions & 0 deletions src/dft/include/dft/Dft.hh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#pragma once

#include "ClockDomain.hh"
#include "TestModeConfig.hh"
#include "db_sta/dbSta.hh"
#include "odb/db.h"
#include "utl/Logger.h"
Expand Down Expand Up @@ -118,6 +119,13 @@ class Dft
// preview_dft and insert_dft
std::vector<std::unique_ptr<ScanChain>> scanArchitect();

std::vector<std::unique_ptr<ScanChain>> scanArchitect(
const TestModeConfig& test_mode_config);

void previewDft(const TestModeConfig& test_mode_config, bool verbose);

void insertDft(const TestModeConfig& test_mode_config);

// Global state
odb::dbDatabase* db_;
sta::dbSta* sta_;
Expand Down
44 changes: 35 additions & 9 deletions src/dft/src/Dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,32 @@ void Dft::pre_dft()
}

void Dft::previewDft(bool verbose)
{
dft_config_->validate(logger_);

for (const auto& [test_mode, test_mode_config] :
dft_config_->getTestModesConfig()) {
previewDft(test_mode_config, verbose);
}
}

void Dft::previewDft(const TestModeConfig& test_mode_config, bool verbose)
{
if (need_to_run_pre_dft_) {
pre_dft();
}

std::vector<std::unique_ptr<ScanChain>> scan_chains = scanArchitect();
std::vector<std::unique_ptr<ScanChain>> scan_chains
= scanArchitect(test_mode_config);

logger_->report("***************************");
logger_->report("Preview DFT Report");
logger_->report("Test mode: {:s}", test_mode_config.getName());
logger_->report("Number of chains: {:d}", scan_chains.size());
logger_->report("Clock domain: {:s}",
ScanArchitectConfig::ClockMixingName(
dft_config_->getScanArchitectConfig().getClockMixing()));
logger_->report(
"Clock domain: {:s}",
ScanArchitectConfig::ClockMixingName(
test_mode_config.getScanArchitectConfig().getClockMixing()));
logger_->report("***************************\n");
for (const auto& scan_chain : scan_chains) {
scan_chain->report(logger_, verbose);
Expand All @@ -112,13 +125,24 @@ void Dft::scanReplace()
}

void Dft::insertDft()
{
dft_config_->validate(logger_);

// iterate and call per test mode
for (const auto& [_, test_mode_config] : dft_config_->getTestModesConfig()) {
insertDft(test_mode_config);
}
}

void Dft::insertDft(const TestModeConfig& test_mode_config)
{
if (need_to_run_pre_dft_) {
pre_dft();
}
std::vector<std::unique_ptr<ScanChain>> scan_chains = scanArchitect();
std::vector<std::unique_ptr<ScanChain>> scan_chains
= scanArchitect(test_mode_config);

ScanStitch stitch(db_, logger_, dft_config_->getScanStitchConfig());
ScanStitch stitch(db_, logger_, test_mode_config.getScanStitchConfig());
stitch.Stitch(scan_chains);

// Write scan chains to odb
Expand Down Expand Up @@ -179,19 +203,21 @@ void Dft::reportDftConfig() const
dft_config_->report(logger_);
}

std::vector<std::unique_ptr<ScanChain>> Dft::scanArchitect()
std::vector<std::unique_ptr<ScanChain>> Dft::scanArchitect(
const TestModeConfig& test_mode_config)
{
std::vector<std::unique_ptr<ScanCell>> scan_cells
= CollectScanCells(db_, sta_, logger_);

// Scan Architect
std::unique_ptr<ScanCellsBucket> scan_cells_bucket
= std::make_unique<ScanCellsBucket>(logger_);
scan_cells_bucket->init(dft_config_->getScanArchitectConfig(), scan_cells);
scan_cells_bucket->init(test_mode_config.getScanArchitectConfig(),
scan_cells);

std::unique_ptr<ScanArchitect> scan_architect
= ScanArchitect::ConstructScanScanArchitect(
dft_config_->getScanArchitectConfig(),
test_mode_config.getScanArchitectConfig(),
std::move(scan_cells_bucket),
logger_);
scan_architect->init();
Expand Down
1 change: 1 addition & 0 deletions src/dft/src/architect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ target_link_libraries(dft_architect_lib
dft_clock_domain_hash_lib
dft_config_lib
dft_utils_scan_pin_lib
dft_utils_macros_lib
)

target_link_libraries(dft_architect_lib
Expand Down
9 changes: 3 additions & 6 deletions src/dft/src/architect/ScanArchitect.hh
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,17 @@
#include "ScanCell.hh"
#include "ScanChain.hh"
#include "utl/Logger.h"
#include "Macros.hh"

namespace dft {

// Contains all the scan cells of the design and maintains them separated based
// on the hash domain.
class ScanCellsBucket
{
DISABLE_COPY_AND_MOVE(ScanCellsBucket);
public:
explicit ScanCellsBucket(utl::Logger* logger);
// Not copyable or movable
ScanCellsBucket(const ScanCellsBucket&) = delete;
ScanCellsBucket& operator=(const ScanCellsBucket&) = delete;

// Gets the next scan cell of the given hash domain
std::unique_ptr<ScanCell> pop(size_t hash_domain);
Expand All @@ -74,6 +73,7 @@ class ScanCellsBucket
// The Scan Architect. We can implement different algorithms to architect
class ScanArchitect
{
DISABLE_COPY_AND_MOVE(ScanArchitect);
public:
// The limits of a hash domain.
struct HashDomainLimits
Expand All @@ -85,9 +85,6 @@ class ScanArchitect

ScanArchitect(const ScanArchitectConfig& config,
std::unique_ptr<ScanCellsBucket> scan_cells_bucket);
// Not copyable or movable
ScanArchitect(const ScanArchitect&) = delete;
ScanArchitect& operator=(const ScanArchitect&) = delete;
virtual ~ScanArchitect() = default;

// Init the Scan Architect
Expand Down
6 changes: 2 additions & 4 deletions src/dft/src/architect/ScanArchitectHeuristic.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "ScanArchitect.hh"
#include "utl/Logger.h"
#include "Macros.hh"

namespace dft {

Expand All @@ -41,14 +42,11 @@ namespace dft {
// the smallest and start adding the biggest cells to each scan chain.
class ScanArchitectHeuristic : public ScanArchitect
{
DISABLE_COPY_AND_MOVE(ScanArchitectHeuristic);
public:
ScanArchitectHeuristic(const ScanArchitectConfig& config,
std::unique_ptr<ScanCellsBucket> scan_cells_bucket,
utl::Logger* logger);
// Not copyable or movable
ScanArchitectHeuristic(const ScanArchitectHeuristic&) = delete;
ScanArchitectHeuristic& operator=(const ScanArchitectHeuristic&) = delete;
~ScanArchitectHeuristic() override = default;

void architect() override;

Expand Down
5 changes: 2 additions & 3 deletions src/dft/src/architect/ScanChain.hh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include "ScanCell.hh"
#include "utl/Logger.h"
#include "Macros.hh"

namespace dft {

Expand All @@ -50,11 +51,9 @@ namespace dft {
// - Find the scan enable of the chain
class ScanChain
{
DISABLE_COPY_AND_MOVE(ScanChain);
public:
explicit ScanChain(const std::string& name);
// Not copyable or movable
ScanChain(const ScanChain&) = delete;
ScanChain& operator=(const ScanChain&) = delete;

// Adds a scan cell to the chain. Depending on the edge of the cell, we will
// move the cell to rising or falling vectors.
Expand Down
2 changes: 2 additions & 0 deletions src/dft/src/cells/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ target_link_libraries(dft_cells_lib
dft_clock_domain_lib
dft_config_lib
dft_utils_lib
dft_utils_macros_lib
)

target_include_directories(dft_cells_lib
Expand All @@ -30,6 +31,7 @@ target_link_libraries(dft_base_scan_cell_lib
dft_clock_domain_lib
dft_config_lib
dft_utils_scan_pin_lib
dft_utils_macros_lib
)

target_include_directories(dft_base_scan_cell_lib
Expand Down
5 changes: 2 additions & 3 deletions src/dft/src/cells/OneBitScanCell.hh
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,21 @@
#include "db_sta/dbNetwork.hh"
#include "odb/db.h"
#include "sta/Liberty.hh"
#include "Macros.hh"

namespace dft {

// A simple single cell with just one bit. Usually one scan FF
class OneBitScanCell : public ScanCell
{
DISABLE_COPY_AND_MOVE(OneBitScanCell);
public:
OneBitScanCell(const std::string& name,
std::unique_ptr<ClockDomain> clock_domain,
odb::dbInst* inst,
sta::TestCell* test_cell,
sta::dbNetwork* db_network,
utl::Logger* logger);
// Not copyable or movable
OneBitScanCell(const OneBitScanCell&) = delete;
OneBitScanCell& operator=(const OneBitScanCell&) = delete;

uint64_t getBits() const override;
void connectScanEnable(const ScanDriver& driver) const override;
Expand Down
5 changes: 2 additions & 3 deletions src/dft/src/cells/ScanCell.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "ScanPin.hh"
#include "odb/db.h"
#include "utl/Logger.h"
#include "Macros.hh"

namespace dft {
class ClockDomain;
Expand All @@ -51,14 +52,12 @@ class ClockDomain;
// in the future black boxes or CTLs (Core Test Language)
class ScanCell
{
DISABLE_COPY_AND_MOVE(ScanCell);
public:
ScanCell(const std::string& name,
std::unique_ptr<ClockDomain> clock_domain,
utl::Logger* logger);
virtual ~ScanCell() = default;
// Not copyable or movable
ScanCell(const ScanCell&) = delete;
ScanCell& operator=(const ScanCell&) = delete;

virtual uint64_t getBits() const = 0;
virtual void connectScanEnable(const ScanDriver& driver) const = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/dft/src/clock_domain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target_link_libraries(dft_clock_domain_lib
PRIVATE
utl_lib
dft_config_lib
dft_utils_macros_lib
)

add_library(dft_clock_domain_hash_lib
Expand All @@ -25,4 +26,5 @@ target_link_libraries(dft_clock_domain_hash_lib
utl_lib
dft_config_lib
dft_clock_domain_lib
dft_utils_macros_lib
)
5 changes: 2 additions & 3 deletions src/dft/src/clock_domain/ClockDomain.hh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#pragma once

#include <string>
#include "Macros.hh"

namespace dft {

Expand All @@ -44,11 +45,9 @@ enum class ClockEdge
// The clock domain of the scan cells based on the clock name and the edge.
class ClockDomain
{
DISABLE_COPY_AND_MOVE(ClockDomain);
public:
ClockDomain(const std::string& clock_name, ClockEdge clock_edge);
// Allow move, copy is implicitly deleted
ClockDomain(ClockDomain&& other) = default;
ClockDomain& operator=(ClockDomain&& other) = default;

std::string_view getClockName() const;
ClockEdge getClockEdge() const;
Expand Down
2 changes: 2 additions & 0 deletions src/dft/src/config/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_library(dft_config_lib
# Keep sorted
DftConfig.cpp
TestModeConfig.cpp
ScanArchitectConfig.cpp
ScanStitchConfig.cpp
)
Expand All @@ -15,4 +16,5 @@ target_link_libraries(dft_config_lib
odb
utl_lib
dft_utils_formatting_lib
dft_utils_macros_lib
)
Loading
Loading