Skip to content

Commit

Permalink
dft: make ScanPin copyable, remove per-chain enables
Browse files Browse the repository at this point in the history
misc. gardening to the abseil codex
  • Loading branch information
donn committed Jan 8, 2025
1 parent 6c7bda7 commit 9b51d2b
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 155 deletions.
8 changes: 3 additions & 5 deletions src/dft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ set_dft_config
[-max_length <int>]
[-max_chains <int>]
[-clock_mixing <string>]
[-scan_enable_mode <string>]
[-scan_enable_name_pattern <string>]
[-scan_in_name_pattern <string>]
[-scan_out_name_pattern <string>]
Expand All @@ -42,10 +41,9 @@ set_dft_config
| `-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. |
| `-scan_enable_mode` | Experimental: how the scan chain enable signals will be created/assigned by the scan chain stitcher. `global`: All scan chains use the same enable signal. `per_chain`: Each scan chain gets assigned or created its own scan enanle. The default is `global`. |
| `-scan_enable_name_pattern` | A format pattern with exactly one set of braces (`{}`) to use to find or create scan enable drivers during scan chain stitching. The braces will be replaced with the chain's ordinal number (starting at `0`) if `-scan_enable_mode` is set to `per_chain`, otherwise, all will share `0`. If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |
| `-scan_in_name_pattern` | A format pattern with exactly one set of braces (`{}`) to use to find or create scan in drivers during scan chain stitching. The braces will be replaced with the chain's ordinal number (starting at `0`). If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |
| `-scan_out_name_pattern` | A format pattern with exactly one set of braces (`{}`) to use to find or create scan in loads during scan chain stitching. The braces will be replaced with the chain's ordinal number (starting at `0`). If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |
| `-scan_enable_name_pattern` | A format pattern with one or less set of braces (`{}`) to use to find or create scan enable drivers during scan chain stitching. The braces, if found, will be set to `0` as DFT architectures typically use a single shift-enable for all scan chains. If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |
| `-scan_in_name_pattern` | A format pattern with one or less braces (`{}`) to use to find or create scan in drivers during scan chain stitching. The braces will be replaced with the chain's ordinal number (starting at `0`). If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |
| `-scan_out_name_pattern` | A format pattern with one or less braces (`{}`) to use to find or create scan in loads during scan chain stitching. The braces will be replaced with the chain's ordinal number (starting at `0`). If an un-escaped forward slash (`/`) is found, instead of searching for and/or creating a top-level port, an instance's pin will be searched for instead where the part of the string preceding the `/` is interpreted as the instance name and part succeeding it will be interpreted as the pin's name. |

### Report DFT Config

Expand Down
34 changes: 21 additions & 13 deletions src/dft/src/Dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
#include "odb/db.h"
#include "utl/Logger.h"

namespace {
constexpr char kDefaultPartition[] = "default";
} // namespace

namespace dft {

Expand Down Expand Up @@ -122,14 +124,14 @@ void Dft::insertDft()
odb::dbBlock* db_block = db_->getChip()->getBlock();
odb::dbDft* db_dft = db_block->getDft();

for (auto& chain : scan_chains) {
for (const auto& chain : scan_chains) {
odb::dbScanChain* db_sc = odb::dbScanChain::create(db_dft);
db_sc->setName(chain->getName());
odb::dbScanPartition* db_part = odb::dbScanPartition::create(db_sc);
db_part->setName(kDefaultPartition);
odb::dbScanList* db_scanlist = odb::dbScanList::create(db_part);

for (auto& scan_cell : chain->getScanCells()) {
for (const auto& scan_cell : chain->getScanCells()) {
std::string inst_name(scan_cell->getName());
odb::dbInst* db_inst = db_block->findInst(inst_name.c_str());
odb::dbScanInst* db_scaninst = db_scanlist->add(db_inst);
Expand All @@ -140,17 +142,23 @@ void Dft::insertDft()
{.scan_in = scan_in_term, .scan_out = scan_out_term});
}

ScanDriver sc_enable_driver = chain->getScanEnable();
ScanDriver sc_in_driver = chain->getScanIn();
ScanLoad sc_out_load = chain->getScanOut();

std::visit(
[&](auto&& sc_enable_term) { db_sc->setScanEnable(sc_enable_term); },
sc_enable_driver.getValue());
std::visit([&](auto&& sc_in_term) { db_sc->setScanIn(sc_in_term); },
sc_in_driver.getValue());
std::visit([&](auto&& sc_out_term) { db_sc->setScanOut(sc_out_term); },
sc_out_load.getValue());
std::optional<ScanDriver> sc_enable_driver = chain->getScanEnable();
std::optional<ScanDriver> sc_in_driver = chain->getScanIn();
std::optional<ScanLoad> sc_out_load = chain->getScanOut();

if (sc_enable_driver.has_value()) {
std::visit(
[&](auto&& sc_enable_term) { db_sc->setScanEnable(sc_enable_term); },
sc_enable_driver.value().getValue());
}
if (sc_in_driver.has_value()) {
std::visit([&](auto&& sc_in_term) { db_sc->setScanIn(sc_in_term); },
sc_in_driver.value().getValue());
}
if (sc_out_load.has_value()) {
std::visit([&](auto&& sc_out_term) { db_sc->setScanOut(sc_out_term); },
sc_out_load.value().getValue());
}
}
}

Expand Down
24 changes: 12 additions & 12 deletions src/dft/src/architect/ScanChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,30 +119,30 @@ const std::string& ScanChain::getName() const
return name_;
}

ScanDriver ScanChain::getScanIn() const
std::optional<ScanDriver> ScanChain::getScanIn() const
{
return ScanDriver(scan_in_);
return scan_in_;
}
ScanDriver ScanChain::getScanEnable() const
std::optional<ScanDriver> ScanChain::getScanEnable() const
{
return ScanDriver(scan_enable_);
return scan_enable_;
}
ScanLoad ScanChain::getScanOut() const
std::optional<ScanLoad> ScanChain::getScanOut() const
{
return ScanLoad(scan_out_);
return scan_out_;
}

void ScanChain::setScanIn(const ScanDriver& signal)
void ScanChain::setScanIn(const std::optional<ScanDriver>& signal)
{
scan_in_ = signal.getValue();
scan_in_ = signal;
}
void ScanChain::setScanEnable(const ScanDriver& signal)
void ScanChain::setScanEnable(const std::optional<ScanDriver>& signal)
{
scan_enable_ = signal.getValue();
scan_enable_ = signal;
}
void ScanChain::setScanOut(const ScanLoad& signal)
void ScanChain::setScanOut(const std::optional<ScanLoad>& signal)
{
scan_out_ = signal.getValue();
scan_out_ = signal;
}

} // namespace dft
20 changes: 9 additions & 11 deletions src/dft/src/architect/ScanChain.hh
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ class ScanChain
const std::string& getName() const;

// For stitchers
ScanDriver getScanIn() const;
ScanDriver getScanEnable() const;
ScanLoad getScanOut() const;
std::optional<ScanDriver> getScanIn() const;
std::optional<ScanDriver> getScanEnable() const;
std::optional<ScanLoad> getScanOut() const;

void setScanIn(const ScanDriver& signal);
void setScanEnable(const ScanDriver& signal);
void setScanOut(const ScanLoad& signal);
void setScanIn(const std::optional<ScanDriver>& signal);
void setScanEnable(const std::optional<ScanDriver>& signal);
void setScanOut(const std::optional<ScanLoad>& signal);

private:
std::string name_;
Expand All @@ -106,11 +106,9 @@ class ScanChain
uint64_t bits_;

// After stitching: store input/output bterms/iterms
std::variant<odb::dbBTerm*, odb::dbITerm*> scan_in_ = (odb::dbBTerm*) nullptr;
std::variant<odb::dbBTerm*, odb::dbITerm*> scan_out_
= (odb::dbBTerm*) nullptr;
std::variant<odb::dbBTerm*, odb::dbITerm*> scan_enable_
= (odb::dbBTerm*) nullptr;
std::optional<ScanDriver> scan_in_;
std::optional<ScanLoad> scan_out_;
std::optional<ScanDriver> scan_enable_;
};

} // namespace dft
29 changes: 3 additions & 26 deletions src/dft/src/config/ScanStitchConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
namespace dft {

void ScanStitchConfig::setEnableNamePattern(
std::string_view& enable_name_pattern)
std::string_view enable_name_pattern)
{
enable_name_pattern_ = enable_name_pattern;
}
Expand All @@ -46,7 +46,7 @@ std::string_view ScanStitchConfig::getEnableNamePattern() const
return enable_name_pattern_;
};

void ScanStitchConfig::setInNamePattern(std::string_view& in_name_pattern)
void ScanStitchConfig::setInNamePattern(std::string_view in_name_pattern)
{
in_name_pattern_ = in_name_pattern;
};
Expand All @@ -55,7 +55,7 @@ std::string_view ScanStitchConfig::getInNamePattern() const
return in_name_pattern_;
};

void ScanStitchConfig::setOutNamePattern(std::string_view& out_name_pattern)
void ScanStitchConfig::setOutNamePattern(std::string_view out_name_pattern)
{
out_name_pattern_ = out_name_pattern;
};
Expand All @@ -64,32 +64,9 @@ std::string_view ScanStitchConfig::getOutNamePattern() const
return out_name_pattern_;
};

void ScanStitchConfig::setEnableMode(ScanStitchConfig::EnableMode enable_mode)
{
enable_mode_ = enable_mode;
}
ScanStitchConfig::EnableMode ScanStitchConfig::getEnableMode() const
{
return enable_mode_;
}

std::string_view ScanStitchConfig::EnableModeName(
ScanStitchConfig::EnableMode enable_mode)
{
switch (enable_mode) {
case ScanStitchConfig::EnableMode::Global:
return "Global";
case ScanStitchConfig::EnableMode::PerChain:
return "Per-Chain";
default:
return "ScanStitchConfig::EnableMode missing case";
}
}

void ScanStitchConfig::report(utl::Logger* logger) const
{
logger->report("Scan Stitch Config:");
logger->report("- Enable Mode: '{}'", EnableModeName(enable_mode_));
logger->report("- Scan Enable Name Pattern: '{}'", enable_name_pattern_);
logger->report("- Scan In Name Pattern: '{}'", in_name_pattern_);
logger->report("- Scan Out Name Pattern: '{}'", out_name_pattern_);
Expand Down
18 changes: 3 additions & 15 deletions src/dft/src/config/ScanStitchConfig.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,22 @@ namespace dft {
class ScanStitchConfig
{
public:
enum class EnableMode
{
Global = 0,
PerChain
};

static std::string_view EnableModeName(EnableMode enable_mode);

void setEnableNamePattern(std::string_view& enable_name_pattern);
void setEnableNamePattern(std::string_view enable_name_pattern);
std::string_view getEnableNamePattern() const;

void setInNamePattern(std::string_view& in_name_pattern);
void setInNamePattern(std::string_view in_name_pattern);
std::string_view getInNamePattern() const;

void setOutNamePattern(std::string_view& out_name_pattern);
void setOutNamePattern(std::string_view out_name_pattern);
std::string_view getOutNamePattern() const;

void setEnableMode(EnableMode enable_mode);
EnableMode getEnableMode() const;

// Prints using logger->report the config used by Scan Stitch
void report(utl::Logger* logger) const;

private:
std::string enable_name_pattern_ = "scan_enable_{}";
std::string in_name_pattern_ = "scan_in_{}";
std::string out_name_pattern_ = "scan_out_{}";
EnableMode enable_mode_ = EnableMode::Global;
};

} // namespace dft
49 changes: 1 addition & 48 deletions src/dft/src/dft.i
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,6 @@ utl::Logger* getLogger()

%include "../../Exception.i"

// Enum: dft::ResetActiveEdge
%typemap(typecheck) dft::ResetActiveEdge {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "LOW") == 0) {
$1 = 1;
} else if (strcasecmp(str, "HIGH") == 0) {
$1 = 1;
} else {
$1 = 0;
}
}

%typemap(in) dft::ResetActiveEdge {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "LOW") == 0) {
$1 = dft::ResetActiveEdge::Low;
} else /* other values eliminated in typecheck */ {
$1 = dft::ResetActiveEdge::High;
};
}

// Enum: dft::ClockEdge
%typemap(typecheck) dft::ClockEdge {
char *str = Tcl_GetStringFromObj($input, 0);
Expand Down Expand Up @@ -117,27 +96,6 @@ utl::Logger* getLogger()
};
}

// Enum: dft::EnableMode
%typemap(typecheck) dft::ScanStitchConfig::EnableMode {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "GLOBAL") == 0) {
$1 = 1;
} else if (strcasecmp(str, "PER_CHAIN") == 0) {
$1 = 1;
} else {
$1 = 0;
}
}

%typemap(in) dft::ScanStitchConfig::EnableMode {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "GLOBAL") == 0) {
$1 = dft::ScanStitchConfig::EnableMode::Global;
} else /* other values eliminated in typecheck */ {
$1 = dft::ScanStitchConfig::EnableMode::PerChain;
};
}

%inline
%{

Expand Down Expand Up @@ -171,13 +129,8 @@ void set_dft_config_clock_mixing(dft::ScanArchitectConfig::ClockMixing clock_mix
getDft()->getMutableDftConfig()->getMutableScanArchitectConfig()->setClockMixing(clock_mixing);
}

void set_dft_config_scan_enable_mode(dft::ScanStitchConfig::EnableMode enable_mode)
{
getDft()->getMutableDftConfig()->getMutableScanStitchConfig()->setEnableMode(enable_mode);
}

void set_dft_config_scan_signal_name_pattern(const char* signal_ptr, const char* pattern_ptr) {
auto config = getDft()->getMutableDftConfig()->getMutableScanStitchConfig();
dft::ScanStitchConfig* config = getDft()->getMutableDftConfig()->getMutableScanStitchConfig();
std::string_view signal(signal_ptr), pattern(pattern_ptr);

if (signal == "scan_in") {
Expand Down
6 changes: 0 additions & 6 deletions src/dft/src/dft.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ proc insert_dft { args } {
sta::define_cmd_args "set_dft_config" { [-max_length max_length]
[-max_chains max_chains]
[-clock_mixing clock_mixing]
[-scan_enable_mode mode]
[-scan_enable_name_pattern scan_enable_name_pattern]
[-scan_in_name_pattern scan_in_name_pattern]
[-scan_out_name_pattern scan_out_name_pattern]
Expand All @@ -84,7 +83,6 @@ proc set_dft_config { args } {
-max_length
-max_chains
-clock_mixing
-scan_enable_mode
-scan_enable_name_pattern
-scan_in_name_pattern
-scan_out_name_pattern
Expand All @@ -110,10 +108,6 @@ proc set_dft_config { args } {
dft::set_dft_config_clock_mixing $clock_mixing
}

if { [info exists keys(-scan_enable_mode)] } {
dft::set_dft_config_scan_enable_mode $keys(-scan_enable_mode)
}

foreach {flag signal} {
-scan_enable_name_pattern "scan_enable"
-scan_in_name_pattern "scan_in"
Expand Down
Loading

0 comments on commit 9b51d2b

Please sign in to comment.