Skip to content

Commit

Permalink
Merge pull request The-OpenROAD-Project#3386 from fgaray/clock_mix2
Browse files Browse the repository at this point in the history
dft: Adding support for clock mixing
  • Loading branch information
maliberty authored May 27, 2023
2 parents 575222d + 54af2a1 commit 9a713f0
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 5 deletions.
73 changes: 71 additions & 2 deletions src/dft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,80 @@ A simple DFT insertion consist of the following parts:
* A scan_enable pin to allow your design to enter and leave the test mode.


# Supported Features
# TCL Commands

TODO
## set_dft_config


```
set_dft_config [-max_length <int>]
[-clock_mixing <string>]
```

* `-max_length`: The maxinum number of bits that can be in each scan chain.
* `-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`: Craetes scan chains mixing clocks and edges. Falling edge
flops are going to be stitched before rising edge.

## report_dft_config

```
report_dft_config
```

Prints the current DFT configuration to be used by `preview_dft` and
`insert_dft`.

## preview_dft

```
preview_dft [-verbose]
```

Prints a preview of the scan chains that will be stitched by `insert_dft`. Use
this command to iterate and try different DFT configurations. This command do
not perform any modification to the design.

* `-verbose`: Shows more information about each one of the scan chains that will
be created.


## insert_dft

```
insert_dft
```

Implements the scan chains into the design by performing the following actions:

1. Scan Replace.
2. Scan Architect.
3. Scan Stitch.

The end result will be a design with scan flops connected to form the scan
chains.

# Example

This example will create scan chains with a max length of 10 bits mixing all the
scan flops in the scan chains.

```
set_dft_config -max_length 10 -clock_mixing clock_mix
report_dft_config
preview_dft -verbose
insert_dft
```

# Limitations

* There are no optimizations for the scan chains. This is a WIP.
* There is no way to specify existing scan ports to be used by scan insertion.
* There is currently no way to define a user defined scan path.
* We can only work with one bit cells.

## License

BSD 3-Clause License. See [LICENSE](../../LICENSE) file.
9 changes: 8 additions & 1 deletion src/dft/src/architect/ScanArchitect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ bool CompareScanCells(const std::shared_ptr<ScanCell>& lhs,
// If they have the same number of bits, then we compare the names of the
// cells so they are ordered by name
if (lhs->getBits() == rhs->getBits()) {
return lhs->getName() < rhs->getName();
const ClockDomain& lhs_clock_domain = lhs->getClockDomain();
const ClockDomain& rhs_clock_domain = rhs->getClockDomain();

if (lhs_clock_domain.getClockName() == rhs_clock_domain.getClockName()) {
return lhs_clock_domain.getClockEdge() < rhs_clock_domain.getClockEdge();
}

return lhs_clock_domain.getClockName() < rhs_clock_domain.getClockName();
}
// Bigger elements last
return lhs->getBits() < rhs->getBits();
Expand Down
2 changes: 2 additions & 0 deletions src/dft/src/clock_domain/ClockDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ std::function<size_t(const ClockDomain&)> GetClockDomainHashFn(
return std::hash<std::string>{}(clock_domain.getClockName())
^ std::hash<ClockEdge>{}(clock_domain.getClockEdge());
};
case ScanArchitectConfig::ClockMixing::ClockMix:
return [](const ClockDomain& clock_domain) { return 1; };
default:
// Not implemented
logger->error(utl::DFT, 4, "Clock mix config requested is not supported");
Expand Down
2 changes: 2 additions & 0 deletions src/dft/src/config/ScanArchitectConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ std::string ScanArchitectConfig::ClockMixingName(
switch (clock_mixing) {
case ScanArchitectConfig::ClockMixing::NoMix:
return "No Mix";
case ScanArchitectConfig::ClockMixing::ClockMix:
return "Clock Mix";
default:
return "Missing case in ClockMixingName";
}
Expand Down
3 changes: 2 additions & 1 deletion src/dft/src/config/ScanArchitectConfig.hh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class ScanArchitectConfig
// TODO Add suport for mix_edges, mix_clocks, mix_clocks_not_edges
enum class ClockMixing
{
NoMix // We create different scan chains for each clock and edge
NoMix, // We create different scan chains for each clock and edge
ClockMix // We architect the flops of different clock and edge together
};

void setClockMixing(ClockMixing clock_mixing);
Expand Down
18 changes: 18 additions & 0 deletions src/dft/src/dft.i
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@
#include "dft/Dft.hh"
#include "DftConfig.hh"
#include "ord/OpenRoad.hh"
#include "ScanArchitect.hh"

dft::Dft * getDft()
{
return ord::OpenRoad::openRoad()->getDft();
}

utl::Logger* getLogger()
{
return ord::OpenRoad::openRoad()->getLogger();
}

%}

%inline
Expand All @@ -63,6 +69,18 @@ void set_dft_config_max_length(int max_length)
getDft()->getMutableDftConfig()->getMutableScanArchitectConfig()->setMaxLength(max_length);
}

void set_dft_config_clock_mixing(const char* clock_mixing_ptr)
{
std::string_view clock_mixing(clock_mixing_ptr);
if (clock_mixing == "no_mix") {
getDft()->getMutableDftConfig()->getMutableScanArchitectConfig()->setClockMixing(dft::ScanArchitectConfig::ClockMixing::NoMix);
} else if (clock_mixing == "clock_mix") {
getDft()->getMutableDftConfig()->getMutableScanArchitectConfig()->setClockMixing(dft::ScanArchitectConfig::ClockMixing::ClockMix);
} else {
getLogger()->error(utl::DFT, 5, "Requested clock mixing config not valid");
}
}

void report_dft_config() {
getDft()->reportDftConfig();
}
Expand Down
8 changes: 7 additions & 1 deletion src/dft/src/dft.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ proc insert_dft {} {

proc set_dft_config { args } {
sta::parse_key_args "set_dft_config" args \
keys {-max_length} \
keys {-max_length -clock_mixing} \
flags {}

sta::check_argc_eq0 "set_dft_config" $args
Expand All @@ -57,6 +57,12 @@ proc set_dft_config { args } {
sta::check_positive_integer "-max_length" $max_length
dft::set_dft_config_max_length $max_length
}

if [info exists keys(-clock_mixing)] {
set clock_mixing $keys(-clock_mixing)
puts $clock_mixing
dft::set_dft_config_clock_mixing $clock_mixing
}
}

proc report_dft_config {} {
Expand Down
1 change: 1 addition & 0 deletions src/dft/test/regression_tests.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ record_tests {
one_cell_nangate45
sub_modules_sky130
scan_architect_no_mix_sky130
scan_architect_clock_mix_sky130
}


Expand Down
58 changes: 58 additions & 0 deletions src/dft/test/scan_architect_clock_mix_sky130.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[INFO ODB-0222] Reading LEF file: sky130hd/sky130hd.tlef
[INFO ODB-0223] Created 13 technology layers
[INFO ODB-0224] Created 25 technology vias
[INFO ODB-0226] Finished LEF file: sky130hd/sky130hd.tlef
[INFO ODB-0222] Reading LEF file: sky130hd/sky130_fd_sc_hd_merged.lef
[INFO ODB-0225] Created 437 library cells
[INFO ODB-0226] Finished LEF file: sky130hd/sky130_fd_sc_hd_merged.lef
clock_mix
***************************
Preview DFT Report
Number of chains: 7
Clock domain: Clock Mix
***************************

Scan chain 'chain_0' has 3 cells (3 bits)

ff8_clk2_falling (clock2, falling)
ff2_clk2_falling
ff6_clk2_falling

Scan chain 'chain_1' has 3 cells (3 bits)

ff10_clk2_falling (clock2, falling)
ff4_clk2_falling
ff10_clk2_rising

Scan chain 'chain_2' has 3 cells (3 bits)

ff8_clk2_rising (clock2, rising)
ff2_clk2_rising
ff6_clk2_rising

Scan chain 'chain_3' has 3 cells (3 bits)

ff1_clk1_falling (clock1, falling)
ff3_clk1_falling
ff4_clk2_rising (clock2, rising)

Scan chain 'chain_4' has 3 cells (3 bits)

ff7_clk1_falling (clock1, falling)
ff9_clk1_falling
ff5_clk1_falling

Scan chain 'chain_5' has 3 cells (3 bits)

ff3_clk1_rising (clock1, rising)
ff5_clk1_rising
ff7_clk1_rising

Scan chain 'chain_6' has 2 cells (2 bits)

ff1_clk1_rising (clock1, rising)
ff9_clk1_rising


No differences found.
No differences found.
32 changes: 32 additions & 0 deletions src/dft/test/scan_architect_clock_mix_sky130.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
source "helpers.tcl"

read_lef sky130hd/sky130hd.tlef
read_lef sky130hd/sky130_fd_sc_hd_merged.lef
read_liberty sky130hd/sky130_fd_sc_hd__tt_025C_1v80.lib

read_verilog scan_architect_sky130.v
link_design scan_architect

create_clock -name clock1 -period 2.0000 -waveform {0.0000 1.0000} [get_ports {clock1}]
create_clock -name clock2 -period 2.0000 -waveform {0.0000 1.0000} [get_ports {clock2}]

set_dft_config -max_length 3 -clock_mixing clock_mix


set verilog_file_before_preview [make_result_file scan_architect_clock_mix_sky130_before_preview.v]
write_verilog -sort $verilog_file_before_preview

preview_dft -verbose

# Preview should not modify the net
set verilog_file_after_preview [make_result_file scan_architect_clock_mix_sky130_after_preview.v]
write_verilog -sort $verilog_file_after_preview

# Before and after preview, the netlist should be the same
diff_files $verilog_file_after_preview $verilog_file_before_preview

insert_dft

set verilog_file [make_result_file scan_architect_clock_mix_sky130.v]
write_verilog $verilog_file
diff_files $verilog_file scan_architect_clock_mix_sky130.vok
Loading

0 comments on commit 9a713f0

Please sign in to comment.