Skip to content

Commit

Permalink
dft: implementing interface to support different test modes
Browse files Browse the repository at this point in the history
This is a refactoring change + public API change where we start
supporting different tests modes. The test mode currently does nothing
except for independendly architect and stitch each test mode.

In the future, different tests modes may have different types of scan
(ex: internal scan, scan compression, boundary scan, etc) and may
support to include/exclude cells in certain modes.

Signed-off-by: Felipe Garay <[email protected]>
  • Loading branch information
fgaray committed Jan 14, 2025
1 parent d7c0c81 commit 438d3a9
Show file tree
Hide file tree
Showing 19 changed files with 337 additions and 63 deletions.
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
40 changes: 31 additions & 9 deletions src/dft/src/Dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,30 @@ void Dft::pre_dft()
}

void Dft::previewDft(bool verbose)
{
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 +123,22 @@ void Dft::scanReplace()
}

void Dft::insertDft()
{
// 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 +199,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/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 Down
46 changes: 30 additions & 16 deletions src/dft/src/config/DftConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,47 @@

namespace dft {

ScanArchitectConfig* DftConfig::getMutableScanArchitectConfig()
{
return &scan_architect_config_;
}
namespace {
constexpr std::string_view kDefaultTestModeName = "default";
} // namespace

const ScanArchitectConfig& DftConfig::getScanArchitectConfig() const
void DftConfig::report(utl::Logger* logger) const
{
return scan_architect_config_;
logger->report("***************************");
logger->report("DFT Config Report:\n");

for (const auto& [test_mode, test_mode_config] : test_modes_config_) {
logger->report("\nTest mode: {}", test_mode);
test_mode_config.report(logger);
}

logger->report("***************************");
}

ScanStitchConfig* DftConfig::getMutableScanStitchConfig()
TestModeConfig* DftConfig::createTestMode(const std::string& name)
{
return &scan_stitch_config_;
auto pair = test_modes_config_.try_emplace(name, name);
return &pair.first->second;
}

const ScanStitchConfig& DftConfig::getScanStitchConfig() const
TestModeConfig* DftConfig::getOrDefaultMutableTestModeConfig(
const std::string& name)
{
return scan_stitch_config_;
auto found = test_modes_config_.find(name);
if (found == test_modes_config_.end()) {
if (name == kDefaultTestModeName) {
return createTestMode(name);
} else {
return nullptr;
}
}
return &found->second;
}

void DftConfig::report(utl::Logger* logger) const
const std::unordered_map<std::string, TestModeConfig>&
DftConfig::getTestModesConfig() const
{
logger->report("***************************");
logger->report("DFT Config Report:\n");
scan_architect_config_.report(logger);
scan_stitch_config_.report(logger);
logger->report("***************************");
return test_modes_config_;
}

} // namespace dft
19 changes: 10 additions & 9 deletions src/dft/src/config/DftConfig.hh
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include "ScanArchitectConfig.hh"
#include "ScanStitchConfig.hh"
#include <unordered_map>

#include "TestModeConfig.hh"
#include "utl/Logger.h"

namespace dft {
Expand All @@ -47,18 +48,18 @@ class DftConfig
DftConfig(const DftConfig&) = delete;
DftConfig& operator=(const DftConfig&) = delete;

ScanArchitectConfig* getMutableScanArchitectConfig();
const ScanArchitectConfig& getScanArchitectConfig() const;

ScanStitchConfig* getMutableScanStitchConfig();
const ScanStitchConfig& getScanStitchConfig() const;
TestModeConfig* createTestMode(const std::string& name);
TestModeConfig* getOrDefaultMutableTestModeConfig(const std::string& name);
const std::unordered_map<std::string, TestModeConfig>& getTestModesConfig()
const;

// Prints the information currently being used by DFT for config
void report(utl::Logger* logger) const;

private:
ScanArchitectConfig scan_architect_config_;
ScanStitchConfig scan_stitch_config_;
// A DFT config can have multiple test modes. If no test mode was defined by
// the user, then we use the "default" test mode.
std::unordered_map<std::string, TestModeConfig> test_modes_config_;
};

} // namespace dft
2 changes: 2 additions & 0 deletions src/dft/src/config/ScanArchitectConfig.hh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ScanArchitectConfig
ClockMix // We architect the flops of different clock and edge together
};

ScanArchitectConfig() : clock_mixing_(ClockMixing::NoMix) {}

void setClockMixing(ClockMixing clock_mixing);

// The max length in bits that a scan chain can have
Expand Down
68 changes: 68 additions & 0 deletions src/dft/src/config/TestModeConfig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2025, 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 "TestModeConfig.hh"

namespace dft {

ScanArchitectConfig* TestModeConfig::getMutableScanArchitectConfig()
{
return &scan_architect_config_;
}

const ScanArchitectConfig& TestModeConfig::getScanArchitectConfig() const
{
return scan_architect_config_;
}

ScanStitchConfig* TestModeConfig::getMutableScanStitchConfig()
{
return &scan_stitch_config_;
}

const ScanStitchConfig& TestModeConfig::getScanStitchConfig() const
{
return scan_stitch_config_;
}

void TestModeConfig::report(utl::Logger* logger) const
{
scan_architect_config_.report(logger);
scan_stitch_config_.report(logger);
}

const std::string& TestModeConfig::getName() const
{
return name_;
}

} // namespace dft
Loading

0 comments on commit 438d3a9

Please sign in to comment.