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