This is a collection of interesting tools, sandboxes and projects I end up doing when I want to learn new things about programming (and more specifically scientific-programming), IC Design how EDA tools for IC design work and can be innovated.
Hope you find something that you would like to try for yourself!
Programming in C-lang with Jupyter Notebooks
Introduction: Hello World!
Start by writting your C-lang file:
%%file hello_world.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
printf("Hello World from C in Jupyter!");
exit(0);
}
Overwriting hello_world.c
Now, compile your C code.
%%bash
gcc --version
Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Compiling the code with the:
- -W
or --Wall
flag is useful, enabling a wide variety of usefull warnings
- -Werror
treats critical warnings as errors, to make your code bulletproof once debugged.
%%bash
gcc ./hello_world.c -g -Werror -o hello_world
Now, we can finally execute our C code from Jupyter.
%%bash
./hello_world
Hello World from C in Jupyter!
Testing the C program: Python scripting
We can now take advantage of having a documentation system with shell and Python scripting capabilities to quickly develop input testing files to run multiple test cases against the C program. This effectively automates the unit testing of the C program.
from itertools import permutations
inputs = permutations([3, '+', 43])
with open('permutations.in', 'w') as testfile:
def str_from_perm(perm: list) -> str:
s = str(perm)
s = s.replace('(', ''); s = s.replace(')', '');
s = s.replace("'", ''); s = s.replace(',', '')
return s + '\n'
[testfile.write(str_from_perm(perm)) for perm in inputs]
%cat permutations.in
3 + 43
3 43 +
+ 3 43
+ 43 3
43 3 +
43 + 3
%%file permutations.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
char *expected_tokens[] = {"3", "A", "+", "6", "43", NULL};
int arg_in_expected_tokens(char *arg, char **tokens){
int found_token_chars = 0;
for(char **it_token = tokens; *it_token != NULL; it_token++){
if(!strcmp(arg, *it_token))
return 1;
}
printf("Assertion Failed: %s not in [", arg);
for(char **it_token = tokens; *it_token != NULL; ++it_token)
printf("%s, ", *it_token);
printf("]\n");
return 0;
}
int main(int argc, char **argv) {
assert(argc>1);
for(int i = 1; i < argc; i++)
assert(arg_in_expected_tokens(argv[i], expected_tokens));
printf("Tests: Passed\n");
exit(0);
}
Overwriting permutations.c
%%bash
gcc ./permutations.c -g -Werror -o permutations
Finally, use bash shell scripting to input all inputs, line by line, to the C programm, so that each test is verified.
%%bash
echo "" > permutations.out
cat permutations.in | while read line
do
./permutations $line >> permutations.out
done
%cat permutations.out
Tests: Passed
Tests: Passed
Tests: Passed
Tests: Passed
Tests: Passed
Tests: Passed
If you're developing in Linux, you can even use Valgrind to automatically detect many memory management and threading bugs, and profile your programs in detail.