Skip to content

Commit 778079b

Browse files
committed
dfflibmap: propagate negated next_state to output correctly
1 parent 44aa313 commit 778079b

File tree

3 files changed

+160
-2
lines changed

3 files changed

+160
-2
lines changed

passes/techmap/dfflibmap.cc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,21 @@ static void find_cell_sr(std::vector<const LibertyAst *> cells, IdString cell_ty
392392
continue;
393393
if (!parse_next_state(cell, ff->find("next_state"), cell_next_pin, cell_next_pol, cell_enable_pin, cell_enable_pol))
394394
continue;
395-
if (!parse_pin(cell, ff->find("preset"), cell_set_pin, cell_set_pol) || cell_set_pol != setpol)
395+
396+
if (!parse_pin(cell, ff->find("preset"), cell_set_pin, cell_set_pol))
397+
continue;
398+
if (!parse_pin(cell, ff->find("clear"), cell_clr_pin, cell_clr_pol))
399+
continue;
400+
if (!cell_next_pol) {
401+
// next_state is negated
402+
// we later propagate this inversion to the output,
403+
// which requires the swap of set and reset
404+
std::swap(cell_set_pin, cell_clr_pin);
405+
std::swap(cell_set_pol, cell_clr_pol);
406+
}
407+
if (cell_set_pol != setpol)
396408
continue;
397-
if (!parse_pin(cell, ff->find("clear"), cell_clr_pin, cell_clr_pol) || cell_clr_pol != clrpol)
409+
if (cell_clr_pol != clrpol)
398410
continue;
399411

400412
std::map<std::string, char> this_cell_ports;
@@ -432,12 +444,14 @@ static void find_cell_sr(std::vector<const LibertyAst *> cells, IdString cell_ty
432444
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
433445
value.erase(pos, 1);
434446
if (value == ff->args[0]) {
447+
// next_state negation propagated to output
435448
this_cell_ports[pin->args[0]] = cell_next_pol ? 'Q' : 'q';
436449
if (cell_next_pol)
437450
found_noninv_output = true;
438451
found_output = true;
439452
} else
440453
if (value == ff->args[1]) {
454+
// next_state negation propagated to output
441455
this_cell_ports[pin->args[0]] = cell_next_pol ? 'q' : 'Q';
442456
if (!cell_next_pol)
443457
found_noninv_output = true;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library (test_not_next) {
2+
cell (dffsr_not_next) {
3+
area : 1.0;
4+
pin (Q) {
5+
direction : output;
6+
function : "STATE";
7+
}
8+
pin (CLK) {
9+
clock : true;
10+
direction : input;
11+
}
12+
pin (D) {
13+
direction : input;
14+
}
15+
pin (RN) {
16+
direction : input;
17+
}
18+
pin (SN) {
19+
direction : input;
20+
}
21+
ff (STATE,STATEN) {
22+
clear : "!SN";
23+
clocked_on : "CLK";
24+
next_state : "!D";
25+
preset : "!RN";
26+
}
27+
}
28+
}

tests/techmap/dfflibmap_formal.ys

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
##################################################################
2+
3+
read_verilog -sv -icells <<EOT
4+
5+
module top(input C, D, E, S, R, output [11:0] Q);
6+
7+
$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
8+
$_DFF_PP0_ ff1 (.C(C), .D(D), .R(R), .Q(Q[1]));
9+
$_DFF_PP1_ ff2 (.C(C), .D(D), .R(R), .Q(Q[2]));
10+
11+
// Formal checking of directly instantiated DFFSR doesn't work at the moment
12+
// likely due to an equiv_induct assume bug #5196
13+
14+
// // Workaround for DFFSR bug #5194
15+
// assume property (~R || ~S);
16+
// $_DFFSR_PPP_ ff3 (.C(C), .D(D), .R(R), .S(S), .Q(Q[3]));
17+
// $_DFFSR_NNN_ ff4 (.C(C), .D(D), .R(~R), .S(~S), .Q(Q[4]));
18+
19+
$_DFFE_PP_ ff5 (.C(C), .D(D), .E(E), .Q(Q[5]));
20+
21+
assign Q[11:6] = ~Q[5:0];
22+
23+
endmodule
24+
25+
EOT
26+
27+
proc
28+
opt
29+
read_liberty dfflibmap_dffn_dffe.lib
30+
read_liberty dfflibmap_dffsr_not_next.lib
31+
32+
copy top top_unmapped
33+
dfflibmap -liberty dfflibmap_dffn_dffe.lib -liberty dfflibmap_dffsr_not_next.lib top
34+
35+
async2sync
36+
flatten
37+
opt_clean -purge
38+
equiv_make top top_unmapped equiv
39+
equiv_induct equiv
40+
equiv_status -assert equiv
41+
42+
##################################################################
43+
44+
design -reset
45+
read_verilog -sv -icells <<EOT
46+
47+
module top(input C, D, E, S, R, output [11:0] Q);
48+
49+
$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
50+
$_DFF_PP0_ ff1 (.C(C), .D(D), .R(R), .Q(Q[1]));
51+
$_DFF_PP1_ ff2 (.C(C), .D(D), .R(R), .Q(Q[2]));
52+
53+
// Formal checking of directly instantiated DFFSR doesn't work at the moment
54+
// likely due to an equiv_induct assume bug #5196
55+
56+
// // Workaround for DFFSR bug #5194
57+
// assume property (~R || ~S);
58+
// $_DFFSR_PPP_ ff3 (.C(C), .D(D), .R(R), .S(S), .Q(Q[3]));
59+
// $_DFFSR_NNN_ ff4 (.C(C), .D(D), .R(~R), .S(~S), .Q(Q[4]));
60+
61+
$_DFFE_PP_ ff5 (.C(C), .D(D), .E(E), .Q(Q[5]));
62+
63+
assign Q[11:6] = ~Q[5:0];
64+
65+
endmodule
66+
67+
EOT
68+
69+
proc
70+
opt
71+
read_liberty dfflibmap_dffr_not_next.lib
72+
73+
copy top top_unmapped
74+
dfflibmap -liberty dfflibmap_dffr_not_next.lib top
75+
76+
async2sync
77+
flatten
78+
opt_clean -purge
79+
equiv_make top top_unmapped equiv
80+
equiv_induct equiv
81+
equiv_status -assert equiv
82+
83+
##################################################################
84+
85+
design -reset
86+
read_verilog <<EOT
87+
88+
module top(input C, D, E, S, R, output Q);
89+
// DFFSR with priority R over S
90+
always @(posedge C, posedge R, posedge S)
91+
if (R == 1)
92+
Q <= 0;
93+
else if (S == 1)
94+
Q <= 1;
95+
else
96+
Q <= D;
97+
98+
endmodule
99+
100+
EOT
101+
102+
proc
103+
opt
104+
read_liberty dfflibmap_dffn_dffe.lib
105+
read_liberty dfflibmap_dffsr_not_next.lib
106+
107+
copy top top_unmapped
108+
simplemap top
109+
dfflibmap -liberty dfflibmap_dffn_dffe.lib -liberty dfflibmap_dffsr_not_next.lib top
110+
111+
async2sync
112+
flatten
113+
opt_clean -purge
114+
equiv_make top top_unmapped equiv
115+
equiv_induct equiv
116+
equiv_status -assert equiv

0 commit comments

Comments
 (0)