Merge pull request #1289 from mmicko/anlogic_fixes
[yosys.git] / passes / pmgen / ice40_dsp.pmg
1 pattern ice40_dsp
2
3 state <SigBit> clock
4 state <bool> clock_pol clock_vld
5 state <SigSpec> sigA sigB sigY sigS
6 state <Cell*> addAB muxAB
7
8 match mul
9 select mul->type.in($mul)
10 select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10
11 select GetSize(mul->getPort(\Y)) > 10
12 endmatch
13
14 match ffA
15 select ffA->type.in($dff)
16 // select nusers(port(ffA, \Q)) == 2
17 index <SigSpec> port(ffA, \Q) === port(mul, \A)
18 optional
19 endmatch
20
21 code sigA clock clock_pol clock_vld
22 sigA = port(mul, \A);
23
24 if (ffA) {
25 sigA = port(ffA, \D);
26
27 clock = port(ffA, \CLK).as_bit();
28 clock_pol = param(ffA, \CLK_POLARITY).as_bool();
29 clock_vld = true;
30 }
31 endcode
32
33 match ffB
34 select ffB->type.in($dff)
35 // select nusers(port(ffB, \Q)) == 2
36 index <SigSpec> port(ffB, \Q) === port(mul, \B)
37 optional
38 endmatch
39
40 code sigB clock clock_pol clock_vld
41 sigB = port(mul, \B);
42
43 if (ffB) {
44 sigB = port(ffB, \D);
45 SigBit c = port(ffB, \CLK).as_bit();
46 bool cp = param(ffB, \CLK_POLARITY).as_bool();
47
48 if (clock_vld && (c != clock || cp != clock_pol))
49 reject;
50
51 clock = c;
52 clock_pol = cp;
53 clock_vld = true;
54 }
55 endcode
56
57 match ffY
58 select ffY->type.in($dff)
59 select nusers(port(ffY, \D)) == 2
60 index <SigSpec> port(ffY, \D) === port(mul, \Y)
61 optional
62 endmatch
63
64 code sigY clock clock_pol clock_vld
65 sigY = port(mul, \Y);
66
67 if (ffY) {
68 sigY = port(ffY, \Q);
69 SigBit c = port(ffY, \CLK).as_bit();
70 bool cp = param(ffY, \CLK_POLARITY).as_bool();
71
72 if (clock_vld && (c != clock || cp != clock_pol))
73 reject;
74
75 clock = c;
76 clock_pol = cp;
77 clock_vld = true;
78 }
79 endcode
80
81 match addA
82 select addA->type.in($add)
83 select nusers(port(addA, \A)) == 2
84 index <SigSpec> port(addA, \A) === sigY
85 optional
86 endmatch
87
88 match addB
89 if !addA
90 select addB->type.in($add, $sub)
91 select nusers(port(addB, \B)) == 2
92 index <SigSpec> port(addB, \B) === sigY
93 optional
94 endmatch
95
96 code addAB sigS
97 if (addA) {
98 addAB = addA;
99 sigS = port(addA, \B);
100 }
101 if (addB) {
102 addAB = addB;
103 sigS = port(addB, \A);
104 }
105 if (addAB) {
106 int natural_mul_width = GetSize(sigA) + GetSize(sigB);
107 int actual_mul_width = GetSize(sigY);
108 int actual_acc_width = GetSize(sigS);
109
110 if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
111 reject;
112 if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
113 reject;
114 }
115 endcode
116
117 match muxA
118 if addAB
119 select muxA->type.in($mux)
120 select nusers(port(muxA, \A)) == 2
121 index <SigSpec> port(muxA, \A) === port(addAB, \Y)
122 optional
123 endmatch
124
125 match muxB
126 if addAB
127 if !muxA
128 select muxB->type.in($mux)
129 select nusers(port(muxB, \B)) == 2
130 index <SigSpec> port(muxB, \B) === port(addAB, \Y)
131 optional
132 endmatch
133
134 code muxAB
135 muxAB = addAB;
136 if (muxA)
137 muxAB = muxA;
138 if (muxB)
139 muxAB = muxB;
140 endcode
141
142 match ffS
143 if muxAB
144 select ffS->type.in($dff)
145 select nusers(port(ffS, \D)) == 2
146 index <SigSpec> port(ffS, \D) === port(muxAB, \Y)
147 index <SigSpec> port(ffS, \Q) === sigS
148 endmatch
149
150 code clock clock_pol clock_vld
151 if (ffS) {
152 SigBit c = port(ffS, \CLK).as_bit();
153 bool cp = param(ffS, \CLK_POLARITY).as_bool();
154
155 if (clock_vld && (c != clock || cp != clock_pol))
156 reject;
157
158 clock = c;
159 clock_pol = cp;
160 clock_vld = true;
161 }
162 accept;
163 endcode