SDC: use fastest clock as ABC9 delay target Signed-off-by: Dan Ravensloft <dan.ravensloft@gmail.com>
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc index 6dbb962..5b60700 100644 --- a/sdc-plugin/clocks.cc +++ b/sdc-plugin/clocks.cc
@@ -140,3 +140,23 @@ } return clock_wires; } + +void Clocks::UpdateAbc9DelayTarget(RTLIL::Design *design) +{ + std::map<std::string, RTLIL::Wire *> clock_wires = Clocks::GetClocks(design); + + for (auto &clock_wire : clock_wires) { + auto &wire = clock_wire.second; + float period = Clock::Period(wire); + + // Set the ABC9 delay to the shortest clock period in the design. + // + // By convention, delays in Yosys are in picoseconds, but ABC9 has + // no information on interconnect delay, so target half the specified + // clock period to give timing slack; otherwise ABC9 may produce a + // mapping that cannot meet the specified clock. + int abc9_delay = design->scratchpad_get_int("abc9.D", INT32_MAX); + int period_ps = period * 1000.0 / 2.0; + design->scratchpad_set_int("abc9.D", std::min(abc9_delay, period_ps)); + } +}
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h index b11d1c0..f565299 100644 --- a/sdc-plugin/clocks.h +++ b/sdc-plugin/clocks.h
@@ -64,6 +64,7 @@ { public: static const std::map<std::string, RTLIL::Wire *> GetClocks(RTLIL::Design *design); + static void UpdateAbc9DelayTarget(RTLIL::Design *design); }; #endif // _CLOCKS_H_
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc index 9f92b48..eafb894 100644 --- a/sdc-plugin/sdc.cc +++ b/sdc-plugin/sdc.cc
@@ -323,6 +323,8 @@ for (auto &pass : passes) { pass->Run(); } + + Clocks::UpdateAbc9DelayTarget(design); } };
diff --git a/sdc-plugin/tests/Makefile b/sdc-plugin/tests/Makefile index 503c542..1361f8e 100644 --- a/sdc-plugin/tests/Makefile +++ b/sdc-plugin/tests/Makefile
@@ -1,3 +1,4 @@ +# abc9 - test that abc9.D is correctly set after importing a clock. # counter, counter2, pll - test buffer and clock divider propagation # set_false_path - test the set_false_path command # set_max_delay - test the set_max_delay command @@ -7,7 +8,8 @@ # waveform_check - test if the WAVEFORM attribute value is correct on wire # period_format_check - test if PERIOD attribute value is correct on wire -TESTS = counter \ +TESTS = abc9 \ + counter \ counter2 \ pll \ pll_div \ @@ -28,6 +30,7 @@ include $(shell pwd)/../../Makefile_test.common +abc9_verify = true counter_verify = $(call diff_test,counter,sdc) && $(call diff_test,counter,txt) counter2_verify = $(call diff_test,counter2,sdc) && $(call diff_test,counter2,txt) pll_verify = $(call diff_test,pll,sdc)
diff --git a/sdc-plugin/tests/abc9/abc9.sdc b/sdc-plugin/tests/abc9/abc9.sdc new file mode 100644 index 0000000..0a192c3 --- /dev/null +++ b/sdc-plugin/tests/abc9/abc9.sdc
@@ -0,0 +1,3 @@ +create_clock -period 10 clk1 +create_clock -period 20 clk2 +propagate_clocks
diff --git a/sdc-plugin/tests/abc9/abc9.tcl b/sdc-plugin/tests/abc9/abc9.tcl new file mode 100644 index 0000000..22766a1 --- /dev/null +++ b/sdc-plugin/tests/abc9/abc9.tcl
@@ -0,0 +1,12 @@ +yosys -import +if { [info procs read_sdc] == {} } { plugin -i sdc } +yosys -import ;# ingest plugin commands + +# ensure abc9.D is unset +scratchpad -assert-unset abc9.D + +read_verilog abc9.v +read_sdc abc9.sdc + +# check that abc9.D was set to half the fastest clock period in the design +scratchpad -assert abc9.D 5000
diff --git a/sdc-plugin/tests/abc9/abc9.v b/sdc-plugin/tests/abc9/abc9.v new file mode 100644 index 0000000..5b73e55 --- /dev/null +++ b/sdc-plugin/tests/abc9/abc9.v
@@ -0,0 +1,15 @@ +module top(input clk1, clk2, output led1, led2); + +reg [15:0] counter1 = 0; +reg [15:0] counter2 = 0; + +assign led1 = counter1[15]; +assign led2 = counter2[15]; + +always @(posedge clk1) + counter1 <= counter1 + 1; + +always @(posedge clk2) + counter2 <= counter2 + 1; + +endmodule