Created
September 9, 2020 03:05
-
-
Save notfoundry/aa927a9ef07a3a5990b08c5e78b0b492 to your computer and use it in GitHub Desktop.
4-bit ALU metaprogrammed in C11's _Generic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const static struct _0 {} _0; | |
| const static struct _1 {} _1; | |
| #define G7_SPLICE(expr) __typeof__(expr) | |
| #define G7_STRUCT(...) (struct { __VA_ARGS__ } ){} | |
| #define G7_NAND(a, b) \ | |
| _Generic(a, \ | |
| struct _0: _1, \ | |
| struct _1: \ | |
| _Generic(b, struct _0: _1, struct _1: _0)) | |
| #define G7_NOT(a) G7_NAND(a,a) | |
| #define G7_AND(a, b) G7_NOT(G7_NAND(a, b)) | |
| #define G7_OR(a, b) G7_NAND(G7_NOT(a), G7_NOT(b)) | |
| #define G7_NOR(a, b) G7_NOT(G7_OR(a, b)) | |
| #define G7_XOR(a, b) G7_NAND(G7_NAND(a, G7_NAND(a, b)), G7_NAND(G7_NAND(a, b), b)) | |
| #define G7_XNOR(a, b) G7_NOT(G7_XOR(a, b)) | |
| #define G7_MUX_2_1(a, b, s) G7_NAND(G7_NAND(a, G7_NOT(s)), G7_NAND(b, s)) | |
| #define G7_HALF_ADD_2_1(a, b) \ | |
| G7_STRUCT( \ | |
| G7_SPLICE(G7_XOR(a, b)) sum; \ | |
| G7_SPLICE(G7_AND(a, b)) carry; \ | |
| ) | |
| #define G7_FULL_ADD_2_1(a, b, c) \ | |
| G7_STRUCT( \ | |
| G7_SPLICE( \ | |
| G7_HALF_ADD_2_1(c, G7_HALF_ADD_2_1(a, b).sum).sum \ | |
| ) sum; \ | |
| G7_SPLICE( \ | |
| G7_OR( \ | |
| G7_HALF_ADD_2_1(a, b).carry, \ | |
| G7_HALF_ADD_2_1(c, G7_HALF_ADD_2_1(a, b).sum).carry \ | |
| ) \ | |
| ) carry; \ | |
| ) | |
| #define G7_FULL_ADD_8_4(x3, x2, x1, x0, y3, y2, y1, y0, c) \ | |
| G7_STRUCT( \ | |
| G7_SPLICE( \ | |
| G7_FULL_ADD_2_1(x0, y0, c).sum \ | |
| ) s0; \ | |
| G7_SPLICE( \ | |
| G7_FULL_ADD_2_1(x1, y1, \ | |
| G7_FULL_ADD_2_1(x0, y0, c).carry).sum \ | |
| ) s1; \ | |
| G7_SPLICE( \ | |
| G7_FULL_ADD_2_1(x2, y2, \ | |
| G7_FULL_ADD_2_1(x1, y1, \ | |
| G7_FULL_ADD_2_1(x0, y0, c).carry).carry).sum \ | |
| ) s2; \ | |
| G7_SPLICE( \ | |
| G7_FULL_ADD_2_1(x3, y3, \ | |
| G7_FULL_ADD_2_1(x2, y2, \ | |
| G7_FULL_ADD_2_1(x1, y1, \ | |
| G7_FULL_ADD_2_1(x0, y0, c).carry).carry).carry).sum \ | |
| ) s3; \ | |
| G7_SPLICE( \ | |
| G7_FULL_ADD_2_1(x3, y3, \ | |
| G7_FULL_ADD_2_1(x2, y2, \ | |
| G7_FULL_ADD_2_1(x1, y1, \ | |
| G7_FULL_ADD_2_1(x0, y0, c).carry).carry).carry).carry \ | |
| ) c; \ | |
| ) | |
| #define G7_TO_INT_1(x) _Generic(x, struct _0: 0, struct _1: 1) | |
| #define G7_TO_INT_4(x3, x2, x1, x0) \ | |
| _Generic(x3, struct _0: 0, struct _1: 8) \ | |
| + _Generic(x2, struct _0: 0, struct _1: 4) \ | |
| + _Generic(x1, struct _0: 0, struct _1: 2) \ | |
| + _Generic(x0, struct _0: 0, struct _1: 1) | |
| #define sum G7_FULL_ADD_8_4( \ | |
| _0, _0, _1, _0, \ | |
| _0, _0, _1, _0, \ | |
| _0 \ | |
| ) | |
| _Static_assert(G7_TO_INT_4(sum.s3, sum.s2, sum.s1, sum.s0) == 4, "wtf"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment