blob: c4f9762b999c3de0656f1656df8b5175328e94a5 [file] [log] [blame]
Christophe Favergeona391d772021-02-10 10:56:33 +01001# Web UI for configuration of the CMSIS-DSP Build
2#
3# How to install
4# pip install streamlit
5#
6# How to use
7# streamlit run cmsisconfig.py
8#
9import streamlit as st
10import textwrap
11import re
12
13
14st.set_page_config(page_title="CMSIS-DSP Configuration",layout="wide" )
15
16# Options requiring a special management
17NOTSTANDARD=["allTables","allInterpolations","allFFTs","Float16"]
18
19HELIUM=False
20
21config={}
22
23config["allTables"] = True
24config["allFFTs"] = True
25config["allInterpolations"] = True
26config["MVEI"]=False
27config["MVEF"]=False
28config["NEON"]=False
29config["HELIUM"]=False
30config["Float16"]=True
31config["HOST"]=False
32
33config["COS_F32"]=False
34config["COS_Q31"]=False
35config["COS_Q15"]=False
36config["SIN_F32"]=False
37config["SIN_Q31"]=False
38config["SIN_Q15"]=False
39config["SIN_COS_F32"]=False
40config["SIN_COS_Q31"]=False
41config["LMS_NORM_Q31"]=False
42config["LMS_NORM_Q15"]=False
43config["CMPLX_MAG_Q31"]=False
44config["CMPLX_MAG_Q15"]=False
45
46config["BASICMATH"]=True
47config["COMPLEXMATH"]=True
48config["CONTROLLER"]=True
49config["FASTMATH"]=True
50config["FILTERING"]=True
51config["MATRIX"]=True
52config["STATISTICS"]=True
53config["SUPPORT"]=True
54config["TRANSFORM"]=True
55config["SVM"]=True
56config["BAYES"]=True
57config["DISTANCE"]=True
58config["INTERPOLATION"]=True
59
60config["LOOPUNROLL"]=True
61config["ROUNDING"]=False
62config["MATRIXCHECK"]=False
63config["AUTOVECTORIZE"] = False
64
65realname={}
66realname["COS_F32"]="ARM_COS_F32"
67realname["COS_Q31"]="ARM_COS_Q31"
68realname["COS_Q15"]="ARM_COS_Q15"
69realname["SIN_F32"]="ARM_SIN_F32"
70realname["SIN_Q31"]="ARM_SIN_Q31"
71realname["SIN_Q15"]="ARM_SIN_Q15"
72realname["SIN_COS_F32"]="ARM_SIN_COS_F32"
73realname["SIN_COS_Q31"]="ARM_SIN_COS_Q31"
74realname["LMS_NORM_Q31"]="ARM_LMS_NORM_Q31"
75realname["LMS_NORM_Q15"]="ARM_LMS_NORM_Q15"
76realname["CMPLX_MAG_Q31"]="ARM_CMPLX_MAG_Q31"
77realname["CMPLX_MAG_Q15"]="ARM_CMPLX_MAG_Q15"
78
79defaulton={}
80defaulton["LOOPUNROLL"]=True
81defaulton["BASICMATH"]=True
82defaulton["COMPLEXMATH"]=True
83defaulton["CONTROLLER"]=True
84defaulton["FASTMATH"]=True
85defaulton["FILTERING"]=True
86defaulton["MATRIX"]=True
87defaulton["STATISTICS"]=True
88defaulton["SUPPORT"]=True
89defaulton["TRANSFORM"]=True
90defaulton["SVM"]=True
91defaulton["BAYES"]=True
92defaulton["DISTANCE"]=True
93defaulton["INTERPOLATION"]=True
94
95CFFTSIZE=[16,32,64,128,256,512,1024,2048,4096]
96CFFTDATATYPE=['F64','F32','F16','Q31','Q15']
97
98RFFTFASTSIZE=[32,64,128,256,512,1024,2048,4096]
99RFFTFASTDATATYPE=['F64','F32','F16']
100
101RFFTSIZE=[32,64,128,256,512,1024,2048,4096,8192]
102RFFTDATATYPE=['F32','Q31','Q15']
103
104DCTSIZE=[128,512,2048,8192]
105DCTDATATYPE=['F32','Q31','Q15']
106
107def joinit(iterable, delimiter):
108 # Intersperse a delimiter between element of a list
109 it = iter(iterable)
110 yield next(it)
111 for x in it:
112 yield delimiter
113 yield x
114
115def options(l):
116 return("".join(joinit(l," ")))
117
118def computeCmakeOptions(config):
119 global defaulton
120 cmake={}
121 if not config["allTables"]:
122 cmake["CONFIGTABLE"]=True
123 if config["allInterpolations"]:
124 cmake["ALLFAST"]=True
125 if config["allFFTs"]:
126 cmake["ALLFFT"]=True
127 if config["Float16"]:
128 cmake["FLOAT16"]=True
129 else:
130 cmake["DISABLEFLOAT16"]=True
131
132 for c in config:
133 if not (c in NOTSTANDARD):
134 if c in defaulton:
135 if not config[c]:
136 if c in realname:
137 cmake[realname[c]]=False
138 else:
139 cmake[c]=False
140 else:
141 if config[c]:
142 if c in realname:
143 cmake[realname[c]]=True
144 else:
145 cmake[c]=True
146 return cmake
147
148def removeDuplicates(l):
149 return list(dict.fromkeys(l))
150
151def genCMakeOptions(config):
152 r=[]
153 cmake = computeCmakeOptions(config)
154 for c in cmake:
155 if cmake[c]:
156 r.append("-D%s=ON" % c)
157 else:
158 r.append("-D%s=OFF" % c)
159 return(removeDuplicates(r),cmake)
160
161def test(cmake,s):
162 global defaulton
163 if s in defaulton and not (s in cmake):
164 return True
165 return(s in cmake and cmake[s])
166
167def cfftCF32Config(cmake,size):
168 result=[]
169 if test(cmake,"CFFT_F32_%d" % size):
170 a="-DARM_TABLE_TWIDDLECOEF_F32_%d" % size
171 if HELIUM:
172 b = "-DARM_TABLE_BITREVIDX_FXT_%d" % size
173 else:
174 b = "-DARM_TABLE_BITREVIDX_FLT_%d" % size
175 result=[a,b]
176 return(result)
177
178def cfftCF16Config(cmake,size):
179 result=[]
180 if test(cmake,"CFFT_F16_%d" % size):
181 result =["-DARM_TABLE_TWIDDLECOEF_F16_%d" % size]
182 result.append("-DARM_TABLE_BITREVIDX_FXT_%d" % size)
183 result.append("-DARM_TABLE_BITREVIDX_FLT_%d" % size)
184 return(result)
185
186def cfftCF64Config(cmake,size):
187 result=[]
188 if test(cmake,"CFFT_F64_%d" % size):
189 result =["-DARM_TABLE_TWIDDLECOEF_F64_%d" % size]
190 result.append("-DARM_TABLE_BITREVIDX_FLT64_%d" % size)
191 return(result)
192
193
194def cfftCFixedConfig(cmake,dt,size):
195 result=[]
196 if test(cmake,"CFFT_%s_%d" % (dt,size)):
197 a="-DARM_TABLE_TWIDDLECOEF_%s_%d" % (dt,size)
198 b = "-DARM_TABLE_BITREVIDX_FXT_%d" % size
199 result=[a,b]
200 return(result)
201
202def crfftFastCF64Config(cmake,size):
203 result=[]
204 s1 = size >> 1
205 if test(cmake,"RFFT_FAST_F64_%d" % size):
206 result =[]
207 result.append("-DARM_TABLE_TWIDDLECOEF_F64_%d" % s1)
208 result.append("-DARM_TABLE_BITREVIDX_FLT64_%d" % s1)
209 result.append("-DARM_TABLE_TWIDDLECOEF_RFFT_F64_%d" % size)
210 result.append("-DARM_TABLE_TWIDDLECOEF_F64_%d" % s1)
211
212 return(result)
213
214def crfftFastCF32Config(cmake,size):
215 result=[]
216 s1 = size >> 1
217 if test(cmake,"RFFT_FAST_F32_%d" % size):
218 result =[]
219 result.append("-DARM_TABLE_TWIDDLECOEF_F32_%d" % s1)
220 result.append("-DARM_TABLE_BITREVIDX_FLT_%d" % s1)
221 result.append("-DARM_TABLE_TWIDDLECOEF_RFFT_F32_%d" % size)
222
223 return(result)
224
225def crfftFastCF16Config(cmake,size):
226 result=[]
227 s1 = size >> 1
228 if test(cmake,"RFFT_FAST_F16_%d" % size):
229 result =[]
230 result.append("-DARM_TABLE_TWIDDLECOEF_F16_%d" % s1)
231 result.append("-DARM_TABLE_BITREVIDX_FLT_%d" % s1)
232 result.append("-DARM_TABLE_BITREVIDX_FXT_%d" % s1)
233 result.append("-DARM_TABLE_TWIDDLECOEF_RFFT_F16_%d" % size)
234
235 return(result)
236
237# Deprecated RFFT used in DCT
238def crfftF32Config(cmake,size):
239 result=[]
240 s1 = size >> 1
241 if test(cmake,"RFFT_FAST_F16_%d" % size):
242 result =[]
243 result.append("-DARM_TABLE_REALCOEF_F32")
244 result.append("-ARM_TABLE_BITREV_%d" % s1)
245 result.append("-ARM_TABLE_TWIDDLECOEF_F32_%d" % s1)
246
247 return(result)
248
249
250def crfftFixedConfig(cmake,dt,size):
251 result=[]
252 s1 = size >> 1
253 if test(cmake,"RFFT_%s_%d" % (dt,size)):
254 result =[]
255 result.append("-DARM_TABLE_REALCOEF_%s" % dt)
256 result.append("-DARM_TABLE_TWIDDLECOEF_%s_%d" % (dt,s1))
257 result.append("-DARM_TABLE_BITREVIDX_FXT_%d" % s1)
258
259 return(result)
260
261
262def dctConfig(cmake,dt,size):
263 result=[]
264 if test(cmake,"DCT4_%s_%d" % (dt,size)):
265 result =[]
266 result.append("-DARM_TABLE_DCT4_%s_%d" % (dt,size))
267 result.append("-DARM_TABLE_REALCOEF_F32")
268 result.append("-DARM_TABLE_BITREV_1024" )
269 result.append("-DARM_TABLE_TWIDDLECOEF_%s_4096" % dt)
270
271 return(result)
272
273# Convert cmake options to make flags
274def interpretCmakeOptions(cmake):
275 r=[]
276 if test(cmake,"CONFIGTABLE"):
277 r.append("-DARM_DSP_CONFIG_TABLES")
278 # In Make configuration we build all modules.
279 # So the code for FFT and FAST maths may be included
280 # so we allow the table to be included if they are needed.
281 r.append("-DARM_FAST_ALLOW_TABLES")
282 r.append("-DARM_FFT_ALLOW_TABLES")
283 for size in CFFTSIZE:
284 r += cfftCF32Config(cmake,size)
285 r += cfftCF16Config(cmake,size)
286 r += cfftCF64Config(cmake,size)
287 r += cfftCFixedConfig(cmake,"Q31",size)
288 r += cfftCFixedConfig(cmake,"Q15",size)
289
290 for size in RFFTFASTSIZE:
291 r += crfftFastCF64Config(cmake,size)
292 r += crfftFastCF32Config(cmake,size)
293 r += crfftFastCF16Config(cmake,size)
294
295 for size in RFFTSIZE:
296 r += crfftFixedConfig(cmake,"F32",size)
297 r += crfftFixedConfig(cmake,"Q31",size)
298 r += crfftFixedConfig(cmake,"Q15",size)
299
300 for size in DCTSIZE:
301 r += dctConfig(cmake,"F32",size)
302 r += dctConfig(cmake,"Q31",size)
303 r += dctConfig(cmake,"Q15",size)
304
305
306
307 if test(cmake,"ALLFAST"):
308 r.append("-DARM_ALL_FAST_TABLES")
309 if test(cmake,"ALLFFT"):
310 r.append("-DARM_ALL_FFT_TABLES")
311
312 if test(cmake,"LOOPUNROLL"):
313 r.append("-DARM_MATH_LOOPUNROLL")
314 if test(cmake,"ROUNDING"):
315 r.append("-DARM_MATH_ROUNDING")
316 if test(cmake,"MATRIXCHECK"):
317 r.append("-DARM_MATH_MATRIX_CHECK")
318 if test(cmake,"AUTOVECTORIZE"):
319 r.append("-DARM_MATH_AUTOVECTORIZE")
320 if test(cmake,"DISABLEFLOAT16"):
321 r.append("-DDISABLEFLOAT16")
322 if test(cmake,"NEON"):
323 r.append("-DARM_MATH_NEON")
324 r.append("-DARM_MATH_NEON_EXPERIMENTAL")
325 if test(cmake,"HOST"):
326 r.append("-D__GNUC_PYTHON__")
327
328 if test(cmake,"ARM_COS_F32"):
329 r.append("-DARM_TABLE_SIN_F32")
330 if test(cmake,"ARM_COS_Q31"):
331 r.append("-DARM_TABLE_SIN_Q31")
332 if test(cmake,"ARM_COS_Q15"):
333 r.append("-DARM_TABLE_SIN_Q15")
334
335 if test(cmake,"ARM_SIN_F32"):
336 r.append("-DARM_TABLE_SIN_F32")
337 if test(cmake,"ARM_SIN_Q31"):
338 r.append("-DARM_TABLE_SIN_Q31")
339 if test(cmake,"ARM_SIN_Q15"):
340 r.append("-DARM_TABLE_SIN_Q15")
341
342 if test(cmake,"ARM_SIN_COS_F32"):
343 r.append("-DARM_TABLE_SIN_F32")
344 if test(cmake,"ARM_SIN_COS_Q31"):
345 r.append("-DARM_TABLE_SIN_Q31")
346
347 if test(cmake,"ARM_LMS_NORM_Q31"):
348 r.append("-DARM_TABLE_RECIP_Q31")
349
350 if test(cmake,"ARM_LMS_NORM_Q15"):
351 r.append("-DARM_TABLE_RECIP_Q15")
352
353 if test(cmake,"ARM_CMPLX_MAG_Q31"):
354 r.append("-DARM_TABLE_FAST_SQRT_Q31_MVE")
355
356 if test(cmake,"ARM_CMPLX_MAG_Q15"):
357 r.append("-DARM_TABLE_FAST_SQRT_Q15_MVE")
358
359 if test(cmake,"MVEI"):
360 r.append("-DARM_MATH_MVEI")
361
362 if test(cmake,"MVEF"):
363 r.append("-DARM_MATH_MVEF")
364
365 if test(cmake,"HELIUM") or test(cmake,"MVEF") or test(cmake,"MVEI"):
366 r.append("-IPrivateInclude")
367
368 if test(cmake,"NEON") or test(cmake,"NEONEXPERIMENTAL"):
369 r.append("-IComputeLibrary/Include")
370
371 return (removeDuplicates(r))
372
373def genMakeOptions(config):
374 cmake = computeCmakeOptions(config)
375 r=interpretCmakeOptions(cmake)
376 return(r,cmake)
377
378
379def check(config,s,name=None,comment=None):
380 if comment is not None:
381 st.sidebar.text(comment)
382 if name is None:
383 config[s]=st.sidebar.checkbox(s,value=config[s])
384 else:
385 config[s]=st.sidebar.checkbox(name,value=config[s])
386 return(config[s])
387
388def genconfig(config,transform,sizes,datatypes):
389 global realname
390 for size in sizes:
391 for dt in datatypes:
392 s="%s_%s_%s" % (transform,dt,size)
393 config[s] = False
394 realname[s] = s
395
396def hasDCTF32(config):
397 result=False
398 for size in DCTSIZE:
399 s="DCT4_F32_%s" % size
400 if config[s]:
401 result = True
402 return(result)
403
404def multiselect(config,name,options):
405 default=[]
406 for r in options:
407 if config[r]:
408 default.append(r)
409 result=st.sidebar.multiselect(name,options,default=default)
410 for r in options:
411 config[r] = False
412 for r in result:
413 config[r] = True
414
415def genui(config,transform,sizes,datatypes):
416 keepF32 = True
417 # RFFT F32 is deprecated and needed only for DCT4
418 if transform == "RFFT":
419 keepF32 = hasDCTF32(config)
420 selected=st.sidebar.multiselect("Sizes",sizes)
421 for size in selected:
422 options=[]
423 for dt in datatypes:
424 if dt != "F32" or keepF32:
425 s="%s_%s_%s" % (transform,dt,size)
426 options.append(s)
427 multiselect(config,"Nb = %d" % size,options)
428
429
430def configMake(config):
431 st.sidebar.header('Table Configuration')
432 st.sidebar.info("Several options to include only the tables needed in an app and minimize code size.")
433 if not check(config,"allTables","All tables included"):
434
435 if not check(config,"allFFTs","All FFT tables included"):
436 st.sidebar.markdown("#### CFFT")
437 genui(config,"CFFT",CFFTSIZE,CFFTDATATYPE)
438
439 st.sidebar.info("Following transforms are using the CFFT. You need to enable the needed CFFTs above.")
440
441 st.sidebar.markdown("#### RFFT FAST")
442 genui(config,"RFFT_FAST",RFFTFASTSIZE,RFFTFASTDATATYPE)
443 st.sidebar.markdown("#### DCT4")
444 genui(config,"DCT4",DCTSIZE,DCTDATATYPE)
445 st.sidebar.markdown("#### RFFT")
446 genui(config,"RFFT",RFFTSIZE,RFFTDATATYPE)
447
448
449
450
451 if not check(config,"allInterpolations",'All interpolation tables included'):
452 selected=st.sidebar.multiselect("Functions",["Cosine","Sine","SineCosine","Normalized LMS"])
453 for s in selected:
454 if s == "Cosine":
455 multiselect(config,"Cosine",["COS_F32","COS_Q31","COS_Q15"])
456 if s == "Sine":
457 multiselect(config,"Sine",["SIN_F32","SIN_Q31","SIN_Q15"])
458 if s == "SineCosine":
459 multiselect(config,"SineCosine",["SIN_COS_F32","SIN_COS_Q31"])
460 if s == "Normalized LMS":
461 multiselect(config,"Normalized LMS",["LMS_NORM_Q31","LMS_NORM_Q15"])
462
463 if config["MVEI"]:
464 st.sidebar.markdown("#### Complex Magnitude")
465 multiselect(config,"Complex Magnitude",["CMPLX_MAG_Q31","CMPLX_MAG_Q15"])
466
467
468
469def configCMake(config):
470 multiselect(config,"Folders",["BASICMATH",
471 "COMPLEXMATH",
472 "CONTROLLER",
473 "FASTMATH",
474 "FILTERING",
475 "MATRIX",
476 "STATISTICS",
477 "SUPPORT",
478 "TRANSFORM",
479 "SVM",
480 "BAYES",
481 "DISTANCE",
482 "INTERPOLATION"])
483 configMake(config)
484
485genconfig(config,"CFFT",CFFTSIZE,CFFTDATATYPE)
486genconfig(config,"RFFT_FAST",RFFTFASTSIZE,RFFTFASTDATATYPE)
487genconfig(config,"RFFT",RFFTSIZE,RFFTDATATYPE)
488genconfig(config,"DCT4",DCTSIZE,DCTDATATYPE)
489
490st.title('CMSIS-DSP Configuration')
491
492st.warning("It is a work in progress. Only a small subset of the combinations has been tested.")
493
494st.sidebar.header('Feature Configuration')
495st.sidebar.info("To build on host. All features will be enabled.")
496forHost=check(config,"HOST")
497
498if not forHost:
499 st.sidebar.info("Enable or disable float16 support")
500 check(config,"Float16")
501
502 st.sidebar.info("Some configurations for the CMSIS-DSP code.")
503 check(config,"LOOPUNROLL")
504 st.sidebar.text("Decrease performances when selected:")
505 check(config,"ROUNDING")
506 check(config,"MATRIXCHECK")
507
508 st.sidebar.info("Enable vector code. It is not automatic for Neon. Use of Helium will enable new options to select some interpolation tables.")
509 archi=st.sidebar.selectbox("Vector",('None','Helium','Neon'))
510 if archi == 'Neon':
511 config["NEON"]=True
512 if archi == 'Helium':
513 multiselect(config,"MVE configuration",["MVEI","MVEF"])
514 HELIUM=True
515 if archi != 'None':
516 st.sidebar.info("When autovectorization is on, pure C code will be compiled. The version with C intrinsics won't be compiled.")
517 check(config,"AUTOVECTORIZE")
518
519
520
521st.sidebar.header('Build Method')
522
523st.sidebar.info("With cmake, some folders can be removed from the build.")
524selected=st.sidebar.selectbox('Select', ("Make","Cmake"),index=1)
525
526
527
528if selected == "Make":
529 if not forHost:
530 configMake(config)
531 result,cmake=genMakeOptions(config)
532else:
533 if not forHost:
534 configCMake(config)
535 result,cmake=genCMakeOptions(config)
536
537st.header('Build options for %s command line' % selected)
538
539if selected == "Make":
540 if test(cmake,"FLOAT16"):
541 st.info("Float16 is selected. You may need to pass compiler specific options for the compiler to recognize the float16 type.")
542
543mode=st.selectbox("Mode",["txt","MDK","sh","bat"])
544
545if mode=="txt":
546 st.code(textwrap.fill(options(result)))
547
548if mode=="MDK":
549 opts=options(result)
550 includes=""
551 maybeincludes=re.findall(r'\-I([^\s]+)',opts)
552 # Managed in MDK pack file
553 #if maybeincludes:
554 # includes = maybeincludes
555 # st.text("Following include directories must be added")
556 # st.code(includes)
557 opts=re.sub(r'\-D','',opts)
558 opts=re.sub(r'\-I[^\s]+','',opts)
559 st.text("MDK Preprocessor Symbols ")
560 st.code(opts)
561
562
563if mode=="sh":
564 lines=options(result).split()
565 txt=""
566 for l in lines:
567 txt += " %s \\\n" % l
568 txt += "\n"
569 st.code(txt)
570
571if mode=="bat":
572 lines=options(result).split()
573 txt=""
574 for l in lines:
575 txt += " %s ^\n" % l
576 txt += "\n"
577 st.code(txt)
578