3 # Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
5 # Algorithm from https://apps.dtic.mil/dtic/tr/fulltext/u2/a163195.pdf
6 # Peter Yan-Tek Hsu, "Highly Concurrent Scalar Processing,"
7 # PhD Dissertation, University of Illinois at Urbana-Champaign, 1986
9 # Usage: softpipe < loop.def > prog.h
11 # See vnv_spmv.def, vnv_spmv.h and ComputeSPVM.cpp for example usage
17 SpecPattern
= re
.compile(r
'^\s*([0-9]+)\s+(.*)')
18 IterPattern
= re
.compile(r
'^\?iter=(\w+)')
19 LimitPattern
= re
.compile(r
'^\?limit=(\w+)')
20 VarPattern
= re
.compile(r
'^(.+)([a-zA-Z_][a-zA-Z_0-9]*)\$')
21 CmdPattern
= re
.compile(r
'^\?([a-z]+)=([a-zA-Z_][a-zA-Z_0-9]*)')
25 lines
.insert(0, l
.rstrip('\r\n'))
36 sys
.stderr
.write('Unrecognized line:\n')
37 sys
.stderr
.write(line
+'\n')
42 for stage
in range(depth
):
43 stmt
= ' Stage("{:2d}:") '.format(stage
)
49 def Substitute(src
, dollar
, at
):
53 at
= str(dollar
) + str(at
)
56 f
= e
.replace('$', str(dollar
))
57 f
= f
.replace('@', at
)
63 epi
= [ None ]*2*depth
64 for j
in range(2*depth
):
66 for j
in range(depth
):
71 for stmt
in Substitute(pipe
[j
], i
, at
):
73 if stmt
not in epi
[stage
] and not (i
>=n
and i
+j
<depth
):
75 if stmt
not in epi
[stage
+depth
] and not (i
>=n
or i
+j
<depth
):
76 epi
[stage
+depth
][stmt
] = 1
80 def GenProlog(n
, depth
):
81 pro
= [ None ]*2*depth
82 for j
in range(2*depth
):
84 for j
in range(depth
):
89 for stmt
in Substitute(pipe
[j
], i
, 0):
91 if stmt
not in pro
[stage
] and not (i
>n
or i
+j
>=depth
):
93 if stmt
not in pro
[stage
+depth
] and not (i
>n
or i
+j
<depth
):
94 pro
[stage
+depth
][stmt
] = 1
98 def GenerateSoftwarePipeline():
99 # Generate vector variable declarations
100 for (var
, decl
) in vectors
:
102 for i
in range(depth
):
103 vec
.append(var
+str(i
))
105 decl
+= comma
.join(vec
)
108 print(' if ({:s} < {:d}) {{ /* Single Pass */'.format(limit
, depth
))
109 # Generate special short tripcount cases
110 # stmt[stage] = {} (key=statement, value=lowest remaining case to execute)
111 # stage = software pipeline stage, 0..2*depth-1
112 stmt
= [ None ]*2*depth
113 for trips
in range(depth
-1):
114 pro
= GenProlog(trips
, depth
)
115 for stage
in range(2*depth
):
116 for s
in pro
[stage
].keys():
117 if stmt
[stage
] == None:
119 if s
not in stmt
[stage
]:
120 stmt
[stage
][s
] = trips
121 elif stmt
[stage
][s
] > trips
:
122 stmt
[stage
][s
] = trips
123 for stage
in range(2*depth
):
124 if stmt
[stage
] != None:
127 for a
in stmt
[stage
].keys():
138 for r
in reversed(sorted(buckets
.keys())):
139 ifstmt
+= 'if ({:s}>{:d}) {{'.format(limit
, r
)
144 ifstmt
= ' Stage("{:2d}:") '.format(stage
) + ifstmt
149 # Generate pipeline prologue
150 stages
= [ None ]*depth
151 for j
in range(depth
):
153 for j
in range(depth
):
157 stages
[(i
+j
)%depth
] += Substitute(pipe
[j
], i
, 0)
158 print(' { /* Prologue */')
162 # Generate pipeline body
163 stages
= [ None ]*depth
164 for j
in range(depth
):
166 for j
in range(depth
):
171 stages
[(i
+j
)%depth
] += Substitute(pipe
[j
], i
, at
)
173 print(' for ({:s}+={:d}; {:s}+{:d}<={:s}; {:s}+={:d}) {{'.format(lv
, depth
, lv
, depth
, limit
, lv
, depth
))
177 # Generate pipeline epilogue
178 # stmt[stage] = {} (key=statement, value=highest remaining case to execute)
179 # stage = software pipeline stage, 0..2*depth-1
180 print(' { /* Epilogue */')
181 stmt
= [ None ]*2*depth
182 for remaining
in range(depth
-1, -1, -1):
183 epi
= GenEpilog(remaining
)
184 for stage
in range(2*depth
):
185 for s
in epi
[stage
].keys():
186 if stmt
[stage
] == None:
188 if s
not in stmt
[stage
]:
189 stmt
[stage
][s
] = remaining
190 elif stmt
[stage
][s
] > remaining
:
191 stmt
[stage
][s
] = remaining
192 for stage
in range(2*depth
):
193 if stmt
[stage
] != None:
196 for a
in stmt
[stage
].keys():
207 for r
in reversed(sorted(buckets
.keys())):
208 ifstmt
+= 'if ({:s}-{:s}>{:d}) {{'.format(limit
, lv
, r
-1)
213 ifstmt
= ' Stage("{:2d}:") '.format(stage
) + ifstmt
223 if line
!= '' and line
[0] != '?':
228 m
= VarPattern
.match(line
)
231 (declaration
, variable
) = m
.groups()
232 vectors
.append( (variable
, declaration
) )
237 m
= SpecPattern
.match(line
)
240 (stage
, statement
) = m
.groups()
242 statement
= statement
.lstrip()
243 statement
= statement
.rstrip()
244 if stage
not in pipe
:
246 pipe
[stage
].append(statement
)
252 # Generate permutation table
254 for i
in range(depth
):
255 perm
[i
] = list(range(i
, depth
)) + list(range(0, i
))
257 for i
in range(depth
):
260 GenerateSoftwarePipeline()
263 m
= CmdPattern
.match(line
)
265 cmd
, value
= m
.groups()