Skip to content

Commit

Permalink
dft: per-chain enables, user-configurable name patterns
Browse files Browse the repository at this point in the history
* dft::Dft::insertDft: Add capability for per-chain enable, ability to provide runtime format strings for scan enable/in/out patterns
* dft::ScanStitch:
  * if a name pattern includes an un-escaped forward slash (/), steps are to attempt to find an existing ITerm instead of creating a new BTerm
  * else, if a BTerm already exists, the BTerm is reused.
  * finally, a new BTerm is created.
* dft::Dft: create writeScanChains, which writes the scan chains (currently just names and ordering of flip-flops) in JSON format. Allows data to be passed to other DFT utilities.
* dft: create ResetDomain, which encapsulates reset domains similar to how dft::ClockDomain encapsulates clock domains. currently unused
  • Loading branch information
donn committed Dec 22, 2024
1 parent 51302eb commit f0f7065
Show file tree
Hide file tree
Showing 17 changed files with 567 additions and 90 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ TAGS
.cache
Makefile
__pycache__
venv/

include/ord/Version.hh

Expand All @@ -45,4 +46,4 @@ etc/openroad_deps_prefixes.txt
debian/changelog
debian/files
debian/openroad
obj-x86_64-linux-gnu/
venv/
2 changes: 2 additions & 0 deletions src/dft/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ target_link_libraries(dft
dft_config_lib
dft_replace_lib
dft_clock_domain_lib
dft_reset_domain_lib
dft_utils_lib
dft_stitch_lib
)
Expand Down Expand Up @@ -105,6 +106,7 @@ add_subdirectory(src/cells)
add_subdirectory(src/clock_domain)
add_subdirectory(src/config)
add_subdirectory(src/replace)
add_subdirectory(src/reset_domain)
add_subdirectory(src/stitch)
add_subdirectory(src/utils)
if(ENABLE_TESTS)
Expand Down
10 changes: 9 additions & 1 deletion src/dft/include/dft/Dft.hh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include "ClockDomain.hh"
#include "ResetDomain.hh"
#include "db_sta/dbSta.hh"
#include "odb/db.h"
#include "utl/Logger.h"
Expand Down Expand Up @@ -95,7 +97,10 @@ class Dft
//
void scanReplace();

void insertDft();
void insertDft(bool per_chain_enable,
std::string scan_enable_name_pattern,
std::string scan_in_name_pattern,
std::string scan_out_name_pattern);

// Returns a mutable version of DftConfig
DftConfig* getMutableDftConfig();
Expand All @@ -106,6 +111,9 @@ class Dft
// Prints to stdout
void reportDftConfig() const;

// Writes scan chains in a JSON format
void writeScanChains(std::string filename);

private:
// If we need to run pre_dft to create the internal state
bool need_to_run_pre_dft_;
Expand Down
52 changes: 49 additions & 3 deletions src/dft/src/Dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include "dft/Dft.hh"

#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <iostream>

#include "ClockDomain.hh"
Expand Down Expand Up @@ -104,15 +106,59 @@ void Dft::scanReplace()
scan_replace_->scanReplace();
}

void Dft::insertDft()
void Dft::writeScanChains(std::string filename)
{
using boost::property_tree::ptree;
if (need_to_run_pre_dft_) {
pre_dft();
}

std::ofstream json_file(filename);
if (!json_file.is_open()) {
logger_->error(
utl::DFT, 13, "Failed to open file {} for writing.", filename);
}
try {
ptree root;

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

for (auto& chain : scan_chains) {
ptree current_chain;
ptree cells;
auto& scan_cells = chain->getScanCells();
for (auto& cell : scan_cells) {
ptree name;
name.put("", cell->getName());
cells.push_back(std::make_pair("", name));
}
current_chain.add_child("cells", cells);
root.add_child(chain->getName(), current_chain);
}

boost::property_tree::write_json(json_file, root);
} catch (std::exception& ex) {
logger_->error(
utl::DFT, 14, "Failed to write JSON report. Exception: {}", ex.what());
}
}

void Dft::insertDft(bool per_chain_enable,
std::string scan_enable_name_pattern,
std::string scan_in_name_pattern,
std::string scan_out_name_pattern)
{
if (need_to_run_pre_dft_) {
pre_dft();
}
std::vector<std::unique_ptr<ScanChain>> scan_chains = scanArchitect();

ScanStitch stitch(db_);
stitch.Stitch(scan_chains);
ScanStitch stitch(db_,
per_chain_enable,
scan_enable_name_pattern,
scan_in_name_pattern,
scan_out_name_pattern);
stitch.Stitch(scan_chains, logger_);
}

DftConfig* Dft::getMutableDftConfig()
Expand Down
5 changes: 5 additions & 0 deletions src/dft/src/architect/ScanChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,9 @@ const std::string& ScanChain::getName() const
return name_;
}

void ScanChain::rename(std::string& new_name)
{
name_ = new_name;
}

} // namespace dft
3 changes: 3 additions & 0 deletions src/dft/src/architect/ScanChain.hh
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class ScanChain
// Returns the name of the scan chain
const std::string& getName() const;

// Changes the name of the scan chain
void rename(std::string& new_name);

private:
std::string name_;
std::vector<std::unique_ptr<ScanCell>> rising_edge_scan_cells_;
Expand Down
52 changes: 49 additions & 3 deletions src/dft/src/dft.i
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "DftConfig.hh"
#include "ord/OpenRoad.hh"
#include "ScanArchitect.hh"
#include "ClockDomain.hh"
#include "ResetDomain.hh"

dft::Dft * getDft()
{
Expand All @@ -51,6 +53,48 @@ utl::Logger* getLogger()

%}

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

%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;
};
}

%typemap(typecheck) dft::ClockEdge {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "RISING") == 0) {
$1 = 1;
} else if (strcasecmp(str, "FALLING") == 0) {
$1 = 1;
} else {
$1 = 0;
}
}

%typemap(in) dft::ClockEdge {
char *str = Tcl_GetStringFromObj($input, 0);
if (strcasecmp(str, "FALLING") == 0) {
$1 = dft::ClockEdge::Falling;
} else /* other values eliminated in typecheck */ {
$1 = dft::ClockEdge::Rising;
};
}

%inline
%{

Expand All @@ -64,10 +108,12 @@ void scan_replace()
getDft()->scanReplace();
}


void insert_dft()
void insert_dft(bool per_chain_enable,
const char *scan_enable_name_pattern,
const char *scan_in_name_pattern,
const char *scan_out_name_pattern)
{
getDft()->insertDft();
getDft()->insertDft(per_chain_enable, scan_enable_name_pattern, scan_in_name_pattern, scan_out_name_pattern);
}

void set_dft_config_max_length(int max_length)
Expand Down
39 changes: 35 additions & 4 deletions src/dft/src/dft.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

sta::define_cmd_args "preview_dft" { [-verbose]}
sta::define_cmd_args "preview_dft" {[-verbose]}

proc preview_dft { args } {
sta::parse_key_args "preview_dft" args \
Expand Down Expand Up @@ -58,15 +58,46 @@ proc scan_replace { args } {
dft::scan_replace
}

sta::define_cmd_args "insert_dft" { }
sta::define_cmd_args "write_scan_chains" {[json_file_out]}
proc write_scan_chains { args } {
sta::parse_key_args "write_scan_chains" args \
keys {} flags {}

if { [ord::get_db_block] == "NULL" } {
utl::error DFT 15 "No design block found."
}

dft::write_scan_chains [lindex $args 0]
}

sta::define_cmd_args "insert_dft" {
[-per_chain_enable]
[-scan_enable_name_pattern scan_enable_name_pattern]
[-scan_in_name_pattern scan_in_name_pattern]
[-scan_out_name_pattern scan_out_name_pattern]
}
proc insert_dft { args } {
sta::parse_key_args "insert_dft" args \
keys {} flags {}
keys {-scan_enable_name_pattern -scan_in_name_pattern -scan_out_name_pattern}\
flags {-per_chain_enable}

if { [ord::get_db_block] == "NULL" } {
utl::error DFT 9 "No design block found."
}
dft::insert_dft

foreach {flag default} {
-scan_enable_name_pattern "scan_enable_{}"
-scan_in_name_pattern "scan_in_{}"
-scan_out_name_pattern "scan_out_{}"
} {
if { ![info exists keys($flag)] } {
set keys($flag) $default
}
}
dft::insert_dft [info exists flags(-per_chain_enable)]\
$keys(-scan_enable_name_pattern)\
$keys(-scan_in_name_pattern)\
$keys(-scan_out_name_pattern)
}

sta::define_cmd_args "set_dft_config" { [-max_length max_length] \
Expand Down
15 changes: 1 addition & 14 deletions src/dft/src/replace/ScanReplace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,6 @@
namespace dft {

namespace {

// Checks if the given LibertyCell is really a Scan Cell with a Scan In and a
// Scan Enable
bool IsScanCell(const sta::LibertyCell* libertyCell)
{
const sta::TestCell* test_cell = libertyCell->testCell();
if (test_cell) {
return getLibertyScanIn(test_cell) != nullptr
&& getLibertyScanEnable(test_cell) != nullptr;
}
return false;
}

// Checks the ports
sta::LibertyPort* FindEquivalentPortInScanCell(
const sta::LibertyPort* non_scan_cell_port,
Expand Down Expand Up @@ -309,7 +296,7 @@ void ScanReplace::collectScanCellAvailable()
continue;
}

if (IsScanCell(liberty_cell)) {
if (utils::IsScanCell(liberty_cell)) {
available_scan_lib_cells_.insert(liberty_cell);
} else {
non_scan_cells.push_back(liberty_cell);
Expand Down
15 changes: 15 additions & 0 deletions src/dft/src/reset_domain/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
add_library(dft_reset_domain_lib
# Keep sorted
ResetDomain.cpp
)

target_include_directories(dft_reset_domain_lib
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

target_link_libraries(dft_reset_domain_lib
PRIVATE
odb
utl_lib
)
Loading

0 comments on commit f0f7065

Please sign in to comment.