mirror of https://github.com/YosysHQ/yosys.git
Compare commits
1045 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
136d80e3d7 | |
|
|
337df7fc75 | |
|
|
afc0e78d11 | |
|
|
780588f28c | |
|
|
0d15cb55bf | |
|
|
ce280354cf | |
|
|
a727e7f6e7 | |
|
|
bcc736ed7d | |
|
|
8125af88d6 | |
|
|
7d3819c6bb | |
|
|
8bb194af22 | |
|
|
86f2ddebce | |
|
|
2105caa844 | |
|
|
904151acd8 | |
|
|
c89cfe1e6e | |
|
|
a14650d07b | |
|
|
e56c6a954c | |
|
|
b85777a6e6 | |
|
|
80bdbaa010 | |
|
|
1d86b3cd6e | |
|
|
1801abf30a | |
|
|
d8587f44f0 | |
|
|
4230ebff71 | |
|
|
715bc4d7d2 | |
|
|
1414012676 | |
|
|
7fef67a141 | |
|
|
d6106f141c | |
|
|
680bb69d85 | |
|
|
94ec78b6e8 | |
|
|
6f111118de | |
|
|
9d0cdb8551 | |
|
|
4c8e61a52b | |
|
|
07924a3c62 | |
|
|
2b3f4c37f5 | |
|
|
15e09163cd | |
|
|
c0779f488a | |
|
|
5c6de04467 | |
|
|
ffa8618413 | |
|
|
2159a0e634 | |
|
|
0c2786be1f | |
|
|
1c831aa50d | |
|
|
d322e2fbe0 | |
|
|
7bcda9d304 | |
|
|
8b68ac04f7 | |
|
|
35d13e1c32 | |
|
|
4a4c3a3be6 | |
|
|
ef092e1f15 | |
|
|
75dcbe03c6 | |
|
|
8bbc3c359c | |
|
|
59c1bc35cb | |
|
|
e87a9bd9a7 | |
|
|
4b3165dd50 | |
|
|
1d87cefd80 | |
|
|
36eceed720 | |
|
|
992eceaaa0 | |
|
|
e4a3b44e8e | |
|
|
8022b5445b | |
|
|
c16e0352f7 | |
|
|
b423cc3bd6 | |
|
|
965a3e67f0 | |
|
|
4a7878b17f | |
|
|
9580ebabc5 | |
|
|
58df27ce7c | |
|
|
c6f53aec5f | |
|
|
70b17181b4 | |
|
|
6ac8758e7e | |
|
|
27ae62f492 | |
|
|
e20a57b09e | |
|
|
6d4e5f5ad0 | |
|
|
9070c83145 | |
|
|
9182329fa1 | |
|
|
105011a53b | |
|
|
81219c58b2 | |
|
|
1ef6311e5b | |
|
|
25459bd8b9 | |
|
|
90e019e319 | |
|
|
6ff6f8fb3c | |
|
|
1e28e8ccab | |
|
|
2046a23a2f | |
|
|
74efc883c7 | |
|
|
90c26fe671 | |
|
|
3a150f2883 | |
|
|
4eb1c61bd5 | |
|
|
b06f9bdf18 | |
|
|
6f16a5cf5f | |
|
|
b85cad6347 | |
|
|
3c619da259 | |
|
|
b61bc1eee0 | |
|
|
54866d154f | |
|
|
84605d89b7 | |
|
|
7fe32137bd | |
|
|
40c1485828 | |
|
|
fb83719745 | |
|
|
e41b969da2 | |
|
|
89d83a3410 | |
|
|
1f02343268 | |
|
|
db258e6dd9 | |
|
|
3f68ee851b | |
|
|
bfc09777e6 | |
|
|
3f354eb03b | |
|
|
10dc0d48b8 | |
|
|
425d47ad2c | |
|
|
687e5442f2 | |
|
|
f4a10a4808 | |
|
|
4e35ed5955 | |
|
|
cb6209506e | |
|
|
f8a50e7174 | |
|
|
3b26a9e45e | |
|
|
ab316c14d2 | |
|
|
de1dd3b1c5 | |
|
|
fecea911ff | |
|
|
0641b7a725 | |
|
|
7de7d04d7c | |
|
|
fff034d2f8 | |
|
|
49b4f6d813 | |
|
|
50266c8aa8 | |
|
|
73e15f2144 | |
|
|
b864f70e52 | |
|
|
8427bd3a35 | |
|
|
67fac1879c | |
|
|
7fa660fc60 | |
|
|
16b893bd88 | |
|
|
239e3c2849 | |
|
|
6cd784e52c | |
|
|
df1fb14b0c | |
|
|
ca88868902 | |
|
|
5dfe1937a0 | |
|
|
18b832247b | |
|
|
805c302411 | |
|
|
92287d4857 | |
|
|
d2f7fecef5 | |
|
|
0d3923d086 | |
|
|
a966d06524 | |
|
|
cfa66f5335 | |
|
|
4dbae6a473 | |
|
|
627b691578 | |
|
|
6b78731792 | |
|
|
5197b9c8ce | |
|
|
3187275184 | |
|
|
c03c0d5f9d | |
|
|
59b3b6d4e4 | |
|
|
c5a8c3cca5 | |
|
|
ec0a102302 | |
|
|
30a914167f | |
|
|
e0b833ac1a | |
|
|
4abaca273e | |
|
|
10bbda93f7 | |
|
|
a2dafce910 | |
|
|
25b9b796c4 | |
|
|
390f09b89a | |
|
|
23a05fcf35 | |
|
|
e69341cd5f | |
|
|
2dc69a7578 | |
|
|
14d0138d0c | |
|
|
dc570e3d55 | |
|
|
14b0efeced | |
|
|
7e7336cdb8 | |
|
|
d795a4f1d2 | |
|
|
afac9a28b0 | |
|
|
5d4d94a5dd | |
|
|
94a215b4f7 | |
|
|
edd3ad525e | |
|
|
9143178343 | |
|
|
bc83311dd8 | |
|
|
64e7ce2f57 | |
|
|
f213a34427 | |
|
|
70ee009dd9 | |
|
|
3ccbd38cc6 | |
|
|
a89e8fd869 | |
|
|
ed5d122174 | |
|
|
2da90a5ad6 | |
|
|
240f7030b2 | |
|
|
22ef992189 | |
|
|
33fba24158 | |
|
|
89d360aa4a | |
|
|
aba5b279c6 | |
|
|
b4c081c70b | |
|
|
a666712687 | |
|
|
5737d2db35 | |
|
|
76732497b9 | |
|
|
bfd3e150fa | |
|
|
f04532bbac | |
|
|
8bed9bd824 | |
|
|
a490f1c3c4 | |
|
|
9c3d79b041 | |
|
|
1aad357370 | |
|
|
5ffa0b1dd7 | |
|
|
686267ea81 | |
|
|
bfd639f6a0 | |
|
|
f087a94470 | |
|
|
f42800d4d3 | |
|
|
c272bfbdc3 | |
|
|
149e2f343a | |
|
|
4a89ae66ff | |
|
|
1c76cadac7 | |
|
|
fdccbe584d | |
|
|
514c55f53f | |
|
|
3ceeb3b00c | |
|
|
58e0473e29 | |
|
|
ee31950770 | |
|
|
4a9dc33098 | |
|
|
1effec2029 | |
|
|
c15bcca25a | |
|
|
0ba9a0fb16 | |
|
|
d1dc23d9f8 | |
|
|
652bbd2b41 | |
|
|
68e01a03d7 | |
|
|
2bc46e77c8 | |
|
|
1231bd5397 | |
|
|
5a06a79c0c | |
|
|
2a8d369be3 | |
|
|
1bfb95513c | |
|
|
474d0d7b2e | |
|
|
8953007483 | |
|
|
f96fa5ff00 | |
|
|
8ff28a2a86 | |
|
|
336a06d091 | |
|
|
c04d724337 | |
|
|
45bb0413bf | |
|
|
b361569abf | |
|
|
ced2521b03 | |
|
|
a2e1fbcfc6 | |
|
|
2f9e35acb8 | |
|
|
712ce93501 | |
|
|
999255e40c | |
|
|
2774671346 | |
|
|
fc55f16fae | |
|
|
3c2adfb523 | |
|
|
ff2dcef53f | |
|
|
8f7e5e9449 | |
|
|
5494000fd7 | |
|
|
c99855535a | |
|
|
0b3d03e69c | |
|
|
3e45f9729e | |
|
|
413169663d | |
|
|
4506dffa9f | |
|
|
fc71719e6e | |
|
|
c3c577f333 | |
|
|
135812ab02 | |
|
|
847a8941e9 | |
|
|
a02c238874 | |
|
|
4bbffecf98 | |
|
|
42c309347b | |
|
|
b6d656e932 | |
|
|
b6a8feec22 | |
|
|
67e145618b | |
|
|
4f4c820f73 | |
|
|
9cc2e7d95e | |
|
|
0f61ba5299 | |
|
|
9dc408eea7 | |
|
|
5d90bcc792 | |
|
|
fc9adae9a2 | |
|
|
ab1c423692 | |
|
|
b64b75db7a | |
|
|
cfee6bb4af | |
|
|
6b0caedcdd | |
|
|
335cce4895 | |
|
|
7183016910 | |
|
|
1a4a41812c | |
|
|
4c4c5cf15a | |
|
|
e69914b8be | |
|
|
46df888191 | |
|
|
90b906c4fc | |
|
|
d51a5535c7 | |
|
|
564c617721 | |
|
|
a54bca5493 | |
|
|
8449dd4700 | |
|
|
dbc6911f40 | |
|
|
7c714b8acc | |
|
|
a4b6a8c580 | |
|
|
9a0842b76a | |
|
|
cb56f01971 | |
|
|
1f6559a5cf | |
|
|
74070911cd | |
|
|
6d2c445aeb | |
|
|
86448c0001 | |
|
|
f7b19774b7 | |
|
|
6b5cd74d7e | |
|
|
6d715784cd | |
|
|
f09afcf581 | |
|
|
b485173428 | |
|
|
d586af0074 | |
|
|
9b9e334c79 | |
|
|
cc3827c80c | |
|
|
2572b1e3df | |
|
|
9385928bc2 | |
|
|
d6518f1b9a | |
|
|
342b0e5fc1 | |
|
|
8bf42c01ce | |
|
|
d75d513402 | |
|
|
a96cf8cc2b | |
|
|
41b69df2cb | |
|
|
cd49dc7be8 | |
|
|
41b41fefb3 | |
|
|
2033df5958 | |
|
|
37ca545b65 | |
|
|
d58e0447c7 | |
|
|
52243e10fb | |
|
|
cdf549a493 | |
|
|
b55fd6718b | |
|
|
cede13a742 | |
|
|
ecaaea8734 | |
|
|
568a31c83a | |
|
|
162eeea29a | |
|
|
240439bdb0 | |
|
|
903695892a | |
|
|
6a5fea1b27 | |
|
|
0f87fd8ef6 | |
|
|
417e871b06 | |
|
|
23cfeabfe1 | |
|
|
74fef31bf2 | |
|
|
18bcd0b499 | |
|
|
d37b02af03 | |
|
|
ebfe5b2c06 | |
|
|
5b22e64d19 | |
|
|
290fb0556d | |
|
|
66306a8ca3 | |
|
|
cc915b4c76 | |
|
|
b44188110b | |
|
|
7b2ab9b245 | |
|
|
69219e6be0 | |
|
|
12b443e71c | |
|
|
0e7f7c826d | |
|
|
5fd39ff3e1 | |
|
|
dc77140275 | |
|
|
ee0461eb00 | |
|
|
d6ab610622 | |
|
|
2a8024ea4a | |
|
|
f560cba952 | |
|
|
27210627e5 | |
|
|
8d1d5a25e5 | |
|
|
05de1c4ae2 | |
|
|
4f4672d17b | |
|
|
7aaa0621d3 | |
|
|
9746bd3897 | |
|
|
ad7a776d73 | |
|
|
27737c6e2e | |
|
|
ea11453cef | |
|
|
23ce4b8560 | |
|
|
a141bd941c | |
|
|
4a6bd6a2fe | |
|
|
f9d930ba5a | |
|
|
c4cc53a72e | |
|
|
bccfdef05d | |
|
|
e05ed6b850 | |
|
|
18a7c54ebd | |
|
|
0b3f103745 | |
|
|
93c762c7c1 | |
|
|
926814f1e4 | |
|
|
0ea739b7d9 | |
|
|
150860c1c3 | |
|
|
e78690fc47 | |
|
|
c8f715fed8 | |
|
|
06264cdb2e | |
|
|
1111a401f7 | |
|
|
4251cd69ed | |
|
|
49ecb1ac11 | |
|
|
4716f4410f | |
|
|
53939bd3ba | |
|
|
18d94fe9a4 | |
|
|
5c74446e57 | |
|
|
4d725ee84d | |
|
|
c5c104f560 | |
|
|
498cb79abe | |
|
|
43ef4d2901 | |
|
|
de99d67bbd | |
|
|
fea0d18c0a | |
|
|
314d01b35f | |
|
|
47c2257f82 | |
|
|
c23ba3f917 | |
|
|
5048dac854 | |
|
|
9e666c727f | |
|
|
2f1cdc2df9 | |
|
|
85013f9ed3 | |
|
|
167c6c4585 | |
|
|
050483a6b2 | |
|
|
602f3fd1a5 | |
|
|
52533b0d1c | |
|
|
9c51ba1b09 | |
|
|
8d8c05b338 | |
|
|
32f5044eaf | |
|
|
70cc2d67fd | |
|
|
1260fda83a | |
|
|
cdfc586f18 | |
|
|
1e96328ede | |
|
|
3910d569da | |
|
|
ac55935a68 | |
|
|
3603cd52a0 | |
|
|
7f3b11e56b | |
|
|
19a7c8fcf3 | |
|
|
8e044d1045 | |
|
|
a7437c636d | |
|
|
887c32cb54 | |
|
|
72a21fe01d | |
|
|
c2bb7d6a82 | |
|
|
b42bb05b63 | |
|
|
e2166c4684 | |
|
|
5ff7d344c9 | |
|
|
fe329a0e14 | |
|
|
e71da96314 | |
|
|
ab238c3145 | |
|
|
87521df534 | |
|
|
b079e5721c | |
|
|
898a288a99 | |
|
|
13d9fffdb9 | |
|
|
bd7f2d9ba4 | |
|
|
7af5dbae35 | |
|
|
6cd66aed47 | |
|
|
df283fa1c9 | |
|
|
4e54853e35 | |
|
|
d9737acc31 | |
|
|
9288889e20 | |
|
|
95d738edc0 | |
|
|
629bf3dffd | |
|
|
23eb38fe3f | |
|
|
da83c93673 | |
|
|
f3efa51b3e | |
|
|
e2e8245be9 | |
|
|
c747466a7a | |
|
|
91740645a9 | |
|
|
709746b184 | |
|
|
cd60dd4912 | |
|
|
241db706e1 | |
|
|
3592d42d3b | |
|
|
5d3ed5a418 | |
|
|
f06018306d | |
|
|
95ef0cd788 | |
|
|
8a09cc5463 | |
|
|
dea8c275ff | |
|
|
39cb61615f | |
|
|
891b89f60d | |
|
|
4954fc980f | |
|
|
2c3876671b | |
|
|
0a2b6a4f21 | |
|
|
6ee0bfa913 | |
|
|
9dcffc3dbf | |
|
|
99e26d80b0 | |
|
|
9be3cfb3f9 | |
|
|
376f746bc9 | |
|
|
30a03886a5 | |
|
|
ae5325fe53 | |
|
|
c4bec4e8b8 | |
|
|
85eb07d14d | |
|
|
c9f6d7b2d4 | |
|
|
f659cbd159 | |
|
|
6f205b41f5 | |
|
|
4f2f064262 | |
|
|
d5ea7f7016 | |
|
|
4caffa7ebd | |
|
|
6ac8c8cb05 | |
|
|
26dc01102e | |
|
|
94c789e9c8 | |
|
|
39343f5f33 | |
|
|
0d7a875675 | |
|
|
6485a13809 | |
|
|
3bc26ff4d0 | |
|
|
16b1a914f1 | |
|
|
04822c6660 | |
|
|
b8ee0803ab | |
|
|
66bd4716cf | |
|
|
cae54a4c7b | |
|
|
6d4736269b | |
|
|
0284595e9c | |
|
|
793a3513c6 | |
|
|
ae10e9e955 | |
|
|
661fcb24cb | |
|
|
f594014bef | |
|
|
12412d1fa5 | |
|
|
ecb8b20f62 | |
|
|
5216d32d1b | |
|
|
7a5c303ccd | |
|
|
c3ed884bc4 | |
|
|
665b6eeb4a | |
|
|
4ab22cbb97 | |
|
|
d91e1c8607 | |
|
|
31b86ebc2e | |
|
|
8e17fb0266 | |
|
|
a0f87dc2d1 | |
|
|
a9463d1aee | |
|
|
e3f9911e33 | |
|
|
07ec8708e4 | |
|
|
3212dfaf1f | |
|
|
2d7d6ca10b | |
|
|
7e9e88c2ec | |
|
|
9e59f05c25 | |
|
|
35ccaa60d7 | |
|
|
6adc08b0e5 | |
|
|
3671d577a0 | |
|
|
a61455645d | |
|
|
cf4d4ff23d | |
|
|
05d1d56b9d | |
|
|
d3e297fcd4 | |
|
|
228052bfb3 | |
|
|
70a11c6bf0 | |
|
|
b7d013e6bf | |
|
|
750d536bba | |
|
|
126492742b | |
|
|
04113eb95d | |
|
|
5b4603c54f | |
|
|
22916aaab1 | |
|
|
024408004a | |
|
|
6f74c54c02 | |
|
|
857bc02710 | |
|
|
2dddc53ccf | |
|
|
c13a623dbc | |
|
|
ffb76a3486 | |
|
|
a53104379d | |
|
|
1d3f9b7905 | |
|
|
e9442194f2 | |
|
|
687a36af38 | |
|
|
7f1f247c56 | |
|
|
2dd71c3ba2 | |
|
|
b3caec1a93 | |
|
|
5970be33fb | |
|
|
2c52546e2a | |
|
|
5f8489d36d | |
|
|
fd1ac58767 | |
|
|
31f7d0d92d | |
|
|
53d8eb43ff | |
|
|
b51110a50b | |
|
|
fd311c5501 | |
|
|
2386923b8f | |
|
|
fb653c4181 | |
|
|
68e47ebcfe | |
|
|
0ed7c5ad53 | |
|
|
094481739f | |
|
|
13795203a1 | |
|
|
74f7b0cf92 | |
|
|
53509a9b2a | |
|
|
679156d323 | |
|
|
abc7563a35 | |
|
|
c75d80905a | |
|
|
29a270c4b6 | |
|
|
5bb31485b7 | |
|
|
62f19cb3a9 | |
|
|
33a2de9635 | |
|
|
01e89a8f9e | |
|
|
2b4f481850 | |
|
|
77f64de997 | |
|
|
81ea922512 | |
|
|
63068f9b8f | |
|
|
e6e57b33e3 | |
|
|
ac96f318ef | |
|
|
0090aa96b6 | |
|
|
adf8b6b0d8 | |
|
|
c7d88ded94 | |
|
|
1e852cef16 | |
|
|
e2f0c4d9a0 | |
|
|
bb7aa7d208 | |
|
|
e4b32d6aae | |
|
|
e5b3e9fc1f | |
|
|
c6e48f4bea | |
|
|
cc79c6a761 | |
|
|
b055ea05fd | |
|
|
5b94a97fb3 | |
|
|
542b29fa6a | |
|
|
5ea073d45e | |
|
|
9b9e7b5ae3 | |
|
|
ce5321da8c | |
|
|
1319112913 | |
|
|
7a0774c3bb | |
|
|
b890b1b43f | |
|
|
a13b5c4211 | |
|
|
be9c857e72 | |
|
|
b0021e5b10 | |
|
|
1ede98797f | |
|
|
9ad7aed4a5 | |
|
|
12ace45b89 | |
|
|
e3db8fee6f | |
|
|
8ab105ac28 | |
|
|
2e03ee1434 | |
|
|
fba29ea8f1 | |
|
|
43a15113ff | |
|
|
3f1fbfdaee | |
|
|
915912cc76 | |
|
|
c4094e457b | |
|
|
fe613f29b9 | |
|
|
5a46106a46 | |
|
|
a6a07fb39c | |
|
|
98c3f03497 | |
|
|
dfbef2fe24 | |
|
|
9f30f0e7d6 | |
|
|
030e495c8b | |
|
|
a6e33d9916 | |
|
|
d2f7d3cf63 | |
|
|
ff9cd0eed7 | |
|
|
b04948a8cd | |
|
|
6f6fa49d3c | |
|
|
b8ee50d77f | |
|
|
1502e23371 | |
|
|
b2f9ac4fb5 | |
|
|
2bb352a861 | |
|
|
f062a0c8d6 | |
|
|
34f8582725 | |
|
|
1717fa0180 | |
|
|
0640a5904b | |
|
|
8bbde80e02 | |
|
|
2aa0e1d009 | |
|
|
992e64342c | |
|
|
776b4d06a6 | |
|
|
ddfa34d743 | |
|
|
7326bb7d66 | |
|
|
3f01d7a33a | |
|
|
91b226b4d4 | |
|
|
ed53ff2f49 | |
|
|
c768e55983 | |
|
|
2efd0247a1 | |
|
|
d199195785 | |
|
|
8d1c1faf82 | |
|
|
8e73e2a306 | |
|
|
000be270ca | |
|
|
44afd4bbdd | |
|
|
fc11754557 | |
|
|
3bfeaee8ca | |
|
|
6dbe03f0f5 | |
|
|
153ddc0c84 | |
|
|
224549fb88 | |
|
|
414b1b6019 | |
|
|
59653da599 | |
|
|
f5c8368f7a | |
|
|
b88d6588bc | |
|
|
ac427a79b0 | |
|
|
382b28acbe | |
|
|
9c56c93632 | |
|
|
6af1b5b19c | |
|
|
106f289e31 | |
|
|
5a4ad6a6d0 | |
|
|
a68fee1115 | |
|
|
61b1c3c75a | |
|
|
7439d2489e | |
|
|
b70f527c67 | |
|
|
6ba8f3dc19 | |
|
|
43db5c9488 | |
|
|
6007b68e9c | |
|
|
8d504ecb48 | |
|
|
b6c148f84a | |
|
|
1f6a13dac7 | |
|
|
139c38ecfa | |
|
|
8f6c4d40e4 | |
|
|
5a64fe2d91 | |
|
|
8c2ef89732 | |
|
|
74c601db0f | |
|
|
6a6e5f0f54 | |
|
|
188082551a | |
|
|
fc2b7c317f | |
|
|
75008b70e5 | |
|
|
97366933b3 | |
|
|
fdff3dac2b | |
|
|
8ed7ac04d8 | |
|
|
4031310ebb | |
|
|
aaebce7adc | |
|
|
c3ffb48a6b | |
|
|
33e4b1d97f | |
|
|
09ceadfde7 | |
|
|
5b10c7f3c6 | |
|
|
ef3b2b0380 | |
|
|
a3c9716f18 | |
|
|
9367090763 | |
|
|
5803461c24 | |
|
|
29a9e42b64 | |
|
|
8576055dea | |
|
|
673c8d1ae7 | |
|
|
a75e0b2e92 | |
|
|
808ec8c04b | |
|
|
f3c87610f5 | |
|
|
32e96605d4 | |
|
|
7d53d64a47 | |
|
|
2468b391bf | |
|
|
f5ea73eb97 | |
|
|
0e4282d442 | |
|
|
4f53612725 | |
|
|
dcd7742d52 | |
|
|
e87bb65956 | |
|
|
125609105d | |
|
|
98f848e503 | |
|
|
a6fc695522 | |
|
|
317a4d77c7 | |
|
|
5e36503676 | |
|
|
f6eba53d1f | |
|
|
2c12545cf3 | |
|
|
2157f9b3fb | |
|
|
2c0448a81b | |
|
|
57ac113b7f | |
|
|
9ed56ac72c | |
|
|
bd9dbea4ea | |
|
|
0f6ef77775 | |
|
|
979b673f20 | |
|
|
d2b6bd00b1 | |
|
|
6565bf3ebf | |
|
|
12315c0d17 | |
|
|
9315f02c17 | |
|
|
bfd1401b32 | |
|
|
5a9d73369a | |
|
|
d0fa4781c6 | |
|
|
491276983e | |
|
|
90673cb0a2 | |
|
|
f67d4bcfa4 | |
|
|
49e5950791 | |
|
|
0f478a5952 | |
|
|
cc3038f468 | |
|
|
2bde91b6ef | |
|
|
67d10a41e8 | |
|
|
691983be14 | |
|
|
7880f31acb | |
|
|
c3f36afe7f | |
|
|
befadf6d4d | |
|
|
9355fa5037 | |
|
|
28c199fbbd | |
|
|
8da8d681d0 | |
|
|
b43c96b03d | |
|
|
cf511628b0 | |
|
|
d095d2c405 | |
|
|
ed64df737b | |
|
|
d5e1647d11 | |
|
|
fb864e91ee | |
|
|
967b47d984 | |
|
|
305b6c81d7 | |
|
|
60ac3670cb | |
|
|
ddf3c6c8b7 | |
|
|
e0077b188d | |
|
|
763001885f | |
|
|
210b733555 | |
|
|
4c1a18f01d | |
|
|
6aef8ea8ab | |
|
|
8a596f330a | |
|
|
40f9e235de | |
|
|
6a93a94d9f | |
|
|
c305c426eb | |
|
|
8b6925c5b0 | |
|
|
71feb2a2a1 | |
|
|
83c1364eeb | |
|
|
8da113b7f0 | |
|
|
d9956b20f8 | |
|
|
ff3c24fcdc | |
|
|
5ba0e9cae3 | |
|
|
8e2038c419 | |
|
|
21e6833010 | |
|
|
8f00c1824f | |
|
|
0e6973037d | |
|
|
b332279baf | |
|
|
77005b69a2 | |
|
|
b08e044994 | |
|
|
5ae48ee25f | |
|
|
51b210c93c | |
|
|
78cbc21b94 | |
|
|
b8497217bc | |
|
|
cc25ccfcd7 | |
|
|
b3b71df07c | |
|
|
72690062a1 | |
|
|
f193dd0a28 | |
|
|
2b12b74121 | |
|
|
37347aacb2 | |
|
|
991e704899 | |
|
|
cc3d569ade | |
|
|
c7b839ef5a | |
|
|
41a098172d | |
|
|
8da919587d | |
|
|
f1fc704c84 | |
|
|
35321cd292 | |
|
|
9a09758f56 | |
|
|
4d237bdd92 | |
|
|
9f77465170 | |
|
|
c0e29ef57c | |
|
|
fcb8695261 | |
|
|
0ab967b036 | |
|
|
5c630a366d | |
|
|
042ec1cf60 | |
|
|
2e1a2cfacb | |
|
|
11b0e7ad92 | |
|
|
1567526954 | |
|
|
1ccbd21ed8 | |
|
|
6e5a516051 | |
|
|
eae00c19a8 | |
|
|
8a78f2f7c5 | |
|
|
ab4381fba4 | |
|
|
ea90f54783 | |
|
|
8101c87fab | |
|
|
a6d696ba2b | |
|
|
582969b236 | |
|
|
55af32024d | |
|
|
96549e5514 | |
|
|
d523c88c3c | |
|
|
99d7ab9c42 | |
|
|
17ca71e1ab | |
|
|
aa9991d3ee | |
|
|
4bc4e4eb41 | |
|
|
721b504479 | |
|
|
09f9e0e8d1 | |
|
|
31f355c599 | |
|
|
0e61f57458 | |
|
|
9ee51c8f27 | |
|
|
d5b38af4a7 | |
|
|
650c18a2a2 | |
|
|
580b57c772 | |
|
|
13030e43d4 | |
|
|
48cdb499f2 | |
|
|
46cb05c471 | |
|
|
ddd6a16ee0 | |
|
|
914e14946d | |
|
|
856d455065 | |
|
|
772d821fb0 | |
|
|
64a933d77b | |
|
|
45d654e2d7 | |
|
|
49feaa1146 | |
|
|
d861a26e49 | |
|
|
e289e4c893 | |
|
|
cf8be2bae7 | |
|
|
2ded4bd893 | |
|
|
07c9d575fd | |
|
|
b201bf2cf3 | |
|
|
4d61ce63d3 | |
|
|
bd514df0df | |
|
|
18a7d4c262 | |
|
|
5b317ee03c | |
|
|
c69be9d767 | |
|
|
24f4902156 | |
|
|
9d3d8bf502 | |
|
|
52dc8c5eff | |
|
|
2833a44503 | |
|
|
f003eca615 | |
|
|
4da0c552dd | |
|
|
c1ec625f47 | |
|
|
9814f9dc4f | |
|
|
54b278d574 | |
|
|
5594b817cd | |
|
|
e08e9119ee | |
|
|
8703e3b4dd | |
|
|
99e873efc9 | |
|
|
d932ce7f47 | |
|
|
882001cb01 | |
|
|
7f3ea41103 | |
|
|
77f846e992 | |
|
|
2e9db8b850 | |
|
|
1cceaa2a80 | |
|
|
cf9ab4c899 | |
|
|
1af4f243af | |
|
|
6acb79afa2 | |
|
|
23e1b0656c | |
|
|
16a420afee | |
|
|
d274ff8627 | |
|
|
0e31e389f2 | |
|
|
685515865c | |
|
|
518610bbc4 | |
|
|
46fbed6e6f | |
|
|
638e904f91 | |
|
|
2ca28d964b | |
|
|
a871415abf | |
|
|
fc951a28d3 | |
|
|
7219ac94b3 | |
|
|
52b1245547 | |
|
|
2843ea3008 | |
|
|
e2dffbf991 | |
|
|
9c9f4f347e | |
|
|
6778151207 | |
|
|
436a247d60 | |
|
|
58c7dc7cc2 | |
|
|
5bafeb77dc | |
|
|
07a690570e | |
|
|
dd65dd610d | |
|
|
36f0e0392f | |
|
|
b2e527c67e | |
|
|
6842003e76 | |
|
|
e2e7922756 | |
|
|
9ec361beab | |
|
|
9871e9b17e | |
|
|
b2270ae1c8 | |
|
|
cebb80250c | |
|
|
38ee4fc730 | |
|
|
62e666c2ed | |
|
|
fb8a1ad3bc | |
|
|
0f8e1e3bf7 | |
|
|
5f84b8b339 | |
|
|
e223087578 | |
|
|
ade6379345 | |
|
|
ddcd93024f | |
|
|
5d5a7ab443 | |
|
|
473edd19ed | |
|
|
403740428c | |
|
|
ded7c9cb03 | |
|
|
9909049d2a | |
|
|
7e75200b2a | |
|
|
d603b7bb58 | |
|
|
6fe35fa46c | |
|
|
34fa8a4ff7 | |
|
|
9525f79d61 | |
|
|
214d09a8c6 | |
|
|
e4044e1b4a | |
|
|
c43246bba5 | |
|
|
c1e40e113c | |
|
|
7cb3a0f830 | |
|
|
752d24c0a8 | |
|
|
b23dc345ae | |
|
|
948001f39f | |
|
|
8f0ecce53f | |
|
|
4c8b537d71 | |
|
|
7f9de6e48f | |
|
|
10fd97821e | |
|
|
cae020a581 | |
|
|
5d3599a78c | |
|
|
d4e0437cfd | |
|
|
a8e8746fc0 | |
|
|
ba31a02578 | |
|
|
38a1e66145 | |
|
|
510f9ef63d | |
|
|
e8cbc92462 | |
|
|
faa1e8fac4 | |
|
|
0d954f2f4c | |
|
|
d550757b4e | |
|
|
53614a37a1 | |
|
|
33a49452d9 | |
|
|
f098352ae6 | |
|
|
615e338acd | |
|
|
542723d121 | |
|
|
bf70581efa | |
|
|
44ab884b06 | |
|
|
e33ca17388 | |
|
|
4d1b688717 | |
|
|
bfc957ee2d | |
|
|
b3112bf025 | |
|
|
d5c1cd8fc0 | |
|
|
302643330c | |
|
|
8ea51e1479 | |
|
|
25ba41f424 | |
|
|
6eb9e823e0 | |
|
|
b5625f9189 | |
|
|
e83d721cb0 | |
|
|
58e831486d | |
|
|
2eff366e8c | |
|
|
2cc0770305 | |
|
|
1edc32dcd0 | |
|
|
920f4793fb | |
|
|
229123eb87 | |
|
|
033a2d5a67 | |
|
|
f56e121ddb | |
|
|
650392d4ec | |
|
|
07de7509bf | |
|
|
224ed524fa | |
|
|
94dd248dfb | |
|
|
8a54e51300 | |
|
|
d4228efae8 | |
|
|
075237f73b | |
|
|
48ff9d4950 | |
|
|
ae1235210d | |
|
|
c6491629d8 | |
|
|
24a6412ea8 | |
|
|
21c68e0022 | |
|
|
420a083d9b | |
|
|
834125a076 | |
|
|
dc48ceadd9 | |
|
|
9a3c7f70ad | |
|
|
c26aa3186d | |
|
|
c1c6ec1266 | |
|
|
5a798b64ef | |
|
|
c281bac461 | |
|
|
85d2702ef6 | |
|
|
411fc149df | |
|
|
a5b6c3cc19 | |
|
|
9a5465bc83 | |
|
|
6846168db3 | |
|
|
5acb77cab1 | |
|
|
cee3d0b598 | |
|
|
9f07e21e35 | |
|
|
7bc88d5c40 | |
|
|
793594bd59 | |
|
|
7bed6ec658 | |
|
|
0c4105d72c | |
|
|
bbf1e4bca2 | |
|
|
e4e32d7966 | |
|
|
c2c9506f4f | |
|
|
9e81db4373 | |
|
|
b3ead7e47d | |
|
|
9aa2dde7ef | |
|
|
b8012086a3 | |
|
|
cfa9c8bfc8 | |
|
|
58d4e2c38e | |
|
|
725a1c3a4b | |
|
|
b870693393 | |
|
|
261a0ae9e1 | |
|
|
677bf21947 | |
|
|
84adc82fad | |
|
|
f47540b950 | |
|
|
c497b3b24c | |
|
|
65d7d70507 | |
|
|
ba99c05902 | |
|
|
4bfdc62f65 | |
|
|
b08195a9cf | |
|
|
a75b999f13 | |
|
|
abc78f0424 | |
|
|
b91dbc7324 | |
|
|
40bbb84766 | |
|
|
10b49f3a91 | |
|
|
5e0bc3fd9f | |
|
|
1929956fd7 | |
|
|
f2263642a4 | |
|
|
a915143768 | |
|
|
c48bc56f4a | |
|
|
1dd5b150e5 | |
|
|
bc3fc21248 | |
|
|
04135ba3e4 | |
|
|
ead0f922e1 | |
|
|
8c76f93fce | |
|
|
1ee4fc9d27 | |
|
|
50bfb5c5c9 | |
|
|
d93039a194 | |
|
|
ae281720cf | |
|
|
578d658871 | |
|
|
8c2984dc5f | |
|
|
c4c389fdd7 | |
|
|
325b27f43a | |
|
|
df8444c5e7 | |
|
|
e95ed7bbab | |
|
|
8895757364 | |
|
|
9577a028c8 | |
|
|
b3f3f42577 | |
|
|
b0e2d75dbe | |
|
|
54bde15329 | |
|
|
5133b4bdea | |
|
|
d28f97e9da | |
|
|
0fe79ce01b | |
|
|
e84bc3c6c5 | |
|
|
20639906e3 | |
|
|
32641bbf93 | |
|
|
2319d82efb | |
|
|
5f76729cbb | |
|
|
529886f7fb | |
|
|
7302bf9a66 | |
|
|
e4c5900acd | |
|
|
a5cc905184 | |
|
|
7d10a72490 | |
|
|
dcf72ff8e2 | |
|
|
108a4ed496 | |
|
|
3c54d8aef7 | |
|
|
a1d68fe3bc | |
|
|
8a9d724873 | |
|
|
51560b0bf6 | |
|
|
9faa61dfc6 | |
|
|
d8b27d41c0 | |
|
|
8ec9de00ec | |
|
|
af51097af7 | |
|
|
a55dc80175 | |
|
|
c1111f125c | |
|
|
1fdfba2a1a | |
|
|
10b8fdddb4 | |
|
|
7b4c9c5dcd | |
|
|
fd5918c811 |
|
|
@ -6,6 +6,8 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
value: >
|
value: >
|
||||||
|
|
||||||
|
Learn more in our [Reporting bugs](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) docs section. We fix well-reported bugs the fastest.
|
||||||
|
|
||||||
If you have a general question, please ask it on the [Discourse forum](https://yosyshq.discourse.group/).
|
If you have a general question, please ask it on the [Discourse forum](https://yosyshq.discourse.group/).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ runs:
|
||||||
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
|
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
|
||||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
with:
|
with:
|
||||||
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev
|
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libgtest-dev libgmock-dev
|
||||||
version: ${{ inputs.runs-on }}-buildys
|
version: ${{ inputs.runs-on }}-buildys
|
||||||
|
|
||||||
- name: Linux docs dependencies
|
- name: Linux docs dependencies
|
||||||
|
|
@ -52,15 +52,6 @@ runs:
|
||||||
packages: graphviz xdot
|
packages: graphviz xdot
|
||||||
version: ${{ inputs.runs-on }}-docsys
|
version: ${{ inputs.runs-on }}-docsys
|
||||||
|
|
||||||
# if updating test dependencies, make sure to update
|
|
||||||
# docs/source/yosys_internals/extending_yosys/test_suites.rst to match.
|
|
||||||
- name: Linux test dependencies
|
|
||||||
if: runner.os == 'Linux' && inputs.get-test-deps == 'true'
|
|
||||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
|
||||||
with:
|
|
||||||
packages: libgtest-dev
|
|
||||||
version: ${{ inputs.runs-on }}-testys
|
|
||||||
|
|
||||||
- name: Install macOS Dependencies
|
- name: Install macOS Dependencies
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -23,13 +23,19 @@ jobs:
|
||||||
get-build-deps: true
|
get-build-deps: true
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v4
|
||||||
with:
|
with:
|
||||||
languages: cpp
|
languages: cpp
|
||||||
queries: security-extended,security-and-quality
|
queries: security-extended,security-and-quality
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: make yosys -j6
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j6
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v4
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
name: Test extra build flows
|
name: Test extra build flows
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# always test main
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
# test PRs
|
|
||||||
pull_request:
|
pull_request:
|
||||||
# allow triggering tests, ignores skip check
|
merge_group:
|
||||||
|
#push:
|
||||||
|
# branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre_job:
|
pre_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on documentation changes
|
# don't run on documentation changes
|
||||||
|
|
@ -25,58 +23,67 @@ jobs:
|
||||||
# but never cancel main
|
# but never cancel main
|
||||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
vs-prep:
|
- id: set_output
|
||||||
name: Prepare Visual Studio build
|
run: |
|
||||||
runs-on: ubuntu-latest
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
needs: [pre_job]
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
else
|
||||||
steps:
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
- uses: actions/checkout@v4
|
fi
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
persist-credentials: false
|
|
||||||
- run: sudo apt-get install libfl-dev
|
|
||||||
- name: Build
|
|
||||||
run: make vcxsrc YOSYS_VER=latest
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: vcxsrc
|
|
||||||
path: yosys-win32-vcxsrc-latest.zip
|
|
||||||
|
|
||||||
vs-build:
|
vs-build:
|
||||||
name: Visual Studio build
|
name: Visual Studio build
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
needs: [vs-prep, pre_job]
|
needs: [pre_job]
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
name: vcxsrc
|
submodules: true
|
||||||
path: .
|
persist-credentials: false
|
||||||
- name: unzip
|
|
||||||
run: unzip yosys-win32-vcxsrc-latest.zip
|
- name: Setup MSVC
|
||||||
- name: setup-msbuild
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
- name: MSBuild
|
- name: Install flex/bison
|
||||||
working-directory: yosys-win32-vcxsrc-latest
|
shell: pwsh
|
||||||
run: msbuild YosysVS.sln /p:PlatformToolset=v142 /p:Configuration=Release /p:WindowsTargetPlatformVersion=10.0.26100.0
|
run: |
|
||||||
|
choco install winflexbison3 --no-progress
|
||||||
|
|
||||||
|
# Make tools visible to CMake
|
||||||
|
echo "C:\Program Files (x86)\GnuWin32\bin" | Out-File -Append -FilePath $env:GITHUB_PATH
|
||||||
|
echo "C:\ProgramData\chocolatey\lib\winflexbison3\tools" | Out-File -Append -FilePath $env:GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build
|
||||||
|
-A x64
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
-DYOSYS_WITHOUT_ABC=ON
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: >
|
||||||
|
cmake --build build
|
||||||
|
--config Release
|
||||||
|
--parallel
|
||||||
|
|
||||||
wasi-build:
|
wasi-build:
|
||||||
name: WASI build
|
name: WASI build
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
WASI_SDK=wasi-sdk-27.0-x86_64-linux
|
WASI_VER=33
|
||||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz
|
WASI_SDK=wasi-sdk-${WASI_VER}.0-x86_64-linux
|
||||||
|
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VER}/${WASI_SDK}.tar.gz
|
||||||
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
||||||
|
WASI_SDK_PATH=$(pwd)/${WASI_SDK}
|
||||||
FLEX_VER=2.6.4
|
FLEX_VER=2.6.4
|
||||||
FLEX=flex-${FLEX_VER}
|
FLEX=flex-${FLEX_VER}
|
||||||
FLEX_URL=https://github.com/westes/flex/releases/download/v${FLEX_VER}/${FLEX}.tar.gz
|
FLEX_URL=https://github.com/westes/flex/releases/download/v${FLEX_VER}/${FLEX}.tar.gz
|
||||||
|
|
@ -88,35 +95,21 @@ jobs:
|
||||||
make &&
|
make &&
|
||||||
make install)
|
make install)
|
||||||
|
|
||||||
mkdir -p build
|
export PATH=${WASI_SDK_PATH}/bin:$(pwd)/flex-prefix/bin:${PATH}
|
||||||
cat > build/Makefile.conf <<END
|
cmake -B build -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk-p1.cmake -DCMAKE_BUILD_TYPE=Release .
|
||||||
export PATH := $(pwd)/${WASI_SDK}/bin:$(pwd)/flex-prefix/bin:${PATH}
|
cmake --build build -j$(nproc)
|
||||||
WASI_SYSROOT := $(pwd)/${WASI_SDK}/share/wasi-sysroot
|
|
||||||
|
|
||||||
CONFIG := wasi
|
|
||||||
PREFIX := /
|
|
||||||
|
|
||||||
ENABLE_TCL := 0
|
|
||||||
ENABLE_READLINE := 0
|
|
||||||
ENABLE_PLUGINS := 0
|
|
||||||
ENABLE_ZLIB := 0
|
|
||||||
|
|
||||||
CXXFLAGS += -I$(pwd)/flex-prefix/include
|
|
||||||
END
|
|
||||||
|
|
||||||
make -C build -f ../Makefile CXX=clang -j$(nproc)
|
|
||||||
|
|
||||||
nix-build:
|
nix-build:
|
||||||
name: "Build nix flake"
|
name: "Build nix flake"
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest]
|
os: [ubuntu-latest, macos-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -124,3 +117,21 @@ jobs:
|
||||||
with:
|
with:
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.30.0/install
|
install_url: https://releases.nixos.org/nix/nix-2.30.0/install
|
||||||
- run: nix build .?submodules=1 -L
|
- run: nix build .?submodules=1 -L
|
||||||
|
|
||||||
|
extra-builds-result:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- vs-build
|
||||||
|
- wasi-build
|
||||||
|
- nix-build
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Check results
|
||||||
|
run: |
|
||||||
|
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||||
|
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||||
|
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||||
|
echo "Some jobs failed or were cancelled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: echo "All good"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
name: Build docs artifact with Verific
|
name: Build docs artifact with Verific
|
||||||
|
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
pull_request:
|
||||||
|
merge_group:
|
||||||
|
push:
|
||||||
|
branches: [ main, "docs-preview/**", "docs-preview*" ]
|
||||||
|
tags: [ "*" ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_docs_rebuild:
|
check_docs_rebuild:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
skip_check: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
docs_export: ${{ steps.docs_var.outputs.docs_export }}
|
docs_export: ${{ steps.docs_var.outputs.docs_export }}
|
||||||
env:
|
env:
|
||||||
docs_export: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }}
|
docs_export: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
|
@ -17,16 +23,26 @@ jobs:
|
||||||
paths_ignore: '["**/README.md"]'
|
paths_ignore: '["**/README.md"]'
|
||||||
# don't cancel in case we're updating docs
|
# don't cancel in case we're updating docs
|
||||||
cancel_others: 'false'
|
cancel_others: 'false'
|
||||||
# only run on push *or* pull_request, not both
|
# push filtering means we only want to skip duplicates for PRs
|
||||||
concurrent_skipping: ${{ env.docs_export && 'never' || 'same_content_newer'}}
|
do_not_skip: '["workflow_dispatch", "merge_group", "push"]'
|
||||||
|
concurrent_skipping: 'same_content_newer'
|
||||||
|
|
||||||
- id: docs_var
|
- id: docs_var
|
||||||
run: echo "docs_export=${docs_export}" >> $GITHUB_OUTPUT
|
run: echo "docs_export=${docs_export}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
prepare-docs:
|
prepare-docs:
|
||||||
# docs builds are needed for anything on main, any tagged versions, and any tag
|
# docs builds are needed for anything on main, any tagged versions, and any tag
|
||||||
# or branch starting with docs-preview
|
# or branch starting with docs-preview
|
||||||
needs: check_docs_rebuild
|
needs: check_docs_rebuild
|
||||||
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||||
runs-on: [self-hosted, linux, x64, fast]
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
|
|
@ -41,19 +57,19 @@ jobs:
|
||||||
|
|
||||||
- name: Build Yosys
|
- name: Build Yosys
|
||||||
run: |
|
run: |
|
||||||
make config-clang
|
rm -rf build Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
|
||||||
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
|
cmake -C Configuration.cmake -B build .
|
||||||
make -j$procs
|
cmake --build build -j$procs
|
||||||
|
|
||||||
- name: Prepare docs
|
- name: Prepare docs
|
||||||
shell: bash
|
shell: bash
|
||||||
run:
|
run:
|
||||||
make docs/prep -j$procs TARGETS= EXTRA_TARGETS=
|
cmake --build build --target docs-prepare -j$procs
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
@ -67,15 +83,15 @@ jobs:
|
||||||
- name: Install doc prereqs
|
- name: Install doc prereqs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make docs/reqs
|
make -C docs reqs
|
||||||
|
|
||||||
- name: Test build docs
|
- name: Test build docs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make -C docs html -j$procs TARGETS= EXTRA_TARGETS=
|
cmake --build build --target docs-html -j$procs
|
||||||
|
|
||||||
- name: Trigger RTDs build
|
- name: Trigger RTDs build
|
||||||
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }}
|
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' && github.repository == 'YosysHQ/yosys' }}
|
||||||
uses: dfm/rtds-action@v1.1.0
|
uses: dfm/rtds-action@v1.1.0
|
||||||
with:
|
with:
|
||||||
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,18 @@
|
||||||
name: Create source archive with vendored dependencies
|
name: Create source archive with vendored dependencies
|
||||||
|
|
||||||
on: [push, workflow_dispatch]
|
on:
|
||||||
|
pull_request:
|
||||||
|
merge_group:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
vendor-sources:
|
vendor-sources:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository with submodules
|
- name: Checkout repository with submodules
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -27,7 +32,7 @@ jobs:
|
||||||
gzip yosys-src-vendored.tar
|
gzip yosys-src-vendored.tar
|
||||||
|
|
||||||
- name: Store tarball artifact
|
- name: Store tarball artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: vendored-sources
|
name: vendored-sources
|
||||||
path: yosys-src-vendored.tar.gz
|
path: yosys-src-vendored.tar.gz
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
name: Build and run tests
|
name: Build and run tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# always test main
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
# test PRs
|
|
||||||
pull_request:
|
pull_request:
|
||||||
# allow triggering tests, ignores skip check
|
merge_group:
|
||||||
|
#push:
|
||||||
|
# branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre_job:
|
pre_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on documentation changes
|
# don't run on documentation changes
|
||||||
|
|
@ -25,12 +23,21 @@ jobs:
|
||||||
# but never cancel main
|
# but never cancel main
|
||||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
pre_docs_job:
|
pre_docs_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on readme changes
|
# don't run on readme changes
|
||||||
|
|
@ -39,6 +46,14 @@ jobs:
|
||||||
# but never cancel main
|
# but never cancel main
|
||||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
build-yosys:
|
build-yosys:
|
||||||
name: Reusable build
|
name: Reusable build
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
@ -53,7 +68,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -67,14 +82,14 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
rm -rf build
|
||||||
cd build
|
cmake -B build . -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release
|
||||||
make -f ../Makefile config-$CC
|
cmake --build build -j$procs
|
||||||
make -f ../Makefile -j$procs
|
ctest --test-dir build/tests/unit
|
||||||
|
|
||||||
- name: Log yosys-config output
|
- name: Log yosys-config output
|
||||||
run: |
|
run: |
|
||||||
./yosys-config || true
|
./build/yosys-config || true
|
||||||
|
|
||||||
- name: Compress build
|
- name: Compress build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -83,7 +98,7 @@ jobs:
|
||||||
tar -cvf ../build.tar share/ yosys yosys-*
|
tar -cvf ../build.tar share/ yosys yosys-*
|
||||||
|
|
||||||
- name: Store build artifact
|
- name: Store build artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}
|
||||||
path: build.tar
|
path: build.tar
|
||||||
|
|
@ -102,7 +117,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|
@ -114,23 +129,24 @@ jobs:
|
||||||
get-iverilog: true
|
get-iverilog: true
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}
|
||||||
|
|
||||||
- name: Uncompress build
|
- name: Uncompress build
|
||||||
shell: bash
|
shell: bash
|
||||||
run:
|
run: |
|
||||||
tar -xvf build.tar
|
mkdir -p build
|
||||||
|
tar -xvf build.tar -C build
|
||||||
|
|
||||||
- name: Log yosys-config output
|
- name: Log yosys-config output
|
||||||
run: |
|
run: |
|
||||||
./yosys-config || true
|
./build/yosys-config || true
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make -j$procs test TARGETS= EXTRA_TARGETS= CONFIG=$CC
|
make -C tests -j$procs vanilla-test
|
||||||
|
|
||||||
- name: Report errors
|
- name: Report errors
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|
@ -150,7 +166,7 @@ jobs:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|
@ -160,7 +176,7 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}
|
||||||
|
|
||||||
|
|
@ -182,15 +198,13 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: [build-yosys, pre_docs_job]
|
needs: [build-yosys, pre_docs_job]
|
||||||
if: needs.pre_docs_job.outputs.should_skip != 'true'
|
if: needs.pre_docs_job.outputs.should_skip != 'true'
|
||||||
env:
|
|
||||||
CC: clang
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|
@ -202,18 +216,19 @@ jobs:
|
||||||
get-docs-deps: true
|
get-docs-deps: true
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}
|
||||||
|
|
||||||
- name: Uncompress build
|
- name: Uncompress build
|
||||||
shell: bash
|
shell: bash
|
||||||
run:
|
run: |
|
||||||
tar -xvf build.tar
|
mkdir -p build
|
||||||
|
tar -xvf build.tar -C build
|
||||||
|
|
||||||
- name: Log yosys-config output
|
- name: Log yosys-config output
|
||||||
run: |
|
run: |
|
||||||
./yosys-config || true
|
./build/yosys-config || true
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -224,7 +239,7 @@ jobs:
|
||||||
name: Try build docs
|
name: Try build docs
|
||||||
runs-on: [self-hosted, linux, x64, fast]
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
needs: [pre_docs_job]
|
needs: [pre_docs_job]
|
||||||
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
docs-target: [html, latexpdf]
|
docs-target: [html, latexpdf]
|
||||||
|
|
@ -242,20 +257,23 @@ jobs:
|
||||||
|
|
||||||
- name: Build Yosys
|
- name: Build Yosys
|
||||||
run: |
|
run: |
|
||||||
make config-clang
|
rm -rf build Configuration.cmake
|
||||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
make -j$procs
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
- name: Install doc prereqs
|
- name: Install doc prereqs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make docs/reqs
|
make -C docs reqs
|
||||||
|
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make docs DOC_TARGET=${{ matrix.docs-target }} -j$procs
|
cmake --build build --target docs-${{ matrix.docs-target }} -j$procs
|
||||||
|
|
||||||
- name: Store docs build artifact
|
- name: Store docs build artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
@ -263,3 +281,22 @@ jobs:
|
||||||
name: docs-build-${{ matrix.docs-target }}
|
name: docs-build-${{ matrix.docs-target }}
|
||||||
path: docs/build/
|
path: docs/build/
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
|
test-build-result:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- test-yosys
|
||||||
|
- test-cells
|
||||||
|
- test-docs
|
||||||
|
- test-docs-build
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Check results
|
||||||
|
run: |
|
||||||
|
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||||
|
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||||
|
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||||
|
echo "Some jobs failed or were cancelled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: echo "All good"
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
name: Compiler testing
|
name: Compiler testing
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# always test main
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
# test PRs
|
|
||||||
pull_request:
|
pull_request:
|
||||||
# allow triggering tests, ignores skip check
|
merge_group:
|
||||||
|
#push:
|
||||||
|
# branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre_job:
|
pre_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on documentation changes
|
# don't run on documentation changes
|
||||||
|
|
@ -25,35 +23,42 @@ jobs:
|
||||||
# but never cancel main
|
# but never cancel main
|
||||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
test-compile:
|
test-compile:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||||
env:
|
env:
|
||||||
CXXFLAGS: ${{ startsWith(matrix.compiler, 'gcc') && '-Wp,-D_GLIBCXX_ASSERTIONS' || ''}}
|
CXXFLAGS: ${{ startsWith(matrix.compiler, 'gcc') && '-Wp,-D_GLIBCXX_ASSERTIONS' || ''}}
|
||||||
CC_SHORT: ${{ startsWith(matrix.compiler, 'gcc') && 'gcc' || 'clang' }}
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
compiler:
|
compiler:
|
||||||
# oldest supported
|
# oldest supported
|
||||||
- 'clang-10'
|
- 'clang-14'
|
||||||
- 'gcc-10'
|
- 'gcc-11'
|
||||||
# newest, make sure to update maximum standard step to match
|
# newest, make sure to update maximum standard step to match
|
||||||
- 'clang-19'
|
- 'clang-22'
|
||||||
- 'gcc-14'
|
- 'gcc-15'
|
||||||
include:
|
include:
|
||||||
# macOS x86
|
# macOS x86
|
||||||
- os: macos-15-intel
|
- os: macos-15-intel
|
||||||
compiler: 'clang-19'
|
compiler: 'clang-22'
|
||||||
# macOS arm
|
# macOS arm
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
compiler: 'clang-19'
|
compiler: 'clang-22'
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -68,6 +73,7 @@ jobs:
|
||||||
uses: aminya/setup-cpp@v1
|
uses: aminya/setup-cpp@v1
|
||||||
with:
|
with:
|
||||||
compiler: ${{ matrix.compiler }}
|
compiler: ${{ matrix.compiler }}
|
||||||
|
gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14') && '12' || '' }}
|
||||||
|
|
||||||
- name: Tool versions
|
- name: Tool versions
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -75,17 +81,40 @@ jobs:
|
||||||
$CC --version
|
$CC --version
|
||||||
$CXX --version
|
$CXX --version
|
||||||
|
|
||||||
|
- name: Fix clang-14 toolchain
|
||||||
|
if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14'
|
||||||
|
run: |
|
||||||
|
echo 'CXXFLAGS=--gcc-toolchain=/usr -isystem /usr/include/c++/12 -isystem /usr/include/x86_64-linux-gnu/c++/12' >> $GITHUB_ENV
|
||||||
|
|
||||||
# minimum standard
|
# minimum standard
|
||||||
- name: Build C++17
|
- name: Build C++20
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make config-$CC_SHORT
|
rm -rf build
|
||||||
make -j$procs CXXSTD=c++17 compile-only
|
cmake -B build -DCMAKE_CXX_STANDARD=20 . --fresh
|
||||||
|
cmake --build build --target yosys -j$procs
|
||||||
|
|
||||||
# maximum standard, only on newest compilers
|
# maximum standard, only on newest compilers
|
||||||
- name: Build C++20
|
- name: Build C++26
|
||||||
if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }}
|
if: ${{ matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-15' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make config-$CC_SHORT
|
rm -rf build
|
||||||
make -j$procs CXXSTD=c++20 compile-only
|
cmake -B build -DCMAKE_CXX_STANDARD=26 . --fresh
|
||||||
|
cmake --build build --target yosys -j$procs
|
||||||
|
|
||||||
|
test-compile-result:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- test-compile
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Check results
|
||||||
|
run: |
|
||||||
|
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||||
|
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||||
|
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||||
|
echo "Some jobs failed or were cancelled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: echo "All good"
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,44 @@
|
||||||
name: Check clang sanitizers
|
name: Check clang sanitizers
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# always test main
|
pull_request:
|
||||||
push:
|
merge_group:
|
||||||
branches:
|
#push:
|
||||||
- main
|
# branches: [ main ]
|
||||||
# ignore PRs due to time needed
|
|
||||||
# allow triggering tests, ignores skip check
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre_job:
|
pre_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on documentation changes
|
# don't run on documentation changes
|
||||||
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
|
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
|
||||||
|
# cancel previous builds if a new commit is pushed
|
||||||
|
# but never cancel main
|
||||||
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
run_san:
|
run_san:
|
||||||
name: Build and run tests
|
name: Build and run tests
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||||
env:
|
env:
|
||||||
CC: clang
|
CC: clang
|
||||||
ASAN_OPTIONS: halt_on_error=1
|
ASAN_OPTIONS: halt_on_error=1 detect_container_overflow=0
|
||||||
UBSAN_OPTIONS: halt_on_error=1
|
UBSAN_OPTIONS: halt_on_error=1
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -37,7 +47,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -53,18 +63,20 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make config-$CC
|
rm -rf build
|
||||||
echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf
|
cmake -B build . \
|
||||||
make -j$procs
|
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||||
|
-DCMAKE_BUILD_TYPE=Sanitize -DSANITIZE=${{ matrix.sanitizer }}
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
- name: Log yosys-config output
|
- name: Log yosys-config output
|
||||||
run: |
|
run: |
|
||||||
./yosys-config || true
|
./build/yosys-config || true
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make -j$procs test TARGETS= EXTRA_TARGETS=
|
make -C tests -j$procs vanilla-test
|
||||||
|
|
||||||
- name: Report errors
|
- name: Report errors
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|
@ -72,7 +84,18 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
find tests/**/*.err -print -exec cat {} \;
|
find tests/**/*.err -print -exec cat {} \;
|
||||||
|
|
||||||
- name: Run unit tests
|
test-sanitizers-result:
|
||||||
shell: bash
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- run_san
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Check results
|
||||||
run: |
|
run: |
|
||||||
make -j$procs unit-test ENABLE_LIBYOSYS=1
|
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||||
|
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||||
|
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||||
|
echo "Some jobs failed or were cancelled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: echo "All good"
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
name: Build various Verific configurations
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-verific-cfg:
|
||||||
|
if: github.repository_owner == 'YosysHQ'
|
||||||
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
|
steps:
|
||||||
|
- name: Checkout Yosys
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
submodules: true
|
||||||
|
- name: Runtime environment
|
||||||
|
run: |
|
||||||
|
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: verific [SV]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [VHDL]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [SV + VHDL]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl;systemverilog" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [SV + HIER]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [VHDL + HIER]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [SV + VHDL + HIER]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;vhdl;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: verific [SV + VHDL + HIER + EDIF + LIBERTY]
|
||||||
|
run: |
|
||||||
|
rm -rf build Configuration.cmake
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;vhdl;hier_tree;edif;liberty" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build .
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
name: Build and run tests with Verific (Linux)
|
name: Build and run tests with Verific (Linux)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# always test main
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
# test PRs
|
|
||||||
pull_request:
|
pull_request:
|
||||||
# allow triggering tests, ignores skip check
|
merge_group:
|
||||||
|
#push:
|
||||||
|
# branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-job:
|
pre_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||||
steps:
|
steps:
|
||||||
- id: skip_check
|
- id: skip_check
|
||||||
|
if: ${{ github.event_name != 'merge_group' }}
|
||||||
uses: fkirc/skip-duplicate-actions@v5
|
uses: fkirc/skip-duplicate-actions@v5
|
||||||
with:
|
with:
|
||||||
# don't run on documentation changes
|
# don't run on documentation changes
|
||||||
|
|
@ -25,9 +23,17 @@ jobs:
|
||||||
# but never cancel main
|
# but never cancel main
|
||||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- id: set_output
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||||
|
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
test-verific:
|
test-verific:
|
||||||
needs: pre-job
|
needs: pre_job
|
||||||
if: ${{ needs.pre-job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||||
runs-on: [self-hosted, linux, x64, fast]
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
|
|
@ -38,21 +44,30 @@ jobs:
|
||||||
- name: Runtime environment
|
- name: Runtime environment
|
||||||
run: |
|
run: |
|
||||||
echo "procs=$(nproc)" >> $GITHUB_ENV
|
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||||
|
mkdir -p "${GITHUB_WORKSPACE}/coverage"
|
||||||
|
echo "LLVM_PROFILE_FILE=${GITHUB_WORKSPACE}/coverage/coverage_%p.profraw" >> $GITHUB_ENV
|
||||||
|
echo "LLVM_PROFILE_FILE_BUFFER_SIZE=0" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Skip generating files
|
||||||
|
if: ${{ github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch' }}
|
||||||
|
run: |
|
||||||
|
echo "LLVM_PROFILE_FILE=/dev/null" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build Yosys
|
- name: Build Yosys
|
||||||
run: |
|
run: |
|
||||||
make config-clang
|
rm -rf build Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
echo 'set(YOSYS_ENABLE_COVERAGE ON CACHE BOOL "")' >> Configuration.cmake
|
||||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf
|
|
||||||
make -j$procs ENABLE_LTO=1
|
cmake -C Configuration.cmake -B build . -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.local -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
- name: Install Yosys
|
- name: Install Yosys
|
||||||
run: |
|
run: |
|
||||||
make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX=
|
cmake --build build --target install
|
||||||
|
|
||||||
- name: Checkout SBY
|
- name: Checkout SBY
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -67,19 +82,96 @@ jobs:
|
||||||
|
|
||||||
- name: Run Yosys tests
|
- name: Run Yosys tests
|
||||||
run: |
|
run: |
|
||||||
make -j$procs test
|
make -C tests -j$procs vanilla-test
|
||||||
|
|
||||||
- name: Run Verific specific Yosys tests
|
- name: Run Verific specific Yosys tests
|
||||||
run: |
|
run: |
|
||||||
make -C tests/sva
|
make -C tests/sva
|
||||||
cd tests/svtypes && bash run-test.sh
|
make -C tests/svtypes
|
||||||
|
|
||||||
- name: Run SBY tests
|
- name: Run SBY tests
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||||
run: |
|
run: |
|
||||||
make -C sby run_ci
|
make -C sby run_ci
|
||||||
|
|
||||||
- name: Run unit tests
|
- name: Run coverage
|
||||||
shell: bash
|
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||||
run: |
|
run: |
|
||||||
make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1
|
make -C tests coverage
|
||||||
|
make -C tests clean_coverage
|
||||||
|
|
||||||
|
- name: Push coverage
|
||||||
|
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||||
|
run: |
|
||||||
|
git clone https://x-access-token:${{ secrets.REPORTS_TOKEN }}@github.com/YosysHQ/reports.git out
|
||||||
|
rm -rf out/coverage/main
|
||||||
|
mkdir -p out/coverage/main
|
||||||
|
cp -r coverage_html/* out/coverage/main/
|
||||||
|
cd out
|
||||||
|
# find . -name "*.html" -type f -print0 | xargs -0 sed -i -z 's#\(<td class="headerItem">Date:</td>[[:space:]]*<td class="headerValue">\)[^<]*\(</td>\)#\1\2#g'
|
||||||
|
git config user.name "yosyshq-ci"
|
||||||
|
git config user.email "105224853+yosyshq-ci@users.noreply.github.com"
|
||||||
|
git add .
|
||||||
|
if ! git diff --cached --quiet; then
|
||||||
|
git commit -m "Update coverage"
|
||||||
|
git push
|
||||||
|
else
|
||||||
|
echo "No changes to commit"
|
||||||
|
fi
|
||||||
|
|
||||||
|
test-pyosys:
|
||||||
|
needs: pre_job
|
||||||
|
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||||
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
|
steps:
|
||||||
|
- name: Checkout Yosys
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
submodules: true
|
||||||
|
- name: Install UV
|
||||||
|
run: |
|
||||||
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
- name: Runtime environment
|
||||||
|
run: |
|
||||||
|
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||||
|
echo "${{ github.workspace }}/.local/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Build pyosys
|
||||||
|
run: |
|
||||||
|
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_WITH_PYTHON ON CACHE BOOL "")' >> Configuration.cmake
|
||||||
|
echo 'set(YOSYS_INSTALL_PYTHON ON CACHE BOOL "")' >> Configuration.cmake
|
||||||
|
cmake -C Configuration.cmake -B build . \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.local \
|
||||||
|
-DYOSYS_INSTALL_PYTHON_SITEDIR=$GITHUB_WORKSPACE/.local/usr/lib/python3/site-packages
|
||||||
|
cmake --build build -j$procs
|
||||||
|
|
||||||
|
- name: Install pyosys
|
||||||
|
run: |
|
||||||
|
cmake --build build --target install
|
||||||
|
|
||||||
|
- name: Run pyosys tests
|
||||||
|
run: |
|
||||||
|
export PYTHONPATH=${GITHUB_WORKSPACE}/.local/usr/lib/python3/site-packages:$PYTHONPATH
|
||||||
|
python3 tests/pyosys/run_tests.py
|
||||||
|
|
||||||
|
test-verific-result:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- test-verific
|
||||||
|
- test-pyosys
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Check results
|
||||||
|
run: |
|
||||||
|
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||||
|
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||||
|
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||||
|
echo "Some jobs failed or were cancelled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: echo "All good"
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
name: update-flake-lock
|
|
||||||
on:
|
|
||||||
workflow_dispatch: # allows manual triggering
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lockfile:
|
|
||||||
if: github.repository == 'YosysHQ/Yosys'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Install Nix
|
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
|
||||||
- name: Update flake.lock
|
|
||||||
uses: DeterminateSystems/update-flake-lock@main
|
|
||||||
with:
|
|
||||||
token: ${{CI_CREATE_PR_TOKEN}}
|
|
||||||
pr-title: "Update flake.lock" # Title of PR to be created
|
|
||||||
pr-labels: | # Labels to be set on the PR
|
|
||||||
dependencies
|
|
||||||
automated
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
name: Bump version
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump-version:
|
|
||||||
if: github.repository == 'YosysHQ/Yosys'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: true
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Take last commit
|
|
||||||
id: log
|
|
||||||
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
|
|
||||||
- name: Bump version
|
|
||||||
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
|
|
||||||
run: |
|
|
||||||
make bumpversion
|
|
||||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git add Makefile
|
|
||||||
git commit -m "Bump version"
|
|
||||||
- name: Push changes # push the output folder to your repo
|
|
||||||
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
|
|
||||||
uses: ad-m/github-push-action@master
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
@ -36,20 +36,18 @@ jobs:
|
||||||
runner: "macos-15",
|
runner: "macos-15",
|
||||||
archs: "arm64",
|
archs: "arm64",
|
||||||
},
|
},
|
||||||
## Windows is disabled because of an issue with compiling FFI as
|
## Windows still needs to be tested.
|
||||||
## under MinGW in the GitHub Actions environment (SHELL variable has
|
|
||||||
## whitespace.)
|
|
||||||
# {
|
# {
|
||||||
# name: "Windows Server 2019",
|
# name: "Windows Server 2025",
|
||||||
# family: "windows",
|
# family: "windows",
|
||||||
# runner: "windows-2019",
|
# runner: "windows-2025",
|
||||||
# archs: "AMD64",
|
# archs: "AMD64",
|
||||||
# },
|
# },
|
||||||
]
|
]
|
||||||
name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }}
|
name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }}
|
||||||
runs-on: ${{ matrix.os.runner }}
|
runs-on: ${{ matrix.os.runner }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
@ -77,17 +75,14 @@ jobs:
|
||||||
name: "[Windows] Flex/Bison"
|
name: "[Windows] Flex/Bison"
|
||||||
run: |
|
run: |
|
||||||
choco install winflexbison3
|
choco install winflexbison3
|
||||||
- if: ${{ matrix.os.family == 'macos' && matrix.os.archs == 'arm64' }}
|
|
||||||
name: "[macOS/arm64] Install Python 3.8 (see: https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64)"
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: 3.8
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.21.1
|
uses: pypa/cibuildwheel@v3.4.1
|
||||||
env:
|
env:
|
||||||
# * APIs not supported by PyPy
|
# * APIs not supported by PyPy
|
||||||
# * Musllinux disabled because it increases build time from 48m to ~3h
|
# * Musllinux disabled because it increases build time from 48m to ~3h
|
||||||
CIBW_SKIP: >
|
CIBW_SKIP: >
|
||||||
|
cp38*
|
||||||
|
cp39*
|
||||||
pp*
|
pp*
|
||||||
*musllinux*
|
*musllinux*
|
||||||
CIBW_ARCHS: ${{ matrix.os.archs }}
|
CIBW_ARCHS: ${{ matrix.os.archs }}
|
||||||
|
|
@ -104,17 +99,16 @@ jobs:
|
||||||
OPTFLAGS=-O3
|
OPTFLAGS=-O3
|
||||||
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
|
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
|
||||||
MACOSX_DEPLOYMENT_TARGET=11
|
MACOSX_DEPLOYMENT_TARGET=11
|
||||||
makeFlags='CONFIG=clang'
|
|
||||||
PATH="$PWD/bison/src:$PATH"
|
PATH="$PWD/bison/src:$PATH"
|
||||||
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
|
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
|
||||||
CIBW_TEST_COMMAND: python3 {project}/tests/pyosys/run_tests.py
|
CIBW_TEST_COMMAND: python3 {project}/tests/pyosys/run_tests.py
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: python-wheels-${{ matrix.os.runner }}
|
name: python-wheels-${{ matrix.os.runner }}
|
||||||
path: ./wheelhouse/*.whl
|
path: ./wheelhouse/*.whl
|
||||||
upload_wheels:
|
upload_wheels:
|
||||||
name: Upload Wheels
|
name: Upload Wheels
|
||||||
if: (github.repository == 'YosysHQ/Yosys') && (github.event_name == 'workflow_dispatch')
|
if: (github.repository == 'YosysHQ/yosys') && (github.event_name == 'workflow_dispatch')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Specifying a GitHub environment is optional, but strongly encouraged
|
# Specifying a GitHub environment is optional, but strongly encouraged
|
||||||
environment: pypi
|
environment: pypi
|
||||||
|
|
@ -123,7 +117,7 @@ jobs:
|
||||||
id-token: write
|
id-token: write
|
||||||
needs: build_wheels
|
needs: build_wheels
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
path: "."
|
path: "."
|
||||||
pattern: python-wheels-*
|
pattern: python-wheels-*
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Copyright (C) 2024 Efabless Corporation
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
"""
|
|
||||||
This runs the cibuildwheel step from the wheels workflow locally.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import yaml
|
|
||||||
import platform
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
__yosys_root__ = Path(__file__).absolute().parents[3]
|
|
||||||
|
|
||||||
for source in ["ffi", "bison"]:
|
|
||||||
if not (__yosys_root__ / source).is_dir():
|
|
||||||
print(
|
|
||||||
"You need to download ffi and bison in a similar manner to wheels.yml first."
|
|
||||||
)
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
with open(__yosys_root__ / ".github" / "workflows" / "wheels.yml") as f:
|
|
||||||
workflow = yaml.safe_load(f)
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
|
||||||
|
|
||||||
steps = workflow["jobs"]["build_wheels"]["steps"]
|
|
||||||
cibw_step = None
|
|
||||||
for step in steps:
|
|
||||||
if (step.get("uses") or "").startswith("pypa/cibuildwheel"):
|
|
||||||
cibw_step = step
|
|
||||||
break
|
|
||||||
|
|
||||||
for key, value in cibw_step["env"].items():
|
|
||||||
if key.endswith("WIN") or key.endswith("MAC"):
|
|
||||||
continue
|
|
||||||
env[key] = value
|
|
||||||
|
|
||||||
env["CIBW_ARCHS"] = os.getenv("CIBW_ARCHS", platform.machine())
|
|
||||||
subprocess.check_call(["cibuildwheel"], env=env)
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
set -e -x
|
set -e -x
|
||||||
|
|
||||||
# Build-time dependencies
|
# Build-time dependencies
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
# Don't use Python objects from previous compiles
|
|
||||||
make clean-py
|
|
||||||
|
|
||||||
# DEBUG: show python3 and python3-config outputs
|
# DEBUG: show python3 and python3-config outputs
|
||||||
if [ "$(uname)" != "Linux" ]; then
|
if [ "$(uname)" != "Linux" ]; then
|
||||||
# https://github.com/pypa/cibuildwheel/issues/2021
|
# https://github.com/pypa/cibuildwheel/issues/2021
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,9 @@
|
||||||
/tests/unit/objtest/
|
/tests/unit/objtest/
|
||||||
/tests/ystests
|
/tests/ystests
|
||||||
/build
|
/build
|
||||||
|
/build-*
|
||||||
/result
|
/result
|
||||||
|
/result-*
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
# pyosys
|
# pyosys
|
||||||
|
|
@ -65,10 +67,10 @@
|
||||||
/viz.js
|
/viz.js
|
||||||
|
|
||||||
# other
|
# other
|
||||||
/coverage.info
|
/yosys.profdata
|
||||||
|
/coverage
|
||||||
/coverage_html
|
/coverage_html
|
||||||
|
|
||||||
|
|
||||||
# these really belong in global gitignore since they're not specific to this project but rather to user tool choice
|
# these really belong in global gitignore since they're not specific to this project but rather to user tool choice
|
||||||
# but too many people don't have a global gitignore configured:
|
# but too many people don't have a global gitignore configured:
|
||||||
# https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
|
# https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
|
||||||
|
|
@ -86,3 +88,5 @@ __pycache__
|
||||||
/qtcreator.creator
|
/qtcreator.creator
|
||||||
/qtcreator.creator.user
|
/qtcreator.creator.user
|
||||||
/compile_commands.json
|
/compile_commands.json
|
||||||
|
/.direnv
|
||||||
|
/.envrc
|
||||||
|
|
|
||||||
3
Brewfile
3
Brewfile
|
|
@ -9,6 +9,7 @@ brew "python3"
|
||||||
brew "uv"
|
brew "uv"
|
||||||
brew "xdot"
|
brew "xdot"
|
||||||
brew "bash"
|
brew "bash"
|
||||||
brew "llvm@20"
|
brew "llvm"
|
||||||
brew "lld"
|
brew "lld"
|
||||||
brew "googletest"
|
brew "googletest"
|
||||||
|
brew "tcl-tk"
|
||||||
|
|
|
||||||
103
CHANGELOG
103
CHANGELOG
|
|
@ -2,9 +2,110 @@
|
||||||
List of major changes and improvements between releases
|
List of major changes and improvements between releases
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
Yosys 0.59 .. Yosys 0.60-dev
|
Yosys 0.66 .. Yosys 0.67-dev
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
Yosys 0.65 .. Yosys 0.66
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- C++ compiler with C++20 support is required.
|
||||||
|
- Please be aware that next release will also
|
||||||
|
migrate to CMake build system.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "lattice_dsp_nexus" pass for Lattice Nexus
|
||||||
|
DSP inference.
|
||||||
|
- Added "-scopename" option to "synth_gatemate" pass
|
||||||
|
that is propagated to "flatten".
|
||||||
|
|
||||||
|
Yosys 0.64 .. Yosys 0.65
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "arith_tree" pass to convert add/sub/macc chains
|
||||||
|
to carry-save adder trees.
|
||||||
|
- Removed "-force" option from "share" pass.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- read_verilog: support positional assignment patterns
|
||||||
|
for unpacked arrays.
|
||||||
|
|
||||||
|
Yosys 0.63 .. Yosys 0.64
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "synth_analogdevices" pass to support synthesis
|
||||||
|
for Analog Devices FPGAs.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- Removed rarely-used options from ABC/ABC9.
|
||||||
|
- Removed "-S" option from "abc" pass.
|
||||||
|
- Removed "-fast" option from "abc9" and "abc9_exe".
|
||||||
|
- Calls to "abc -g AND -fast" to map logic to
|
||||||
|
AND-Inverter Graph form should be replaced with
|
||||||
|
"aigmap".
|
||||||
|
- The above change was made to SBY, so we recommend
|
||||||
|
updating it.
|
||||||
|
- Added hardware latch support for Gowin FPGAs.
|
||||||
|
|
||||||
|
Yosys 0.62 .. Yosys 0.63
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- Added DSP inference for Gowin GW1N and GW2A.
|
||||||
|
- Added support for subtract in preadder for Xilinx arch.
|
||||||
|
- Added infrastructure to run a sat solver as a command.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "-ignore-unknown-cells" option to "equiv_induct"
|
||||||
|
and "equiv_simple" pass.
|
||||||
|
- Added "-force-params" option to "memory_libmap" pass.
|
||||||
|
- Added "-select-solver" option to "sat" pass.
|
||||||
|
- Added "-default_params" option to "write_verilog" pass.
|
||||||
|
- Added "-nodsp" option to "synth_gowin" pass.
|
||||||
|
|
||||||
|
Yosys 0.61 .. Yosys 0.62
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- verific: Added "-sv2017" flag option to support System
|
||||||
|
Verilog 2017.
|
||||||
|
- verific: Added VHDL related flags to "-f" and "-F" and
|
||||||
|
support reading VHDL file from file lists.
|
||||||
|
- Updated cell libs with proper module declaration where
|
||||||
|
non standard (...) style was used.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "-word" option to "lut2mux" pass to enable emitting
|
||||||
|
word level cells.
|
||||||
|
- Added experimental "opt_balance_tree" pass to convert
|
||||||
|
cascaded cells into tree of cells to improve timing.
|
||||||
|
- Added "-gatesi" option to "write_blif" pass to init gates
|
||||||
|
under gates_mode in BLIF format.
|
||||||
|
- Added "-on" and "-off" options to "debug" pass for
|
||||||
|
persistent debug logging.
|
||||||
|
- Added "linux_perf" pass to control performance recording.
|
||||||
|
|
||||||
|
Yosys 0.60 .. Yosys 0.61
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- Removed "cover" pass for coverage tracking.
|
||||||
|
- Avoid merging formal properties with "opt_merge" pass.
|
||||||
|
- Parallelize "opt_merge" pass.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "design_equal" pass to support fuzz-test comparison.
|
||||||
|
- Added "lut2bmux" pass to convert $lut to $bmux.
|
||||||
|
- Added "-legalize" option to "read_rtlil" pass to prevent
|
||||||
|
semantic errors.
|
||||||
|
|
||||||
|
Yosys 0.59 .. Yosys 0.60
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- read_verilog: suport unsized parameters.
|
||||||
|
- Added static library compile option.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "sdc" pass for reading SDC files.
|
||||||
|
- Added experimental "sdc_expand" and "opensta" for OpenSTA integration.
|
||||||
|
- Added "icell_liberty" pass for used internal cells.
|
||||||
|
|
||||||
Yosys 0.58 .. Yosys 0.59
|
Yosys 0.58 .. Yosys 0.59
|
||||||
--------------------------
|
--------------------------
|
||||||
* Various
|
* Various
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,572 @@
|
||||||
|
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
|
set(rm "rm -rf")
|
||||||
|
if (WIN32)
|
||||||
|
set(rm "del /s /q")
|
||||||
|
endif()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"In-tree builds are not supported. Instead, run:\n"
|
||||||
|
"${rm} CMakeCache.txt CMakeFiles ; cmake -B build <options>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.27)
|
||||||
|
project(yosys LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
include(FeatureSummary)
|
||||||
|
include(CheckPIESupported)
|
||||||
|
|
||||||
|
include(Condition)
|
||||||
|
include(CheckLibcFeatures)
|
||||||
|
include(PkgConfig)
|
||||||
|
include(PmgenCommand)
|
||||||
|
include(YosysVersion)
|
||||||
|
include(YosysInstallDirs)
|
||||||
|
include(YosysConfigScript)
|
||||||
|
include(YosysComponent)
|
||||||
|
include(YosysLinkTarget)
|
||||||
|
include(YosysAbc)
|
||||||
|
include(YosysAbcSubmodule)
|
||||||
|
include(YosysVerific)
|
||||||
|
|
||||||
|
# Build options.
|
||||||
|
set(YOSYS_COMPILER_LAUNCHER "" CACHE STRING "Compiler launcher (ccache, sccache)")
|
||||||
|
option(YOSYS_ENABLE_COVERAGE "Enable code coverage" OFF)
|
||||||
|
option(YOSYS_ENABLE_PROFILING "Enable instruction profiling" OFF)
|
||||||
|
|
||||||
|
set(YOSYS_PROGRAM_PREFIX "" CACHE STRING "Name prefix for programs, libraries, and data")
|
||||||
|
set(YOSYS_COMPONENTS "everything" CACHE STRING "List of components to build (use pass names)")
|
||||||
|
option(BUILD_SHARED_LIBS "Build libyosys as a shared library" ON)
|
||||||
|
|
||||||
|
option(YOSYS_DISABLE_THREADS "Disable threading" OFF)
|
||||||
|
set(YOSYS_ABC_EXECUTABLE "" CACHE FILEPATH
|
||||||
|
"Path to the ABC executable (empty for vendored, 'INTEGRATED-NOTFOUND' for in-process)")
|
||||||
|
option(YOSYS_WITHOUT_ABC "Disable ABC support (not recommended)" OFF)
|
||||||
|
option(YOSYS_WITHOUT_ZLIB "Disable zlib integration" OFF)
|
||||||
|
option(YOSYS_WITHOUT_LIBFFI "Disable libffi integration" OFF)
|
||||||
|
option(YOSYS_WITHOUT_READLINE "Disable readline integration" OFF)
|
||||||
|
option(YOSYS_WITHOUT_EDITLINE "Disable editline integration" OFF)
|
||||||
|
option(YOSYS_WITHOUT_TCL "Disable Tcl integration" OFF)
|
||||||
|
option(YOSYS_WITH_PYTHON "Enable Python integration" OFF)
|
||||||
|
|
||||||
|
set(YOSYS_VERIFIC_DIR "" CACHE FILEPATH "Path to the Verific source code (empty to disable)")
|
||||||
|
set(YOSYS_VERIFIC_COMPONENTS "" CACHE STRING
|
||||||
|
"List of Verific components to link (empty for autodetect)")
|
||||||
|
set(YOSYS_VERIFIC_FEATURES "" CACHE STRING
|
||||||
|
"List of Yosys Verific frontend features to enable (empty for autodetect)")
|
||||||
|
|
||||||
|
option(YOSYS_INSTALL_DRIVER "Install Yosys executable" ON)
|
||||||
|
option(YOSYS_INSTALL_LIBRARY "Install libyosys library" OFF)
|
||||||
|
cmake_dependent_option(YOSYS_INSTALL_PYTHON "Install Python extension module" OFF
|
||||||
|
YOSYS_WITH_PYTHON OFF)
|
||||||
|
set(YOSYS_INSTALL_PYTHON_SITEDIR "" CACHE STRING "Path to Python package installation directory")
|
||||||
|
|
||||||
|
# This option is something of a hack to make Python wheels buildable in an environment that has
|
||||||
|
# the `Development.Module` component, but not `Development.Embed` (e.g. cibuildwheel). It is only
|
||||||
|
# present to be used in the wheel build and is not supported otherwise.
|
||||||
|
cmake_dependent_option(YOSYS_BUILD_PYTHON_ONLY "Build only Pyosys components" ON
|
||||||
|
"NOT (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY) AND YOSYS_INSTALL_PYTHON" OFF)
|
||||||
|
mark_as_advanced(YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
|
||||||
|
# Configure compiler.
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
|
||||||
|
|
||||||
|
if (YOSYS_COMPILER_LAUNCHER)
|
||||||
|
set(CMAKE_C_COMPILER_LAUNCHER "${YOSYS_COMPILER_LAUNCHER}")
|
||||||
|
set(CMAKE_CXX_COMPILER_LAUNCHER "${YOSYS_COMPILER_LAUNCHER}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||||
|
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
check_pie_supported() # opportunistically enable PIE
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -ggdb")
|
||||||
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
|
||||||
|
set(CMAKE_CXX_FLAGS_SANITIZE "-O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||||
|
if ("${SANITIZE}" MATCHES "memory")
|
||||||
|
set(CMAKE_CXX_FLAGS_SANITIZE "${CMAKE_CXX_FLAGS_SANITIZE} -fsanitize-memory-track-origins")
|
||||||
|
endif()
|
||||||
|
set(no_abc_options
|
||||||
|
"$<$<AND:$<NOT:$<BOOL:$<TARGET_PROPERTY:YOSYS_IS_ABC>>>,$<CONFIG:Sanitize>>:-fsanitize=${SANITIZE}>"
|
||||||
|
"$<$<NOT:$<BOOL:$<TARGET_PROPERTY:YOSYS_IS_ABC>>>:-Wall;-Wextra;-Werror=unused>"
|
||||||
|
)
|
||||||
|
add_compile_options("${no_abc_options}")
|
||||||
|
add_link_options("${no_abc_options}")
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "/Od /DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "/O2")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os")
|
||||||
|
add_compile_options(/Zc:__cplusplus)
|
||||||
|
add_compile_definitions(
|
||||||
|
_CRT_NONSTDC_NO_DEPRECATE
|
||||||
|
_CRT_SECURE_NO_WARNINGS
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# We have to do this because CMake adds `-DNDEBUG` in release builds by default, and there's
|
||||||
|
# no particularly good way to prevent this without also erasing optimization flags.
|
||||||
|
# If you see this message, reproduce the block above with the flags supported by your compiler.
|
||||||
|
message(FATAL_ERROR "${CMAKE_CXX_COMPILER_ID} compiler is not supported")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (YOSYS_ENABLE_COVERAGE)
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Code coverage is not supported on ${CMAKE_CXX_COMPILER_ID} compiler")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (YOSYS_ENABLE_PROFILING)
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Instruction profiling is not supported on ${CMAKE_CXX_COMPILER_ID} compiler")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)
|
||||||
|
message(FATAL_ERROR "C and C++ compilers must be provided by the same vendor")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||||
|
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
|
||||||
|
set(CMAKE_C_FLAGS_SANITIZE "${CMAKE_CXX_FLAGS_SANITIZE}")
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "WASI")
|
||||||
|
add_compile_options(
|
||||||
|
-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false
|
||||||
|
-D_WASI_EMULATED_PROCESS_CLOCKS
|
||||||
|
)
|
||||||
|
add_link_options(
|
||||||
|
-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false -lunwind
|
||||||
|
-lwasi-emulated-process-clocks
|
||||||
|
-Wl,--stack-first,-z,stack-size=8388608
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16.0.0")
|
||||||
|
# GCC 15.2 sometimes refuses to construct an import directory for yosys.exe/libyosys.dll with:
|
||||||
|
# .../ld.exe: error: export ordinal too large: 67035
|
||||||
|
# The cause is unknown.
|
||||||
|
message(WARNING "MinGW GCC is supported starting with version 16.0.0")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Required dependencies.
|
||||||
|
find_package(FLEX)
|
||||||
|
set_package_properties(FLEX PROPERTIES
|
||||||
|
URL "https://github.com/westes/flex"
|
||||||
|
DESCRIPTION "The Fast Lexical Analyzer"
|
||||||
|
PURPOSE "Compiling the Verilog lexer"
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(BISON)
|
||||||
|
set_package_properties(BISON PROPERTIES
|
||||||
|
URL "https://www.gnu.org/software/bison/"
|
||||||
|
DESCRIPTION "The Yacc-compatible Parser Generator"
|
||||||
|
PURPOSE "Compiling the Verilog parser"
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Python3 3.7 COMPONENTS Interpreter)
|
||||||
|
set_package_properties(Python3 PROPERTIES
|
||||||
|
URL "https://www.python.org/"
|
||||||
|
DESCRIPTION "Dynamic programming language (Interpreter)"
|
||||||
|
PURPOSE "Generating data files\n Running external SMT2 solvers"
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
|
||||||
|
# Optional dependencies.
|
||||||
|
check_glob()
|
||||||
|
check_system()
|
||||||
|
check_popen()
|
||||||
|
find_package(Threads QUIET)
|
||||||
|
check_pthread_create()
|
||||||
|
find_package(Dlfcn QUIET)
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
set_package_properties(PkgConfig PROPERTIES
|
||||||
|
URL "https://www.freedesktop.org/wiki/Software/pkg-config/"
|
||||||
|
DESCRIPTION "Library metadata manager"
|
||||||
|
PURPOSE "Discovering dependencies"
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
)
|
||||||
|
|
||||||
|
pkg_config_import(zlib)
|
||||||
|
set_package_properties(zlib PROPERTIES
|
||||||
|
URL "https://github.com/madler/zlib"
|
||||||
|
DESCRIPTION "A massively spiffy yet delicately unobtrusive compression library"
|
||||||
|
PURPOSE "Handling Gzip and FST file formats"
|
||||||
|
)
|
||||||
|
|
||||||
|
pkg_config_import(libffi)
|
||||||
|
set_package_properties(libffi PROPERTIES
|
||||||
|
URL "https://sourceware.org/libffi/"
|
||||||
|
DESCRIPTION "A Portable Foreign Function Interface Library"
|
||||||
|
PURPOSE "Implementing Verilog DPI-C"
|
||||||
|
)
|
||||||
|
|
||||||
|
pkg_config_import(editline MODULES libedit)
|
||||||
|
set_package_properties(editline PROPERTIES
|
||||||
|
URL "https://www.thrysoee.dk/editline/"
|
||||||
|
DESCRIPTION "Line editing and history library (BSD)"
|
||||||
|
PURPOSE "Enhancing the command prompt"
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
)
|
||||||
|
|
||||||
|
pkg_config_import(readline)
|
||||||
|
set_package_properties(readline PROPERTIES
|
||||||
|
URL "https://tiswww.case.edu/php/chet/readline/rltop.html"
|
||||||
|
DESCRIPTION "Line editing and history library (GPL)"
|
||||||
|
PURPOSE "Enhancing the command prompt"
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
)
|
||||||
|
|
||||||
|
# See https://core.tcl-lang.org/tips/doc/trunk/tip/538.md
|
||||||
|
pkg_config_import(tcl MODULES tcl)
|
||||||
|
set_package_properties(tcl PROPERTIES
|
||||||
|
URL "https://www.tcl-lang.org/"
|
||||||
|
DESCRIPTION "Dynamic programming language"
|
||||||
|
PURPOSE "Parsing SDC constraint files\n Binding Yosys API"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (tcl_FOUND)
|
||||||
|
get_target_property(tcl_options PkgConfig::tcl INTERFACE_COMPILE_OPTIONS)
|
||||||
|
if (tcl_options MATCHES "TCL_WITH_EXTERNAL_TOMMATH")
|
||||||
|
pkg_config_import(libtommath)
|
||||||
|
set_package_properties(libtommath PROPERTIES
|
||||||
|
URL "https://www.libtom.net/LibTomMath/"
|
||||||
|
DESCRIPTION "Multiple-precision integer library"
|
||||||
|
PURPOSE "Required by this build of Tcl"
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
# Unfortunately the pkg-config file for Tcl includes libtommath as a private dependency,
|
||||||
|
# while it should be public since it is exposed in the public API and necessary for its use.
|
||||||
|
target_link_libraries(PkgConfig::tcl INTERFACE PkgConfig::libtommath)
|
||||||
|
else()
|
||||||
|
# Vendored within Tcl itself.
|
||||||
|
set(libtommath_FOUND TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (YOSYS_WITH_PYTHON)
|
||||||
|
find_package(Python3Devel REQUIRED)
|
||||||
|
set_property(GLOBAL PROPERTY _CMAKE_Python3Devel_REQUIRED_VERSION "== ${Python3_VERSION}")
|
||||||
|
set_package_properties(Python3Devel PROPERTIES
|
||||||
|
URL "https://www.python.org/"
|
||||||
|
DESCRIPTION "Dynamic programming language (Embedding)"
|
||||||
|
PURPOSE "Binding Yosys API"
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(PyosysEnv REQUIRED)
|
||||||
|
set_package_properties(PyosysEnv PROPERTIES
|
||||||
|
DESCRIPTION "Pyosys wrapper generator environment"
|
||||||
|
PURPOSE "Either 'uv' or 'pybind11>3,<4 cxxheaderparser'"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(GTest)
|
||||||
|
set_package_properties(GTest PROPERTIES
|
||||||
|
URL "https://google.github.io/googletest/"
|
||||||
|
DESCRIPTION "C++ testing and mocking framework by Google"
|
||||||
|
PURPOSE "Running unit tests"
|
||||||
|
TYPE RECOMMENDED
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configure features based on dependency availability.
|
||||||
|
message(VERBOSE "Conditional features:")
|
||||||
|
condition(YOSYS_ENABLE_GLOB HAVE_GLOB)
|
||||||
|
condition(YOSYS_ENABLE_SPAWN HAVE_SYSTEM AND HAVE_POPEN)
|
||||||
|
condition(YOSYS_ENABLE_THREADS Threads_FOUND AND HAVE_PTHREAD_CREATE AND NOT YOSYS_DISABLE_THREADS)
|
||||||
|
condition(YOSYS_ENABLE_PLUGINS Dlfcn_FOUND)
|
||||||
|
condition(YOSYS_ENABLE_ABC NOT YOSYS_WITHOUT_ABC)
|
||||||
|
condition(YOSYS_ENABLE_ZLIB zlib_FOUND AND NOT YOSYS_WITHOUT_ZLIB)
|
||||||
|
condition(YOSYS_ENABLE_LIBFFI Dlfcn_FOUND AND libffi_FOUND AND NOT YOSYS_WITHOUT_LIBFFI)
|
||||||
|
condition(YOSYS_ENABLE_READLINE readline_FOUND AND NOT YOSYS_WITHOUT_READLINE)
|
||||||
|
condition(YOSYS_ENABLE_EDITLINE editline_FOUND AND NOT YOSYS_WITHOUT_EDITLINE AND NOT YOSYS_ENABLE_READLINE)
|
||||||
|
condition(YOSYS_ENABLE_TCL tcl_FOUND AND libtommath_FOUND AND NOT YOSYS_WITHOUT_TCL)
|
||||||
|
condition(YOSYS_ENABLE_PYTHON Python3Devel_FOUND AND PyosysEnv_FOUND AND YOSYS_WITH_PYTHON)
|
||||||
|
condition(YOSYS_ENABLE_VERIFIC YOSYS_VERIFIC_DIR AND zlib_FOUND)
|
||||||
|
|
||||||
|
# Describe dependencies and features
|
||||||
|
# CMake 4.0 would let us use proper conditions, but that's too new for now.
|
||||||
|
add_feature_info(have_glob YOSYS_ENABLE_GLOB "Glob expansion in filenames")
|
||||||
|
add_feature_info(have_spawn YOSYS_ENABLE_SPAWN "Passes that invoke external tools")
|
||||||
|
add_feature_info(have_threads YOSYS_ENABLE_THREADS "Multithreaded netlist operations")
|
||||||
|
add_feature_info(have_plugins YOSYS_ENABLE_PLUGINS "Dynamically loadable binary plugins")
|
||||||
|
add_feature_info(with_abc YOSYS_ENABLE_ABC "Production-quality logic synthesis flow")
|
||||||
|
add_feature_info(with_zlib YOSYS_ENABLE_ZLIB "Transparent Gzip decompression and FST file format support")
|
||||||
|
add_feature_info(with_libffi YOSYS_ENABLE_LIBFFI "Verilog DPI-C foreign function interface")
|
||||||
|
add_feature_info(with_readline YOSYS_ENABLE_READLINE "Using readline for prompt editing and history")
|
||||||
|
add_feature_info(with_editline YOSYS_ENABLE_EDITLINE "Using editline for prompt editing and history")
|
||||||
|
add_feature_info(with_tcl YOSYS_ENABLE_TCL "Tcl scripting and SDC parsing")
|
||||||
|
add_feature_info(with_python YOSYS_ENABLE_PYTHON "Python scripting and embedding")
|
||||||
|
add_feature_info(with_verific YOSYS_ENABLE_VERIFIC "Verific frontend integration")
|
||||||
|
message(STATUS "")
|
||||||
|
feature_summary(WHAT PACKAGES_FOUND
|
||||||
|
DEFAULT_DESCRIPTION)
|
||||||
|
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
|
||||||
|
DEFAULT_DESCRIPTION QUIET_ON_EMPTY FATAL_ON_MISSING_REQUIRED_PACKAGES
|
||||||
|
)
|
||||||
|
feature_summary(WHAT PACKAGES_NOT_FOUND
|
||||||
|
DEFAULT_DESCRIPTION QUIET_ON_EMPTY
|
||||||
|
)
|
||||||
|
feature_summary(WHAT ENABLED_FEATURES
|
||||||
|
DEFAULT_DESCRIPTION QUIET_ON_EMPTY)
|
||||||
|
feature_summary(WHAT DISABLED_FEATURES
|
||||||
|
DEFAULT_DESCRIPTION QUIET_ON_EMPTY)
|
||||||
|
|
||||||
|
# Describe project version.
|
||||||
|
yosys_extract_version()
|
||||||
|
|
||||||
|
# Describe ABC integration.
|
||||||
|
if (YOSYS_ENABLE_ABC AND NOT YOSYS_ENABLE_SPAWN AND NOT YOSYS_ABC_EXECUTABLE STREQUAL "INTEGRATED-NOTFOUND")
|
||||||
|
message(WARNING "ABC support on this platform forces -DYOSYS_ABC_EXECUTABLE=INTEGRATED-NOTFOUND")
|
||||||
|
set(YOSYS_ABC_EXECUTABLE "INTEGRATED-NOTFOUND" CACHE FILEPATH "" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(YOSYS_LINK_ABC 0)
|
||||||
|
if (YOSYS_ENABLE_ABC)
|
||||||
|
if (NOT YOSYS_ABC_EXECUTABLE AND NOT YOSYS_SKIP_ABC_SUBMODULE_CHECK)
|
||||||
|
yosys_check_abc_submodule()
|
||||||
|
endif()
|
||||||
|
if (YOSYS_ABC_EXECUTABLE STREQUAL "INTEGRATED-NOTFOUND")
|
||||||
|
set(YOSYS_LINK_ABC 1)
|
||||||
|
message(STATUS "Building ABC: (integrated)")
|
||||||
|
elseif (YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||||
|
set(abc_filename ${YOSYS_PROGRAM_PREFIX}yosys-abc${CMAKE_EXECUTABLE_SUFFIX})
|
||||||
|
message(STATUS "Building ABC: ${YOSYS_INSTALL_FULL_BINDIR}/${abc_filename}")
|
||||||
|
else()
|
||||||
|
message(STATUS "External ABC: ${YOSYS_ABC_EXECUTABLE}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Ensure invalid dependencies fail at configuration time, not link time.
|
||||||
|
set(CMAKE_LINK_LIBRARIES_ONLY_TARGETS ON)
|
||||||
|
|
||||||
|
# Pseudo-library that injects common compilation options into every Yosys component.
|
||||||
|
add_library(yosys_common INTERFACE)
|
||||||
|
target_compile_definitions(yosys_common INTERFACE
|
||||||
|
_YOSYS_
|
||||||
|
$<$<CONFIG:Debug,RelWithDebInfo>:DEBUG>
|
||||||
|
)
|
||||||
|
target_include_directories(yosys_common INTERFACE
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
)
|
||||||
|
if (SANITIZE)
|
||||||
|
target_compile_options(yosys_common INTERFACE
|
||||||
|
${sanitize_options}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Two pseudo-components used for dependency tracking only.
|
||||||
|
yosys_core(essentials BOOTSTRAP)
|
||||||
|
yosys_core(everything BOOTSTRAP)
|
||||||
|
|
||||||
|
# All of the source code.
|
||||||
|
add_subdirectory(libs)
|
||||||
|
add_subdirectory(kernel)
|
||||||
|
add_subdirectory(passes)
|
||||||
|
add_subdirectory(frontends)
|
||||||
|
add_subdirectory(backends)
|
||||||
|
add_subdirectory(techlibs)
|
||||||
|
if (YOSYS_ENABLE_PYTHON)
|
||||||
|
add_subdirectory(pyosys)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ABC submodule.
|
||||||
|
if (YOSYS_ENABLE_ABC AND NOT YOSYS_ABC_EXECUTABLE)
|
||||||
|
set(YOSYS_ABC_INSTALL NO)
|
||||||
|
if (YOSYS_ABC_EXECUTABLE STREQUAL "" AND (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY))
|
||||||
|
set(YOSYS_ABC_INSTALL YES)
|
||||||
|
endif()
|
||||||
|
yosys_abc_target(libyosys-abc yosys-abc
|
||||||
|
INSTALL_IF ${YOSYS_ABC_INSTALL}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compute a transitive closure of enabled components.
|
||||||
|
yosys_expand_components(library_components essentials ${YOSYS_COMPONENTS})
|
||||||
|
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
yosys_expand_components(driver_components driver ${YOSYS_COMPONENTS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Main Yosys executable (compiler driver).
|
||||||
|
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
yosys_cxx_executable(yosys
|
||||||
|
OUTPUT_NAME yosys
|
||||||
|
INSTALL_IF ${YOSYS_INSTALL_DRIVER}
|
||||||
|
)
|
||||||
|
yosys_link_components(yosys PRIVATE ${driver_components})
|
||||||
|
set_property(TARGET yosys PROPERTY ENABLE_EXPORTS ON)
|
||||||
|
if (MINGW)
|
||||||
|
target_link_options(yosys PRIVATE LINKER:--export-all-symbols)
|
||||||
|
set_target_properties(yosys PROPERTIES
|
||||||
|
# Final name: `yosys.exe.a` (linked to explicitly)
|
||||||
|
IMPORT_PREFIX ""
|
||||||
|
IMPORT_SUFFIX ".exe.a"
|
||||||
|
)
|
||||||
|
if (YOSYS_INSTALL_DRIVER)
|
||||||
|
install(FILES ${CMAKE_BINARY_DIR}/yosys.exe.a DESTINATION ${YOSYS_INSTALL_LIBDIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_options(yosys PRIVATE -fsanitize=undefined)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Yosys components as a library.
|
||||||
|
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(libyosys_type SHARED)
|
||||||
|
else()
|
||||||
|
set(libyosys_type STATIC)
|
||||||
|
endif()
|
||||||
|
yosys_cxx_library(libyosys ${libyosys_type}
|
||||||
|
OUTPUT_NAME libyosys
|
||||||
|
INSTALL_IF ${YOSYS_INSTALL_LIBRARY}
|
||||||
|
)
|
||||||
|
yosys_link_components(libyosys PRIVATE ${library_components})
|
||||||
|
add_library(Yosys::libyosys ALIAS libyosys)
|
||||||
|
if (MINGW)
|
||||||
|
set_target_properties(libyosys PROPERTIES
|
||||||
|
# Final name: `libyosys.dll.a` (linked to via `-lyosys`)
|
||||||
|
IMPORT_PREFIX ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Yosys data files (mainly headers and technological libraries).
|
||||||
|
if (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY)
|
||||||
|
yosys_install_component_data(${library_components} DESTINATION ${YOSYS_INSTALL_DATADIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Python binary extension (for using Yosys as a Python library).
|
||||||
|
if (YOSYS_ENABLE_PYTHON)
|
||||||
|
yosys_cxx_library(pyosys MODULE
|
||||||
|
OUTPUT_NAME pyosys
|
||||||
|
)
|
||||||
|
yosys_link_components(pyosys PRIVATE ${library_components})
|
||||||
|
set_target_properties(pyosys PROPERTIES EXCLUDE_FROM_ALL FALSE) # build but not install
|
||||||
|
if (YOSYS_ENABLE_ABC AND YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||||
|
add_dependencies(pyosys yosys-abc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (YOSYS_INSTALL_PYTHON)
|
||||||
|
string(REPLACE "-" "_" PYOSYS_MODULE_PREFIX "${YOSYS_PROGRAM_PREFIX}")
|
||||||
|
if (YOSYS_INSTALL_PYTHON_SITEDIR STREQUAL "")
|
||||||
|
set(YOSYS_INSTALL_PYTHON_SITEDIR ${Python3_SITEARCH})
|
||||||
|
endif()
|
||||||
|
set(pyosys_install_dir ${YOSYS_INSTALL_PYTHON_SITEDIR}/${PYOSYS_MODULE_PREFIX}pyosys)
|
||||||
|
install(FILES pyosys/modinit.py
|
||||||
|
RENAME __init__.py
|
||||||
|
DESTINATION ${pyosys_install_dir}
|
||||||
|
)
|
||||||
|
install(FILES $<TARGET_FILE:pyosys>
|
||||||
|
RENAME libyosys${CMAKE_SHARED_MODULE_SUFFIX}
|
||||||
|
DESTINATION ${pyosys_install_dir}
|
||||||
|
)
|
||||||
|
if (YOSYS_ENABLE_ABC AND YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||||
|
# If ABC is vendored it needs to be installed as a part of pyosys.
|
||||||
|
install(TARGETS yosys-abc
|
||||||
|
DESTINATION ${pyosys_install_dir}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
yosys_install_component_data(${library_components} DESTINATION ${pyosys_install_dir}/share)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Plugin build tool.
|
||||||
|
yosys_config_script(BUILD)
|
||||||
|
if (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY)
|
||||||
|
yosys_config_script(INSTALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configuration for Makefile-based steps.
|
||||||
|
# (The use of `${makefile_vars}` in `add_custom_{target,command}()` adds dependencies for
|
||||||
|
# all of the targets specified via `$<TARGET_FILE:tgt>`.)
|
||||||
|
set(makefile_vars
|
||||||
|
BUILD_DIR=${CMAKE_BINARY_DIR}
|
||||||
|
PROGRAM_PREFIX=${YOSYS_PROGRAM_PREFIX}
|
||||||
|
ABC=$<IF:$<TARGET_EXISTS:yosys-abc>,$<TARGET_FILE:yosys-abc>,${YOSYS_ABC_EXECUTABLE}>
|
||||||
|
YOSYS=$<TARGET_FILE:yosys>
|
||||||
|
YOSYS_CONFIG=${CMAKE_BINARY_DIR}/yosys-config
|
||||||
|
YOSYS_FILTERLIB=$<$<TARGET_EXISTS:yosys-filterlib>:$<TARGET_FILE:yosys-filterlib>>
|
||||||
|
YOSYS_SMTBMC=${CMAKE_BINARY_DIR}/yosys-smtbmc
|
||||||
|
YOSYS_WITNESS=${CMAKE_BINARY_DIR}/yosys-witness
|
||||||
|
)
|
||||||
|
set(makefile_depends
|
||||||
|
# abc is implied via $<TARGET_FILE>
|
||||||
|
# yosys is implied via $<TARGET_FILE>
|
||||||
|
# yosys-filterlib is implied via $<TARGET_FILE>
|
||||||
|
$<$<TARGET_EXISTS:yosys-smtbmc>:yosys-smtbmc>
|
||||||
|
$<$<TARGET_EXISTS:yosys-witness>:yosys-witness>
|
||||||
|
)
|
||||||
|
|
||||||
|
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
# Tests.
|
||||||
|
add_subdirectory(tests/unit)
|
||||||
|
|
||||||
|
add_custom_target(test-unit
|
||||||
|
COMMAND ${CMAKE_CTEST_COMMAND} --test-dir tests/unit --output-on-failure
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(test-vanilla
|
||||||
|
COMMAND make vanilla-test ${makefile_vars}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||||
|
DEPENDS ${makefile_depends}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(test
|
||||||
|
DEPENDS test-unit test-vanilla
|
||||||
|
)
|
||||||
|
|
||||||
|
# Docs.
|
||||||
|
add_custom_target(docs-prepare
|
||||||
|
COMMAND make gen ${makefile_vars}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
|
||||||
|
DEPENDS ${makefile_depends}
|
||||||
|
)
|
||||||
|
foreach (format html latexpdf)
|
||||||
|
add_custom_target(docs-${format}
|
||||||
|
COMMAND make ${format}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
|
||||||
|
DEPENDS docs-prepare
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Utilities.
|
||||||
|
add_custom_target(print-version
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo ${YOSYS_VERSION}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
yosys_expand_components(all_components everything QUIET)
|
||||||
|
list(TRANSFORM all_components PREPEND "COMMAND;${CMAKE_COMMAND};-E;echo;" OUTPUT_VARIABLE echo_all_components)
|
||||||
|
add_custom_target(print-yosys-components
|
||||||
|
${echo_all_components}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
math(EXPR YOSYS_VERSION_MINOR_next "${YOSYS_VERSION_MINOR} + 1")
|
||||||
|
add_custom_target(increment-minor-version
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo
|
||||||
|
"set(YOSYS_VERSION_MAJOR ${YOSYS_VERSION_MAJOR})"
|
||||||
|
> ${CMAKE_SOURCE_DIR}/cmake/YosysVersionData.cmake
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo
|
||||||
|
"set(YOSYS_VERSION_MINOR ${YOSYS_VERSION_MINOR_next})"
|
||||||
|
>> ${CMAKE_SOURCE_DIR}/cmake/YosysVersionData.cmake
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
@ -1,70 +1,15 @@
|
||||||
# Introduction
|
# Contributing to Yosys
|
||||||
|
|
||||||
Thanks for thinking about contributing to the Yosys project. If this is your
|
Thanks for considering helping out. If this is your
|
||||||
first time contributing to an open source project, please take a look at the
|
first time contributing to an open source project, please take a look at the
|
||||||
following guide:
|
following guide about the basics:
|
||||||
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
|
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
|
||||||
|
|
||||||
Information about the Yosys coding style is available on our Read the Docs:
|
Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html) to learn the best ways to
|
||||||
https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html.
|
|
||||||
|
|
||||||
# Using the issue tracker
|
+ get help
|
||||||
|
+ report bugs
|
||||||
|
+ contribute code
|
||||||
|
+ review code
|
||||||
|
|
||||||
The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for
|
If you're reading this file offline and don't have internet access, you can [read the contributing.rst file locally](docs/source/yosys_internals/extending_yosys/contributing.rst).
|
||||||
tracking bugs or other problems with Yosys or its documentation. It is also the
|
|
||||||
place to go for requesting new features.
|
|
||||||
When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose),
|
|
||||||
we have a few templates available. Please make use of these! It will make it
|
|
||||||
much easier for someone to respond and help.
|
|
||||||
|
|
||||||
### Bug reports
|
|
||||||
|
|
||||||
Before you submit an issue, please check out the [how-to guide for
|
|
||||||
`bugpoint`](https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html).
|
|
||||||
This guide will take you through the process of using the [`bugpoint`
|
|
||||||
command](https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html) in Yosys to
|
|
||||||
produce a [minimal, complete and verifiable
|
|
||||||
example](https://stackoverflow.com/help/minimal-reproducible-example) (MVCE).
|
|
||||||
Providing an MVCE with your bug report drastically increases the likelihood that
|
|
||||||
someone will be able to help resolve your issue.
|
|
||||||
|
|
||||||
|
|
||||||
# Using pull requests
|
|
||||||
|
|
||||||
If you are working on something to add to Yosys, or fix something that isn't
|
|
||||||
working quite right, make a [PR](https://github.com/YosysHQ/yosys/pulls)! An
|
|
||||||
open PR, even as a draft, tells everyone that you're working on it and they
|
|
||||||
don't have to. It can also be a useful way to solicit feedback on in-progress
|
|
||||||
changes. See below to find the best way to [ask us
|
|
||||||
questions](#asking-questions).
|
|
||||||
|
|
||||||
In general, all changes to the code are done as a PR, with [Continuous
|
|
||||||
Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that
|
|
||||||
automatically run the full suite of tests compiling and running Yosys. Please
|
|
||||||
make use of this! If you're adding a feature: add a test! Not only does it
|
|
||||||
verify that your feature is working as expected, but it can also be a handy way
|
|
||||||
for people to see how the feature is used. If you're fixing a bug: add a test!
|
|
||||||
If you can, do this first; it's okay if the test starts off failing - you
|
|
||||||
already know there is a bug. CI also helps to make sure that your changes still
|
|
||||||
work under a range of compilers, settings, and targets.
|
|
||||||
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
|
|
||||||
We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise
|
|
||||||
issues and PRs. If a label seems relevant to your work, please do add it; this
|
|
||||||
also includes the labels beggining with 'status-'. The 'merge-' labels are used
|
|
||||||
by maintainers for tracking and communicating which PRs are ready and pending
|
|
||||||
merge; please do not use these labels if you are not a maintainer.
|
|
||||||
|
|
||||||
|
|
||||||
# Asking questions
|
|
||||||
|
|
||||||
If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions
|
|
||||||
page](https://github.com/YosysHQ/yosys/discussions).
|
|
||||||
The Discourse is also a great place to ask questions about developing or
|
|
||||||
contributing to Yosys.
|
|
||||||
|
|
||||||
We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) where developers from YosysHQ and the
|
|
||||||
community come together to discuss open issues and PRs. This is also a good
|
|
||||||
place to talk to us about how to implement larger PRs.
|
|
||||||
|
|
|
||||||
2
COPYING
2
COPYING
|
|
@ -1,6 +1,6 @@
|
||||||
ISC License
|
ISC License
|
||||||
|
|
||||||
Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com>
|
Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
|
||||||
58
Dockerfile
58
Dockerfile
|
|
@ -1,58 +0,0 @@
|
||||||
ARG IMAGE="python:3-slim-buster"
|
|
||||||
|
|
||||||
#---
|
|
||||||
|
|
||||||
FROM $IMAGE AS base
|
|
||||||
|
|
||||||
RUN apt-get update -qq \
|
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
|
|
||||||
ca-certificates \
|
|
||||||
clang \
|
|
||||||
lld \
|
|
||||||
curl \
|
|
||||||
libffi-dev \
|
|
||||||
libreadline-dev \
|
|
||||||
tcl-dev \
|
|
||||||
graphviz \
|
|
||||||
xdot \
|
|
||||||
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
|
|
||||||
&& update-ca-certificates \
|
|
||||||
&& rm -rf /var/lib/apt/lists
|
|
||||||
|
|
||||||
#---
|
|
||||||
|
|
||||||
FROM base AS build
|
|
||||||
|
|
||||||
RUN apt-get update -qq \
|
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
|
|
||||||
bison \
|
|
||||||
flex \
|
|
||||||
gawk \
|
|
||||||
gcc \
|
|
||||||
git \
|
|
||||||
iverilog \
|
|
||||||
pkg-config \
|
|
||||||
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
|
|
||||||
&& rm -rf /var/lib/apt/lists
|
|
||||||
|
|
||||||
COPY . /yosys
|
|
||||||
|
|
||||||
ENV PREFIX /opt/yosys
|
|
||||||
|
|
||||||
RUN cd /yosys \
|
|
||||||
&& make \
|
|
||||||
&& make install \
|
|
||||||
&& make test
|
|
||||||
|
|
||||||
#---
|
|
||||||
|
|
||||||
FROM base
|
|
||||||
|
|
||||||
COPY --from=build /opt/yosys /opt/yosys
|
|
||||||
|
|
||||||
ENV PATH /opt/yosys/bin:$PATH
|
|
||||||
|
|
||||||
RUN useradd -m yosys
|
|
||||||
USER yosys
|
|
||||||
|
|
||||||
CMD ["yosys"]
|
|
||||||
|
|
@ -114,8 +114,8 @@ To build Yosys simply type 'make' in this directory.
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
Tests are located in the tests subdirectory and can be executed using the test
|
Tests are located in the tests subdirectory and can be executed using the test
|
||||||
target. Note that you need gawk as well as a recent version of iverilog (i.e.
|
target. Note that you need gawk, a recent version of iverilog, and gtest.
|
||||||
build from git). Then, execute tests via:
|
Execute tests via:
|
||||||
|
|
||||||
$ make test
|
$ make test
|
||||||
|
|
||||||
|
|
@ -246,6 +246,8 @@ Building the documentation
|
||||||
|
|
||||||
Note that there is no need to build the manual if you just want to read it.
|
Note that there is no need to build the manual if you just want to read it.
|
||||||
Simply visit https://yosys.readthedocs.io/en/latest/ instead.
|
Simply visit https://yosys.readthedocs.io/en/latest/ instead.
|
||||||
|
If you're offline, you can read the sources, replacing `.../en/latest`
|
||||||
|
with `docs/source`.
|
||||||
|
|
||||||
In addition to those packages listed above for building Yosys from source, the
|
In addition to those packages listed above for building Yosys from source, the
|
||||||
following are used for building the website:
|
following are used for building the website:
|
||||||
|
|
|
||||||
2
abc
2
abc
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1c5ed1ce378cc04beac30bb31abc4c37c8467042
|
Subproject commit 5d51a5e420f5de493d07bf61109a977248c86ffb
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
add_subdirectory(aiger)
|
||||||
|
add_subdirectory(aiger2)
|
||||||
|
add_subdirectory(blif)
|
||||||
|
add_subdirectory(btor)
|
||||||
|
add_subdirectory(cxxrtl)
|
||||||
|
add_subdirectory(edif)
|
||||||
|
add_subdirectory(firrtl)
|
||||||
|
add_subdirectory(functional)
|
||||||
|
add_subdirectory(intersynth)
|
||||||
|
add_subdirectory(jny)
|
||||||
|
add_subdirectory(json)
|
||||||
|
add_subdirectory(rtlil)
|
||||||
|
add_subdirectory(simplec)
|
||||||
|
add_subdirectory(smt2)
|
||||||
|
add_subdirectory(smv)
|
||||||
|
add_subdirectory(spice)
|
||||||
|
add_subdirectory(table)
|
||||||
|
add_subdirectory(verilog)
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
yosys_backend(aiger
|
||||||
|
aiger.cc
|
||||||
|
REQUIRES
|
||||||
|
json11
|
||||||
|
)
|
||||||
|
yosys_backend(xaiger
|
||||||
|
xaiger.cc
|
||||||
|
)
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/aiger/aiger.o
|
|
||||||
OBJS += backends/aiger/xaiger.o
|
|
||||||
|
|
||||||
|
|
@ -340,7 +340,7 @@ struct AigerWriter
|
||||||
if (cell->type == ID($scopeinfo))
|
if (cell->type == ID($scopeinfo))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
log_error("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto bit : unused_bits)
|
for (auto bit : unused_bits)
|
||||||
|
|
@ -349,10 +349,10 @@ struct AigerWriter
|
||||||
if (!undriven_bits.empty()) {
|
if (!undriven_bits.empty()) {
|
||||||
undriven_bits.sort();
|
undriven_bits.sort();
|
||||||
for (auto bit : undriven_bits) {
|
for (auto bit : undriven_bits) {
|
||||||
log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
|
log_warning("Treating undriven bit %s.%s like $anyseq.\n", module, log_signal(bit));
|
||||||
input_bits.insert(bit);
|
input_bits.insert(bit);
|
||||||
}
|
}
|
||||||
log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
|
log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), module);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_map.sort();
|
init_map.sort();
|
||||||
|
|
@ -635,35 +635,35 @@ struct AigerWriter
|
||||||
int a = aig_map.at(sig[i]);
|
int a = aig_map.at(sig[i]);
|
||||||
log_assert((a & 1) == 0);
|
log_assert((a & 1) == 0);
|
||||||
if (GetSize(wire) != 1)
|
if (GetSize(wire) != 1)
|
||||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
|
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", wire, i));
|
||||||
else
|
else
|
||||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
|
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wire->port_output) {
|
if (wire->port_output) {
|
||||||
int o = ordered_outputs.at(SigSpec(wire, i));
|
int o = ordered_outputs.at(SigSpec(wire, i));
|
||||||
if (GetSize(wire) != 1)
|
if (GetSize(wire) != 1)
|
||||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
|
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", wire, i));
|
||||||
else
|
else
|
||||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
|
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_inputs.count(sig[i])) {
|
if (init_inputs.count(sig[i])) {
|
||||||
int a = init_inputs.at(sig[i]);
|
int a = init_inputs.at(sig[i]);
|
||||||
log_assert((a & 1) == 0);
|
log_assert((a & 1) == 0);
|
||||||
if (GetSize(wire) != 1)
|
if (GetSize(wire) != 1)
|
||||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
|
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", wire, i));
|
||||||
else
|
else
|
||||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
|
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ordered_latches.count(sig[i])) {
|
if (ordered_latches.count(sig[i])) {
|
||||||
int l = ordered_latches.at(sig[i]);
|
int l = ordered_latches.at(sig[i]);
|
||||||
const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
|
const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
|
||||||
if (GetSize(wire) != 1)
|
if (GetSize(wire) != 1)
|
||||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
|
symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, wire, i));
|
||||||
else
|
else
|
||||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
|
symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, wire));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -705,30 +705,30 @@ struct AigerWriter
|
||||||
int index = no_startoffset ? i : (wire->start_offset+i);
|
int index = no_startoffset ? i : (wire->start_offset+i);
|
||||||
|
|
||||||
if (verbose_map)
|
if (verbose_map)
|
||||||
wire_lines[a] += stringf("wire %d %d %s\n", a, index, log_id(wire));
|
wire_lines[a] += stringf("wire %d %d %s\n", a, index, wire);
|
||||||
|
|
||||||
if (wire->port_input) {
|
if (wire->port_input) {
|
||||||
log_assert((a & 1) == 0);
|
log_assert((a & 1) == 0);
|
||||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, log_id(wire));
|
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wire->port_output) {
|
if (wire->port_output) {
|
||||||
int o = ordered_outputs.at(SigSpec(wire, i));
|
int o = ordered_outputs.at(SigSpec(wire, i));
|
||||||
output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire));
|
output_lines[o] += stringf("output %d %d %s\n", o, index, wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_inputs.count(sig[i])) {
|
if (init_inputs.count(sig[i])) {
|
||||||
int a = init_inputs.at(sig[i]);
|
int a = init_inputs.at(sig[i]);
|
||||||
log_assert((a & 1) == 0);
|
log_assert((a & 1) == 0);
|
||||||
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, log_id(wire));
|
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ordered_latches.count(sig[i])) {
|
if (ordered_latches.count(sig[i])) {
|
||||||
int l = ordered_latches.at(sig[i]);
|
int l = ordered_latches.at(sig[i]);
|
||||||
if (zinit_mode && (aig_latchinit.at(l) == 1))
|
if (zinit_mode && (aig_latchinit.at(l) == 1))
|
||||||
latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, log_id(wire));
|
latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, wire);
|
||||||
else
|
else
|
||||||
latch_lines[l] += stringf("latch %d %d %s\n", l, index, log_id(wire));
|
latch_lines[l] += stringf("latch %d %d %s\n", l, index, wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -930,7 +930,9 @@ struct AigerBackend : public Backend {
|
||||||
log(" make indexes zero based, enable using map files with smt solvers.\n");
|
log(" make indexes zero based, enable using map files with smt solvers.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -ywmap <filename>\n");
|
log(" -ywmap <filename>\n");
|
||||||
log(" write a map file for conversion to and from yosys witness traces.\n");
|
log(" write a map file for conversion to and from yosys witness traces,\n");
|
||||||
|
log(" also allows for mapping AIGER bad-state properties and invariant\n");
|
||||||
|
log(" constraints back to individual formal properties by name.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -I, -O, -B, -L\n");
|
log(" -I, -O, -B, -L\n");
|
||||||
log(" If the design contains no input/output/assert/flip-flop then create one\n");
|
log(" If the design contains no input/output/assert/flip-flop then create one\n");
|
||||||
|
|
@ -1025,12 +1027,12 @@ struct AigerBackend : public Backend {
|
||||||
log_error("Can't find top module in current design!\n");
|
log_error("Can't find top module in current design!\n");
|
||||||
|
|
||||||
if (!design->selected_whole_module(top_module))
|
if (!design->selected_whole_module(top_module))
|
||||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
|
log_cmd_error("Can't handle partially selected module %s!\n", top_module);
|
||||||
|
|
||||||
if (!top_module->processes.empty())
|
if (!top_module->processes.empty())
|
||||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module));
|
log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", top_module);
|
||||||
if (!top_module->memories.empty())
|
if (!top_module->memories.empty())
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", top_module);
|
||||||
|
|
||||||
AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode);
|
AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode);
|
||||||
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ struct XAigerWriter
|
||||||
if (ys_debug(1)) {
|
if (ys_debug(1)) {
|
||||||
static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
|
static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
|
||||||
if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n",
|
if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n",
|
||||||
log_id(cell->type), log_id(i.first.name), offset, d);
|
cell->type.unescape(), i.first.name.unescape(), offset, d);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
arrival_times[rhs[offset]] = d;
|
arrival_times[rhs[offset]] = d;
|
||||||
|
|
@ -285,7 +285,7 @@ struct XAigerWriter
|
||||||
auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first);
|
auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first);
|
||||||
auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first);
|
auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first);
|
||||||
if (!is_input && !is_output)
|
if (!is_input && !is_output)
|
||||||
log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type));
|
log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", c.first.unescape(), cell, cell->type.unescape());
|
||||||
|
|
||||||
if (is_input)
|
if (is_input)
|
||||||
for (auto b : c.second) {
|
for (auto b : c.second) {
|
||||||
|
|
@ -303,7 +303,7 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
//log_warning("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
dict<IdString, std::vector<IdString>> box_ports;
|
dict<IdString, std::vector<IdString>> box_ports;
|
||||||
|
|
@ -325,12 +325,12 @@ struct XAigerWriter
|
||||||
if (w->get_bool_attribute(ID::abc9_carry)) {
|
if (w->get_bool_attribute(ID::abc9_carry)) {
|
||||||
if (w->port_input) {
|
if (w->port_input) {
|
||||||
if (carry_in != IdString())
|
if (carry_in != IdString())
|
||||||
log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module));
|
log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", box_module);
|
||||||
carry_in = port_name;
|
carry_in = port_name;
|
||||||
}
|
}
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
if (carry_out != IdString())
|
if (carry_out != IdString())
|
||||||
log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module));
|
log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", box_module);
|
||||||
carry_out = port_name;
|
carry_out = port_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -339,9 +339,9 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (carry_in != IdString() && carry_out == IdString())
|
if (carry_in != IdString() && carry_out == IdString())
|
||||||
log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module));
|
log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", box_module);
|
||||||
if (carry_in == IdString() && carry_out != IdString())
|
if (carry_in == IdString() && carry_out != IdString())
|
||||||
log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module));
|
log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", box_module);
|
||||||
if (carry_in != IdString()) {
|
if (carry_in != IdString()) {
|
||||||
r.first->second.push_back(carry_in);
|
r.first->second.push_back(carry_in);
|
||||||
r.first->second.push_back(carry_out);
|
r.first->second.push_back(carry_out);
|
||||||
|
|
@ -612,7 +612,7 @@ struct XAigerWriter
|
||||||
write_r_buffer(mergeability);
|
write_r_buffer(mergeability);
|
||||||
|
|
||||||
State init = init_map.at(q, State::Sx);
|
State init = init_map.at(q, State::Sx);
|
||||||
log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init));
|
log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", cell, cell->type.unescape(), log_signal(init));
|
||||||
if (init == State::S1)
|
if (init == State::S1)
|
||||||
write_s_buffer(1);
|
write_s_buffer(1);
|
||||||
else if (init == State::S0)
|
else if (init == State::S0)
|
||||||
|
|
@ -692,12 +692,12 @@ struct XAigerWriter
|
||||||
if (input_bits.count(b)) {
|
if (input_bits.count(b)) {
|
||||||
int a = aig_map.at(b);
|
int a = aig_map.at(b);
|
||||||
log_assert((a & 1) == 0);
|
log_assert((a & 1) == 0);
|
||||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
|
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_bits.count(b)) {
|
if (output_bits.count(b)) {
|
||||||
int o = ordered_outputs.at(b);
|
int o = ordered_outputs.at(b);
|
||||||
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire));
|
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +709,7 @@ struct XAigerWriter
|
||||||
|
|
||||||
int box_count = 0;
|
int box_count = 0;
|
||||||
for (auto cell : box_list)
|
for (auto cell : box_list)
|
||||||
f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name));
|
f << stringf("box %d %d %s\n", box_count++, 0, cell->name.unescape());
|
||||||
|
|
||||||
output_lines.sort();
|
output_lines.sort();
|
||||||
for (auto &it : output_lines)
|
for (auto &it : output_lines)
|
||||||
|
|
@ -774,12 +774,12 @@ struct XAigerBackend : public Backend {
|
||||||
log_error("Can't find top module in current design!\n");
|
log_error("Can't find top module in current design!\n");
|
||||||
|
|
||||||
if (!design->selected_whole_module(top_module))
|
if (!design->selected_whole_module(top_module))
|
||||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
|
log_cmd_error("Can't handle partially selected module %s!\n", top_module);
|
||||||
|
|
||||||
if (!top_module->processes.empty())
|
if (!top_module->processes.empty())
|
||||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module));
|
log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", top_module);
|
||||||
if (!top_module->memories.empty())
|
if (!top_module->memories.empty())
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", top_module);
|
||||||
|
|
||||||
XAigerWriter writer(top_module, dff_mode);
|
XAigerWriter writer(top_module, dff_mode);
|
||||||
writer.write_aiger(*f, ascii_mode);
|
writer.write_aiger(*f, ascii_mode);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
yosys_backend(aiger2
|
||||||
|
aiger.cc
|
||||||
|
PROVIDES
|
||||||
|
write_xaiger2
|
||||||
|
)
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
OBJS += backends/aiger2/aiger.o
|
|
||||||
|
|
@ -21,9 +21,13 @@
|
||||||
// - gracefully handling inout ports (an error message probably)
|
// - gracefully handling inout ports (an error message probably)
|
||||||
// - undriven wires
|
// - undriven wires
|
||||||
// - zero-width operands
|
// - zero-width operands
|
||||||
|
// - decide how to unify this with cellaigs
|
||||||
|
// - break up Index into something smaller
|
||||||
|
// - (C++20) remove snprintf-into-std::ostream weirdness
|
||||||
|
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
@ -44,8 +48,22 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
// TODO
|
// TODO
|
||||||
//#define ARITH_OPS ID($add), ID($sub), ID($neg)
|
//#define ARITH_OPS ID($add), ID($sub), ID($neg)
|
||||||
|
|
||||||
#define KNOWN_OPS BITWISE_OPS, REDUCE_OPS, LOGIC_OPS, GATE_OPS, ID($pos), CMP_OPS, \
|
static constexpr auto known_ops = []() constexpr {
|
||||||
ID($pmux), ID($bmux) /*, ARITH_OPS*/
|
StaticCellTypes::Categories::Category c{};
|
||||||
|
for (auto id : {BITWISE_OPS})
|
||||||
|
c.set_id(id);
|
||||||
|
for (auto id : {REDUCE_OPS})
|
||||||
|
c.set_id(id);
|
||||||
|
for (auto id : {LOGIC_OPS})
|
||||||
|
c.set_id(id);
|
||||||
|
for (auto id : {GATE_OPS})
|
||||||
|
c.set_id(id);
|
||||||
|
for (auto id : {CMP_OPS})
|
||||||
|
c.set_id(id);
|
||||||
|
for (auto id : {ID($pos), ID($pmux), ID($bmux)})
|
||||||
|
c.set_id(id);
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
|
|
||||||
template<typename Writer, typename Lit, Lit CFALSE, Lit CTRUE>
|
template<typename Writer, typename Lit, Lit CFALSE, Lit CTRUE>
|
||||||
struct Index {
|
struct Index {
|
||||||
|
|
@ -91,7 +109,7 @@ struct Index {
|
||||||
int pos = index_wires(info, m);
|
int pos = index_wires(info, m);
|
||||||
|
|
||||||
for (auto cell : m->cells()) {
|
for (auto cell : m->cells()) {
|
||||||
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
if (known_ops(cell->type) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Module *submodule = m->design->module(cell->type);
|
Module *submodule = m->design->module(cell->type);
|
||||||
|
|
@ -114,7 +132,7 @@ struct Index {
|
||||||
continue;
|
continue;
|
||||||
if (!submodule || submodule->get_blackbox_attribute())
|
if (!submodule || submodule->get_blackbox_attribute())
|
||||||
log_error("Unsupported cell type: %s (%s in %s)\n",
|
log_error("Unsupported cell type: %s (%s in %s)\n",
|
||||||
log_id(cell->type), log_id(cell), log_id(m));
|
cell->type.unescape(), cell, m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,6 +180,11 @@ struct Index {
|
||||||
if (!strashing) {
|
if (!strashing) {
|
||||||
return (static_cast<Writer*>(this))->emit_gate(a, b);
|
return (static_cast<Writer*>(this))->emit_gate(a, b);
|
||||||
} else {
|
} else {
|
||||||
|
// AigMaker::node2index
|
||||||
|
|
||||||
|
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||||
|
// and XOR gates. AND gates have their first input literal be larger
|
||||||
|
// than their second, and vice-versa for XORs.
|
||||||
if (a < b) std::swap(a, b);
|
if (a < b) std::swap(a, b);
|
||||||
auto pair = std::make_pair(a, b);
|
auto pair = std::make_pair(a, b);
|
||||||
|
|
||||||
|
|
@ -182,7 +205,9 @@ struct Index {
|
||||||
|
|
||||||
Lit OR(Lit a, Lit b)
|
Lit OR(Lit a, Lit b)
|
||||||
{
|
{
|
||||||
return NOT(AND(NOT(a), NOT(b)));
|
Lit not_a = NOT(a);
|
||||||
|
Lit not_b = NOT(b);
|
||||||
|
return NOT(AND(not_a, not_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit MUX(Lit a, Lit b, Lit s)
|
Lit MUX(Lit a, Lit b, Lit s)
|
||||||
|
|
@ -196,17 +221,24 @@ struct Index {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OR(AND(a, NOT(s)), AND(b, s));
|
Lit not_s = NOT(s);
|
||||||
|
Lit a_active = AND(a, not_s);
|
||||||
|
Lit b_active = AND(b, s);
|
||||||
|
return OR(a_active, b_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit XOR(Lit a, Lit b)
|
Lit XOR(Lit a, Lit b)
|
||||||
{
|
{
|
||||||
return OR(AND(a, NOT(b)), AND(NOT(a), b));
|
Lit not_a = NOT(a);
|
||||||
|
Lit not_b = NOT(b);
|
||||||
|
Lit a_and_not_b = AND(a, not_b);
|
||||||
|
Lit not_a_and_b = AND(not_a, b);
|
||||||
|
return OR(a_and_not_b, not_a_and_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit XNOR(Lit a, Lit b)
|
Lit XNOR(Lit a, Lit b)
|
||||||
{
|
{
|
||||||
return NOT(OR(AND(a, NOT(b)), AND(NOT(a), b)));
|
return NOT(XOR(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit CARRY(Lit a, Lit b, Lit c)
|
Lit CARRY(Lit a, Lit b, Lit c)
|
||||||
|
|
@ -218,7 +250,10 @@ struct Index {
|
||||||
return AND(a, b);
|
return AND(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OR(AND(a, b), AND(c, OR(a, b)));
|
Lit a_or_b = OR(a, b);
|
||||||
|
Lit a_or_b_and_c = AND(c, a_or_b);
|
||||||
|
Lit a_and_b = AND(a, b);
|
||||||
|
return OR(a_and_b, a_or_b_and_c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit REDUCE(std::vector<Lit> lits, bool op_xor=false)
|
Lit REDUCE(std::vector<Lit> lits, bool op_xor=false)
|
||||||
|
|
@ -366,7 +401,7 @@ struct Index {
|
||||||
} else if (cell->type.in(ID($xor), ID($_XOR_))) {
|
} else if (cell->type.in(ID($xor), ID($_XOR_))) {
|
||||||
return XOR(a, b);
|
return XOR(a, b);
|
||||||
} else if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
} else if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||||
return NOT(XOR(a, b));
|
return XNOR(a, b);
|
||||||
} else if (cell->type.in(ID($_ANDNOT_))) {
|
} else if (cell->type.in(ID($_ANDNOT_))) {
|
||||||
return AND(a, NOT(b));
|
return AND(a, NOT(b));
|
||||||
} else if (cell->type.in(ID($_ORNOT_))) {
|
} else if (cell->type.in(ID($_ORNOT_))) {
|
||||||
|
|
@ -386,7 +421,9 @@ struct Index {
|
||||||
if (oport == ID::Y) {
|
if (oport == ID::Y) {
|
||||||
return XOR(ab, c);
|
return XOR(ab, c);
|
||||||
} else /* oport == ID::X */ {
|
} else /* oport == ID::X */ {
|
||||||
return OR(AND(a, b), AND(c, ab));
|
Lit a_and_b = AND(a, b);
|
||||||
|
Lit c_and_ab = AND(c, ab);
|
||||||
|
return OR(a_and_b, c_and_ab);
|
||||||
}
|
}
|
||||||
} else if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
|
} else if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
|
||||||
Lit c, d;
|
Lit c, d;
|
||||||
|
|
@ -397,10 +434,15 @@ struct Index {
|
||||||
else
|
else
|
||||||
d = cell->type == ID($_AOI3_) ? CTRUE : CFALSE;
|
d = cell->type == ID($_AOI3_) ? CTRUE : CFALSE;
|
||||||
|
|
||||||
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_)))
|
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_))) {
|
||||||
return NOT(OR(AND(a, b), AND(c, d)));
|
Lit a_and_b = AND(a, b);
|
||||||
else
|
Lit c_and_d = AND(c, d);
|
||||||
return NOT(AND(OR(a, b), OR(c, d)));
|
return NOT(OR(a_and_b, c_and_d));
|
||||||
|
} else {
|
||||||
|
Lit a_or_b = OR(a, b);
|
||||||
|
Lit c_or_d = OR(c, d);
|
||||||
|
return NOT(AND(a_or_b, c_or_d));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log_abort();
|
log_abort();
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +463,11 @@ struct Index {
|
||||||
sels.push_back(NOT(s));
|
sels.push_back(NOT(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
return OR(AND(REDUCE(sels), a), NOT(REDUCE(bar)));
|
Lit reduce_sels = REDUCE(sels);
|
||||||
|
Lit reduce_sels_and_a = AND(reduce_sels, a);
|
||||||
|
Lit reduce_bar = NOT(REDUCE(bar));
|
||||||
|
|
||||||
|
return OR(reduce_sels_and_a, reduce_bar);
|
||||||
} else if (cell->type == ID($bmux)) {
|
} else if (cell->type == ID($bmux)) {
|
||||||
SigSpec aport = cell->getPort(ID::A);
|
SigSpec aport = cell->getPort(ID::A);
|
||||||
SigSpec sport = cell->getPort(ID::S);
|
SigSpec sport = cell->getPort(ID::S);
|
||||||
|
|
@ -491,7 +537,7 @@ struct Index {
|
||||||
Design *design = index.design;
|
Design *design = index.design;
|
||||||
auto &minfo = leaf_minfo(index);
|
auto &minfo = leaf_minfo(index);
|
||||||
if (!minfo.suboffsets.count(cell))
|
if (!minfo.suboffsets.count(cell))
|
||||||
log_error("Reached unsupport cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module));
|
log_error("Reached unsupported cell %s (%s in %s)\n", cell->type.unescape(), cell, cell->module);
|
||||||
Module *def = design->module(cell->type);
|
Module *def = design->module(cell->type);
|
||||||
log_assert(def);
|
log_assert(def);
|
||||||
levels.push_back(Level(index.modules.at(def), cell));
|
levels.push_back(Level(index.modules.at(def), cell));
|
||||||
|
|
@ -510,13 +556,13 @@ struct Index {
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto pair : levels) {
|
for (auto [minfo, cell] : levels) {
|
||||||
if (!first)
|
if (!first)
|
||||||
ret += ".";
|
ret += ".";
|
||||||
if (!pair.second)
|
if (!cell)
|
||||||
ret += RTLIL::unescape_id(pair.first.module->name);
|
ret += minfo.module->name.unescape();
|
||||||
else
|
else
|
||||||
ret += RTLIL::unescape_id(pair.second->name);
|
ret += cell->name.unescape();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -525,8 +571,8 @@ struct Index {
|
||||||
int hash() const
|
int hash() const
|
||||||
{
|
{
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
for (auto pair : levels)
|
for (auto [_, cell] : levels)
|
||||||
hash += (uintptr_t) pair.second;
|
hash += (uintptr_t) cell;
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -535,9 +581,12 @@ struct Index {
|
||||||
if (levels.size() != other.levels.size())
|
if (levels.size() != other.levels.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < levels.size(); i++)
|
for (int i = 0; i < levels.size(); i++) {
|
||||||
if (levels[i].second != other.levels[i].second)
|
auto* cell = levels[i].second;
|
||||||
|
auto* other_cell = other.levels[i].second;
|
||||||
|
if (cell != other_cell)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -578,7 +627,7 @@ struct Index {
|
||||||
// an output of a cell
|
// an output of a cell
|
||||||
Cell *driver = bit.wire->driverCell();
|
Cell *driver = bit.wire->driverCell();
|
||||||
|
|
||||||
if (driver->type.in(KNOWN_OPS)) {
|
if (known_ops(driver->type)) {
|
||||||
ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset);
|
ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset);
|
||||||
} else {
|
} else {
|
||||||
Module *def = cursor.enter(*this, driver);
|
Module *def = cursor.enter(*this, driver);
|
||||||
|
|
@ -587,10 +636,10 @@ struct Index {
|
||||||
Wire *w = def->wire(portname);
|
Wire *w = def->wire(portname);
|
||||||
if (!w)
|
if (!w)
|
||||||
log_error("Output port %s on instance %s of %s doesn't exist\n",
|
log_error("Output port %s on instance %s of %s doesn't exist\n",
|
||||||
log_id(portname), log_id(driver), log_id(def));
|
portname.unescape(), driver, def);
|
||||||
if (bit.offset >= w->width)
|
if (bit.offset >= w->width)
|
||||||
log_error("Bit position %d of output port %s on instance %s of %s is out of range (port has width %d)\n",
|
log_error("Bit position %d of output port %s on instance %s of %s is out of range (port has width %d)\n",
|
||||||
bit.offset, log_id(portname), log_id(driver), log_id(def), w->width);
|
bit.offset, portname.unescape(), driver, def, w->width);
|
||||||
ret = visit(cursor, SigBit(w, bit.offset));
|
ret = visit(cursor, SigBit(w, bit.offset));
|
||||||
}
|
}
|
||||||
cursor.exit(*this);
|
cursor.exit(*this);
|
||||||
|
|
@ -606,11 +655,11 @@ struct Index {
|
||||||
IdString portname = bit.wire->name;
|
IdString portname = bit.wire->name;
|
||||||
if (!instance->hasPort(portname))
|
if (!instance->hasPort(portname))
|
||||||
log_error("Input port %s on instance %s of %s unconnected\n",
|
log_error("Input port %s on instance %s of %s unconnected\n",
|
||||||
log_id(portname), log_id(instance), log_id(instance->type));
|
portname.unescape(), instance, instance->type);
|
||||||
auto &port = instance->getPort(portname);
|
auto &port = instance->getPort(portname);
|
||||||
if (bit.offset >= port.size())
|
if (bit.offset >= port.size())
|
||||||
log_error("Bit %d of input port %s on instance %s of %s unconnected\n",
|
log_error("Bit %d of input port %s on instance %s of %s unconnected\n",
|
||||||
bit.offset, log_id(portname), log_id(instance), log_id(instance->type));
|
bit.offset, portname.unescape(), instance, instance->type.unescape());
|
||||||
ret = visit(cursor, port[bit.offset]);
|
ret = visit(cursor, port[bit.offset]);
|
||||||
}
|
}
|
||||||
cursor.enter(*this, instance);
|
cursor.enter(*this, instance);
|
||||||
|
|
@ -700,6 +749,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
nands++;
|
nands++;
|
||||||
lit_counter += 2;
|
lit_counter += 2;
|
||||||
|
|
||||||
|
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||||
|
// and XOR gates. AND gates have their first input literal be larger
|
||||||
|
// than their second, and vice-versa for XORs.
|
||||||
if (a < b) std::swap(a, b);
|
if (a < b) std::swap(a, b);
|
||||||
encode(out - a);
|
encode(out - a);
|
||||||
encode(a - b);
|
encode(a - b);
|
||||||
|
|
@ -716,7 +768,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2);
|
log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2);
|
||||||
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
snprintf(buf, sizeof(buf) - 1, "aig %08d %08d %08d %08d %08d\n",
|
snprintf(buf, sizeof(buf), "aig %08d %08d %08d %08d %08d\n",
|
||||||
ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands);
|
ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
@ -729,15 +781,16 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
// populate inputs
|
// populate inputs
|
||||||
std::vector<SigBit> inputs;
|
std::vector<SigBit> inputs;
|
||||||
for (auto id : top->ports) {
|
for (auto id : top->ports) {
|
||||||
Wire *w = top->wire(id);
|
Wire *w = top->wire(id);
|
||||||
log_assert(w);
|
log_assert(w);
|
||||||
if (w->port_input && !w->port_output)
|
if (w->port_input && !w->port_output)
|
||||||
for (int i = 0; i < w->width; i++) {
|
for (int i = 0; i < w->width; i++) {
|
||||||
pi_literal(SigBit(w, i)) = lit_counter;
|
auto bit = SigBit(w, i);
|
||||||
inputs.push_back(SigBit(w, i));
|
pi_literal(bit) = lit_counter;
|
||||||
lit_counter += 2;
|
inputs.push_back(bit);
|
||||||
ninputs++;
|
lit_counter += 2;
|
||||||
}
|
ninputs++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->f = f;
|
this->f = f;
|
||||||
|
|
@ -745,35 +798,38 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
write_header();
|
write_header();
|
||||||
// insert padding where output literals will go (once known)
|
// insert padding where output literals will go (once known)
|
||||||
for (auto id : top->ports) {
|
for (auto id : top->ports) {
|
||||||
Wire *w = top->wire(id);
|
Wire *w = top->wire(id);
|
||||||
log_assert(w);
|
log_assert(w);
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w)) {
|
for (auto bit : SigSpec(w)) {
|
||||||
(void) bit;
|
(void) bit;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
noutputs++;
|
noutputs++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
auto data_start = f->tellp();
|
auto data_start = f->tellp();
|
||||||
|
|
||||||
// now the guts
|
// now the guts
|
||||||
std::vector<std::pair<SigBit, int>> outputs;
|
std::vector<std::pair<SigBit, int>> outputs;
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w))
|
for (auto bit : SigSpec(w))
|
||||||
outputs.push_back({bit, eval_po(bit)});
|
// Each call to eval_po eventually reaches emit_gate and
|
||||||
}
|
// encode which writes to f.
|
||||||
|
outputs.push_back({bit, eval_po(bit)});
|
||||||
|
}
|
||||||
|
|
||||||
auto data_end = f->tellp();
|
auto data_end = f->tellp();
|
||||||
|
|
||||||
// revisit header and the list of outputs
|
// revisit header and the list of outputs
|
||||||
f->seekp(file_start);
|
f->seekp(file_start);
|
||||||
write_header();
|
write_header();
|
||||||
for (auto pair : outputs) {
|
for (auto [_, po] : outputs) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", pair.second);
|
snprintf(buf, sizeof(buf), "%08d\n", po);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
// double check we arrived at the same offset for the
|
// double check we arrived at the same offset for the
|
||||||
|
|
@ -782,12 +838,13 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
|
|
||||||
f->seekp(data_end);
|
f->seekp(data_end);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto pair : outputs) {
|
for (auto [bit, _] : outputs) {
|
||||||
if (SigSpec(pair.first).is_wire()) {
|
if (SigSpec(bit).is_wire()) {
|
||||||
|
// primary output symbol
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf) - 1, "o%d ", i);
|
snprintf(buf, sizeof(buf), "o%d ", i);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
std::string name = RTLIL::unescape_id(pair.first.wire->name);
|
std::string name = bit.wire->name.unescape();
|
||||||
f->write(name.data(), name.size());
|
f->write(name.data(), name.size());
|
||||||
f->put('\n');
|
f->put('\n');
|
||||||
}
|
}
|
||||||
|
|
@ -796,10 +853,11 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||||
i = 0;
|
i = 0;
|
||||||
for (auto bit : inputs) {
|
for (auto bit : inputs) {
|
||||||
if (SigSpec(bit).is_wire()) {
|
if (SigSpec(bit).is_wire()) {
|
||||||
|
// primary input symbol
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf) - 1, "i%d ", i);
|
snprintf(buf, sizeof(buf), "i%d ", i);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
std::string name = RTLIL::unescape_id(bit.wire->name);
|
std::string name = bit.wire->name.unescape();
|
||||||
f->write(name.data(), name.size());
|
f->write(name.data(), name.size());
|
||||||
f->put('\n');
|
f->put('\n');
|
||||||
}
|
}
|
||||||
|
|
@ -845,11 +903,14 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int max = 1;
|
int max = 1;
|
||||||
for (auto wire : mod->wires())
|
for (auto wire : mod->wires()) {
|
||||||
if (wire->port_input && !wire->port_output)
|
if (wire->port_input && !wire->port_output) {
|
||||||
for (int i = 0; i < wire->width; i++) {
|
SigSpec port = driver->getPort(wire->name);
|
||||||
int ilevel = visit(cursor, driver->getPort(wire->name)[i]);
|
for (int i = 0; i < std::min(wire->width, port.size()); i++) {
|
||||||
max = std::max(max, ilevel + 1);
|
int ilevel = visit(cursor, port[i]);
|
||||||
|
max = std::max(max, ilevel + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lits[idx] = max;
|
lits[idx] = max;
|
||||||
|
|
||||||
|
|
@ -867,33 +928,34 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
|
||||||
Wire *w = top->wire(id);
|
Wire *w = top->wire(id);
|
||||||
log_assert(w);
|
log_assert(w);
|
||||||
if (w->port_input && !w->port_output)
|
if (w->port_input && !w->port_output)
|
||||||
for (int i = 0; i < w->width; i++)
|
for (int i = 0; i < w->width; i++)
|
||||||
pi_literal(SigBit(w, i)) = 0;
|
pi_literal(SigBit(w, i)) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HierCursor cursor;
|
HierCursor cursor;
|
||||||
for (auto box : top_minfo->found_blackboxes) {
|
for (auto box : top_minfo->found_blackboxes) {
|
||||||
Module *def = design->module(box->type);
|
Module *def = design->module(box->type);
|
||||||
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
||||||
for (auto &conn : box->connections_)
|
for (auto &conn : box->connections_)
|
||||||
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
|
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
|
||||||
for (auto bit : conn.second)
|
for (auto bit : conn.second)
|
||||||
pi_literal(bit, &cursor) = 0;
|
pi_literal(bit, &cursor) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires()) {
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w))
|
for (auto bit : SigSpec(w))
|
||||||
(void) eval_po(bit);
|
(void) eval_po(bit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto box : top_minfo->found_blackboxes) {
|
for (auto box : top_minfo->found_blackboxes) {
|
||||||
Module *def = design->module(box->type);
|
Module *def = design->module(box->type);
|
||||||
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
||||||
for (auto &conn : box->connections_)
|
for (auto &conn : box->connections_)
|
||||||
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
|
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
|
||||||
for (auto bit : conn.second)
|
for (auto bit : conn.second)
|
||||||
(void) eval_po(bit);
|
(void) eval_po(bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -912,15 +974,15 @@ struct XAigerWriter : AigerWriter {
|
||||||
std::vector<HierBit> pos;
|
std::vector<HierBit> pos;
|
||||||
std::vector<HierBit> pis;
|
std::vector<HierBit> pis;
|
||||||
|
|
||||||
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
||||||
// inputs to opaque boxes, then module outputs. COs going first is
|
// inputs to opaque boxes, then module outputs. COs going first is
|
||||||
// required by abc.
|
// required by abc.
|
||||||
// * proper_pos_counter counts ports which follow after COs
|
// * proper_pos_counter counts ports which follow after COs
|
||||||
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
||||||
// to the first port following COs.
|
// to the first port following COs.
|
||||||
// * If a module output is directly driven by an opaque box, the emission
|
// * If a module output is directly driven by an opaque box, the emission
|
||||||
// of the po statement in the mapping file is skipped. This is done to
|
// of the po statement in the mapping file is skipped. This is done to
|
||||||
// aid re-integration of the mapped result.
|
// aid re-integration of the mapped result.
|
||||||
int proper_pos_counter = 0;
|
int proper_pos_counter = 0;
|
||||||
|
|
||||||
pool<SigBit> driven_by_opaque_box;
|
pool<SigBit> driven_by_opaque_box;
|
||||||
|
|
@ -986,7 +1048,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
} else if (!is_input && !inputs) {
|
} else if (!is_input && !inputs) {
|
||||||
for (auto &bit : conn.second) {
|
for (auto &bit : conn.second) {
|
||||||
if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output))
|
if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output))
|
||||||
log_error("Bad connection %s/%s ~ %s\n", log_id(box), log_id(conn.first), log_signal(conn.second));
|
log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), log_signal(conn.second));
|
||||||
|
|
||||||
|
|
||||||
ensure_pi(bit, cursor);
|
ensure_pi(bit, cursor);
|
||||||
|
|
@ -1011,9 +1073,9 @@ struct XAigerWriter : AigerWriter {
|
||||||
void prep_boxes(int pending_pos_num)
|
void prep_boxes(int pending_pos_num)
|
||||||
{
|
{
|
||||||
XAigerAnalysis analysis;
|
XAigerAnalysis analysis;
|
||||||
log_debug("preforming analysis on '%s'\n", log_id(top));
|
log_debug("preforming analysis on '%s'\n", top);
|
||||||
analysis.analyze(top);
|
analysis.analyze(top);
|
||||||
log_debug("analysis on '%s' done\n", log_id(top));
|
log_debug("analysis on '%s' done\n", top);
|
||||||
|
|
||||||
// boxes which have timing data, maybe a whitebox model
|
// boxes which have timing data, maybe a whitebox model
|
||||||
std::vector<std::tuple<HierCursor, Cell *, Module *>> nonopaque_boxes;
|
std::vector<std::tuple<HierCursor, Cell *, Module *>> nonopaque_boxes;
|
||||||
|
|
@ -1026,8 +1088,8 @@ struct XAigerWriter : AigerWriter {
|
||||||
|
|
||||||
for (auto box : minfo.found_blackboxes) {
|
for (auto box : minfo.found_blackboxes) {
|
||||||
log_debug(" - %s.%s (type %s): ", cursor.path(),
|
log_debug(" - %s.%s (type %s): ", cursor.path(),
|
||||||
RTLIL::unescape_id(box->name),
|
box,
|
||||||
log_id(box->type));
|
box->type.unescape());
|
||||||
|
|
||||||
Module *box_module = design->module(box->type), *box_derived;
|
Module *box_module = design->module(box->type), *box_derived;
|
||||||
|
|
||||||
|
|
@ -1096,7 +1158,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
} else {
|
} else {
|
||||||
// FIXME: hierarchical path
|
// FIXME: hierarchical path
|
||||||
log_warning("connection on port %s[%d] of instance %s (type %s) missing, using 1'bx\n",
|
log_warning("connection on port %s[%d] of instance %s (type %s) missing, using 1'bx\n",
|
||||||
log_id(port_id), i, log_id(box), log_id(box->type));
|
port_id.unescape(), i, box, box->type.unescape());
|
||||||
bit = RTLIL::Sx;
|
bit = RTLIL::Sx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1131,7 +1193,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
} else {
|
} else {
|
||||||
// FIXME: hierarchical path
|
// FIXME: hierarchical path
|
||||||
log_warning("connection on port %s[%d] of instance %s (type %s) missing\n",
|
log_warning("connection on port %s[%d] of instance %s (type %s) missing\n",
|
||||||
log_id(port_id), i, log_id(box), log_id(box->type));
|
port_id.unescape(), i, box, box->type.unescape());
|
||||||
pad_pi();
|
pad_pi();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1148,7 +1210,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
holes_wb->setPort(port_id, w);
|
holes_wb->setPort(port_id, w);
|
||||||
} else {
|
} else {
|
||||||
log_error("Ambiguous port direction on %s/%s\n",
|
log_error("Ambiguous port direction on %s/%s\n",
|
||||||
log_id(box->type), log_id(port_id));
|
box->type.unescape(), port_id.unescape());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1198,29 +1260,29 @@ struct XAigerWriter : AigerWriter {
|
||||||
reset_counters();
|
reset_counters();
|
||||||
|
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_input && !w->port_output)
|
if (w->port_input && !w->port_output)
|
||||||
for (int i = 0; i < w->width; i++)
|
for (int i = 0; i < w->width; i++)
|
||||||
ensure_pi(SigBit(w, i));
|
ensure_pi(SigBit(w, i));
|
||||||
|
|
||||||
int proper_po_num = 0;
|
int proper_po_num = 0;
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_output)
|
if (w->port_output)
|
||||||
proper_po_num += w->width;
|
proper_po_num += w->width;
|
||||||
|
|
||||||
prep_boxes(proper_po_num);
|
prep_boxes(proper_po_num);
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_output)
|
if (w->port_output)
|
||||||
for (int i = 0; i < w->width; i++) {
|
for (int i = 0; i < w->width; i++) {
|
||||||
// When a module output is directly driven by an opaque box, we
|
// When a module output is directly driven by an opaque box, we
|
||||||
// don't emit it to the mapping file to aid re-integration, but we
|
// don't emit it to the mapping file to aid re-integration, but we
|
||||||
// do emit a proper PO.
|
// do emit a proper PO.
|
||||||
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
||||||
map_file << "po " << proper_pos_counter << " " << i
|
map_file << "po " << proper_pos_counter << " " << i
|
||||||
<< " " << w->name.c_str() << "\n";
|
<< " " << w->name.c_str() << "\n";
|
||||||
}
|
}
|
||||||
proper_pos_counter++;
|
proper_pos_counter++;
|
||||||
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->f = f;
|
this->f = f;
|
||||||
// start with the header
|
// start with the header
|
||||||
|
|
@ -1230,7 +1292,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
// insert padding where output literals will go (once known)
|
// insert padding where output literals will go (once known)
|
||||||
for (auto _ : pos) {
|
for (auto _ : pos) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
auto data_start = f->tellp();
|
auto data_start = f->tellp();
|
||||||
|
|
@ -1247,35 +1309,36 @@ struct XAigerWriter : AigerWriter {
|
||||||
write_header();
|
write_header();
|
||||||
for (auto lit : outlits) {
|
for (auto lit : outlits) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", lit);
|
snprintf(buf, sizeof(buf), "%08d\n", lit);
|
||||||
f->write(buf, strlen(buf));
|
f->write(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
// double check we arrived at the same offset for the
|
// double check we arrived at the same offset for the
|
||||||
// main data section
|
// main data section
|
||||||
log_assert(data_start == f->tellp());
|
log_assert(data_start == f->tellp());
|
||||||
|
|
||||||
// extensions
|
// XAIGER extensions
|
||||||
f->seekp(0, std::ios::end);
|
f->seekp(0, std::ios::end);
|
||||||
|
|
||||||
f->put('c');
|
f->put('c'); // 'c': comment (marks beginning of extensions)
|
||||||
|
|
||||||
// insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those)
|
// insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those)
|
||||||
f->put('r');
|
f->put('r'); // 'r': register classes
|
||||||
write_be32(*f, 4);
|
write_be32(*f, 4); // length in bytes
|
||||||
write_be32(*f, 0);
|
write_be32(*f, 0); // no register classes
|
||||||
f->put('s');
|
|
||||||
write_be32(*f, 4);
|
|
||||||
write_be32(*f, 0);
|
|
||||||
|
|
||||||
f->put('h');
|
f->put('s'); // 's': register initial values
|
||||||
|
write_be32(*f, 4); // length in bytes
|
||||||
|
write_be32(*f, 0); // no register initial values
|
||||||
|
|
||||||
|
f->put('h'); // 'h': hierarchy information
|
||||||
// TODO: get rid of std::string copy
|
// TODO: get rid of std::string copy
|
||||||
std::string h_buffer_str = h_buffer.str();
|
std::string h_buffer_str = h_buffer.str();
|
||||||
write_be32(*f, h_buffer_str.size());
|
write_be32(*f, h_buffer_str.size()); // length in bytes
|
||||||
f->write(h_buffer_str.data(), h_buffer_str.size());
|
f->write(h_buffer_str.data(), h_buffer_str.size()); // data
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
f->put('a');
|
f->put('a'); // 'a': additional AIG (used for holes)
|
||||||
write_be32(*f, 0); // size to be filled later
|
write_be32(*f, 0); // length in bytes (to be filled later)
|
||||||
auto holes_aiger_start = f->tellp();
|
auto holes_aiger_start = f->tellp();
|
||||||
{
|
{
|
||||||
AigerWriter holes_writer;
|
AigerWriter holes_writer;
|
||||||
|
|
@ -1287,7 +1350,7 @@ struct XAigerWriter : AigerWriter {
|
||||||
auto holes_aiger_size = f->tellp() - holes_aiger_start;
|
auto holes_aiger_size = f->tellp() - holes_aiger_start;
|
||||||
f->seekp(holes_aiger_start, std::ios::beg);
|
f->seekp(holes_aiger_start, std::ios::beg);
|
||||||
f->seekp(-4, std::ios::cur);
|
f->seekp(-4, std::ios::cur);
|
||||||
write_be32(*f, holes_aiger_size);
|
write_be32(*f, holes_aiger_size); // length in bytes
|
||||||
#endif
|
#endif
|
||||||
f->seekp(0, std::ios::end);
|
f->seekp(0, std::ios::end);
|
||||||
|
|
||||||
|
|
@ -1327,41 +1390,50 @@ struct Aiger2Backend : Backend {
|
||||||
log(" perform structural hashing while writing\n");
|
log(" perform structural hashing while writing\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -flatten\n");
|
log(" -flatten\n");
|
||||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||||
log(" hierarchy starting at the selected top\n");
|
log(" hierarchy starting at the selected top\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("This command is able to ingest all combinational cells except for:\n");
|
log("This command is able to ingest all combinational cells except for:\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
pool<IdString> supported = {KNOWN_OPS};
|
|
||||||
CellTypes ct;
|
|
||||||
ct.setup_internals_eval();
|
|
||||||
log(" ");
|
log(" ");
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (auto pair : ct.cell_types)
|
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||||
if (!supported.count(pair.first)) {
|
auto &cell = StaticCellTypes::builder.cells[i];
|
||||||
if (col + pair.first.size() + 2 > 72) {
|
if (!cell.features.is_evaluable)
|
||||||
|
continue;
|
||||||
|
if (cell.features.is_stdcell)
|
||||||
|
continue;
|
||||||
|
if (known_ops(cell.type))
|
||||||
|
continue;
|
||||||
|
std::string name = cell.type.unescape();
|
||||||
|
if (col + name.size() + 2 > 72) {
|
||||||
log("\n ");
|
log("\n ");
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
col += pair.first.size() + 2;
|
col += name.size() + 2;
|
||||||
log("%s, ", log_id(pair.first));
|
log("%s, ", name.c_str());
|
||||||
}
|
}
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("And all combinational gates except for:\n");
|
log("And all combinational gates except for:\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
CellTypes ct2;
|
|
||||||
ct2.setup_stdcells();
|
|
||||||
log(" ");
|
log(" ");
|
||||||
col = 0;
|
col = 0;
|
||||||
for (auto pair : ct2.cell_types)
|
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||||
if (!supported.count(pair.first)) {
|
auto &cell = StaticCellTypes::builder.cells[i];
|
||||||
if (col + pair.first.size() + 2 > 72) {
|
if (!cell.features.is_evaluable)
|
||||||
|
continue;
|
||||||
|
if (!cell.features.is_stdcell)
|
||||||
|
continue;
|
||||||
|
if (known_ops(cell.type))
|
||||||
|
continue;
|
||||||
|
std::string name = cell.type.unescape();
|
||||||
|
if (col + name.size() + 2 > 72) {
|
||||||
log("\n ");
|
log("\n ");
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
col += pair.first.size() + 2;
|
col += name.size() + 2;
|
||||||
log("%s, ", log_id(pair.first));
|
log("%s, ", name.c_str());
|
||||||
}
|
}
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
@ -1419,20 +1491,20 @@ struct XAiger2Backend : Backend {
|
||||||
log(" perform structural hashing while writing\n");
|
log(" perform structural hashing while writing\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -flatten\n");
|
log(" -flatten\n");
|
||||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||||
log(" hierarchy starting at the selected top\n");
|
log(" hierarchy starting at the selected top\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -mapping_prep\n");
|
log(" -mapping_prep\n");
|
||||||
log(" after the file is written, prepare the module for reintegration of\n");
|
log(" after the file is written, prepare the module for reintegration of\n");
|
||||||
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
||||||
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
||||||
log(" connect to removed cells\n");
|
log(" connect to removed cells\n");
|
||||||
log(" (conflicts with -flatten)\n");
|
log(" (conflicts with -flatten)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -map2 <file>\n");
|
log(" -map2 <file>\n");
|
||||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||||
log(" reintegrate a mapping\n");
|
log(" reintegrate a mapping\n");
|
||||||
log(" (conflicts with -flatten)\n");
|
log(" (conflicts with -flatten)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(blif
|
||||||
|
blif.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/blif/blif.o
|
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -44,6 +44,7 @@ struct BlifDumperConfig
|
||||||
bool iattr_mode;
|
bool iattr_mode;
|
||||||
bool blackbox_mode;
|
bool blackbox_mode;
|
||||||
bool noalias_mode;
|
bool noalias_mode;
|
||||||
|
bool gatesi_mode;
|
||||||
|
|
||||||
std::string buf_type, buf_in, buf_out;
|
std::string buf_type, buf_in, buf_out;
|
||||||
std::map<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> unbuf_types;
|
std::map<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> unbuf_types;
|
||||||
|
|
@ -51,7 +52,7 @@ struct BlifDumperConfig
|
||||||
|
|
||||||
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
|
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
|
||||||
cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
|
cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
|
||||||
blackbox_mode(false), noalias_mode(false) { }
|
blackbox_mode(false), noalias_mode(false), gatesi_mode(false) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlifDumper
|
struct BlifDumper
|
||||||
|
|
@ -60,7 +61,7 @@ struct BlifDumper
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
RTLIL::Design *design;
|
RTLIL::Design *design;
|
||||||
BlifDumperConfig *config;
|
BlifDumperConfig *config;
|
||||||
CellTypes ct;
|
NewCellTypes ct;
|
||||||
|
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
dict<SigBit, int> init_bits;
|
dict<SigBit, int> init_bits;
|
||||||
|
|
@ -90,7 +91,7 @@ struct BlifDumper
|
||||||
|
|
||||||
const std::string str(RTLIL::IdString id)
|
const std::string str(RTLIL::IdString id)
|
||||||
{
|
{
|
||||||
std::string str = RTLIL::unescape_id(id);
|
std::string str = id.unescape();
|
||||||
for (size_t i = 0; i < str.size(); i++)
|
for (size_t i = 0; i < str.size(); i++)
|
||||||
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
||||||
str[i] = '?';
|
str[i] = '?';
|
||||||
|
|
@ -107,7 +108,7 @@ struct BlifDumper
|
||||||
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
|
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str = RTLIL::unescape_id(sig.wire->name);
|
std::string str = sig.wire->name.unescape();
|
||||||
for (size_t i = 0; i < str.size(); i++)
|
for (size_t i = 0; i < str.size(); i++)
|
||||||
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
||||||
str[i] = '?';
|
str[i] = '?';
|
||||||
|
|
@ -118,16 +119,21 @@ struct BlifDumper
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string str_init(RTLIL::SigBit sig)
|
template <bool Space = true> const std::string str_init(RTLIL::SigBit sig)
|
||||||
{
|
{
|
||||||
sigmap.apply(sig);
|
sigmap.apply(sig);
|
||||||
|
|
||||||
if (init_bits.count(sig) == 0)
|
if (init_bits.count(sig) == 0) {
|
||||||
return " 2";
|
if constexpr (Space)
|
||||||
|
return " 2";
|
||||||
|
else
|
||||||
|
return "2";
|
||||||
|
}
|
||||||
|
|
||||||
string str = stringf(" %d", init_bits.at(sig));
|
if constexpr (Space)
|
||||||
|
return stringf(" %d", init_bits.at(sig));
|
||||||
return str;
|
else
|
||||||
|
return stringf("%d", init_bits.at(sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *subckt_or_gate(std::string cell_type)
|
const char *subckt_or_gate(std::string cell_type)
|
||||||
|
|
@ -144,7 +150,7 @@ struct BlifDumper
|
||||||
void dump_params(const char *command, dict<IdString, Const> ¶ms)
|
void dump_params(const char *command, dict<IdString, Const> ¶ms)
|
||||||
{
|
{
|
||||||
for (auto ¶m : params) {
|
for (auto ¶m : params) {
|
||||||
f << stringf("%s %s ", command, log_id(param.first));
|
f << stringf("%s %s ", command, param.first.unescape());
|
||||||
if (param.second.flags & RTLIL::CONST_FLAG_STRING) {
|
if (param.second.flags & RTLIL::CONST_FLAG_STRING) {
|
||||||
std::string str = param.second.decode_string();
|
std::string str = param.second.decode_string();
|
||||||
f << stringf("\"");
|
f << stringf("\"");
|
||||||
|
|
@ -469,6 +475,11 @@ struct BlifDumper
|
||||||
f << stringf(".names %s %s\n1 1\n", str(rhs_bit), str(lhs_bit));
|
f << stringf(".names %s %s\n1 1\n", str(rhs_bit), str(lhs_bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->gatesi_mode) {
|
||||||
|
for (auto &&init_bit : init_bits)
|
||||||
|
f << stringf(".gateinit %s=%s\n", str(init_bit.first), str_init<false>(init_bit.first));
|
||||||
|
}
|
||||||
|
|
||||||
f << stringf(".end\n");
|
f << stringf(".end\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,6 +561,9 @@ struct BlifBackend : public Backend {
|
||||||
log(" -impltf\n");
|
log(" -impltf\n");
|
||||||
log(" do not write definitions for the $true, $false and $undef wires.\n");
|
log(" do not write definitions for the $true, $false and $undef wires.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -gatesi\n");
|
||||||
|
log(" write initial bit(s) with .gateinit for gates that needs to be initialized.\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
|
|
@ -640,6 +654,10 @@ struct BlifBackend : public Backend {
|
||||||
config.noalias_mode = true;
|
config.noalias_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-gatesi") {
|
||||||
|
config.gatesi_mode = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(f, filename, args, argidx);
|
extra_args(f, filename, args, argidx);
|
||||||
|
|
@ -660,9 +678,9 @@ struct BlifBackend : public Backend {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (module->processes.size() != 0)
|
if (module->processes.size() != 0)
|
||||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name));
|
log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", module->name.unescape());
|
||||||
if (module->memories.size() != 0)
|
if (module->memories.size() != 0)
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", module->name.unescape());
|
||||||
|
|
||||||
if (module->name == RTLIL::escape_id(top_module_name)) {
|
if (module->name == RTLIL::escape_id(top_module_name)) {
|
||||||
BlifDumper::dump(*f, module, design, config);
|
BlifDumper::dump(*f, module, design, config);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
yosys_backend(btor
|
||||||
|
btor.cc
|
||||||
|
REQUIRES
|
||||||
|
bmuxmap
|
||||||
|
demuxmap
|
||||||
|
bwmuxmap
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/btor/btor.o
|
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ struct BtorWorker
|
||||||
template<typename T>
|
template<typename T>
|
||||||
string getinfo(T *obj, bool srcsym = false)
|
string getinfo(T *obj, bool srcsym = false)
|
||||||
{
|
{
|
||||||
string infostr = log_id(obj);
|
string infostr = obj->name.unescape();
|
||||||
if (!srcsym && !print_internal_names && infostr[0] == '$') return "";
|
if (!srcsym && !print_internal_names && infostr[0] == '$') return "";
|
||||||
if (obj->attributes.count(ID::src)) {
|
if (obj->attributes.count(ID::src)) {
|
||||||
string src = obj->attributes.at(ID::src).decode_string().c_str();
|
string src = obj->attributes.at(ID::src).decode_string().c_str();
|
||||||
|
|
@ -243,12 +243,12 @@ struct BtorWorker
|
||||||
if (cell_recursion_guard.count(cell)) {
|
if (cell_recursion_guard.count(cell)) {
|
||||||
string cell_list;
|
string cell_list;
|
||||||
for (auto c : cell_recursion_guard)
|
for (auto c : cell_recursion_guard)
|
||||||
cell_list += stringf("\n %s", log_id(c));
|
cell_list += stringf("\n %s", c);
|
||||||
log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list);
|
log_error("Found topological loop while processing cell %s. Active cells:%s\n", cell, cell_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_recursion_guard.insert(cell);
|
cell_recursion_guard.insert(cell);
|
||||||
btorf_push(log_id(cell));
|
btorf_push(cell->name.unescape());
|
||||||
|
|
||||||
if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx),
|
if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx),
|
||||||
ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_)))
|
ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_)))
|
||||||
|
|
@ -726,7 +726,7 @@ struct BtorWorker
|
||||||
if (symbol.empty() || (!print_internal_names && symbol[0] == '$'))
|
if (symbol.empty() || (!print_internal_names && symbol[0] == '$'))
|
||||||
btorf("%d state %d\n", nid, sid);
|
btorf("%d state %d\n", nid, sid);
|
||||||
else
|
else
|
||||||
btorf("%d state %d %s\n", nid, sid, log_id(symbol));
|
btorf("%d state %d %s\n", nid, sid, symbol.unescape());
|
||||||
|
|
||||||
if (cell->get_bool_attribute(ID(clk2fflogic)))
|
if (cell->get_bool_attribute(ID(clk2fflogic)))
|
||||||
ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output
|
ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output
|
||||||
|
|
@ -804,12 +804,12 @@ struct BtorWorker
|
||||||
|
|
||||||
if (asyncwr && syncwr)
|
if (asyncwr && syncwr)
|
||||||
log_error("Memory %s.%s has mixed async/sync write ports.\n",
|
log_error("Memory %s.%s has mixed async/sync write ports.\n",
|
||||||
log_id(module), log_id(mem->memid));
|
module, mem->memid.unescape());
|
||||||
|
|
||||||
for (auto &port : mem->rd_ports) {
|
for (auto &port : mem->rd_ports) {
|
||||||
if (port.clk_enable)
|
if (port.clk_enable)
|
||||||
log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n",
|
log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n",
|
||||||
log_id(module), log_id(mem->memid));
|
module, mem->memid.unescape());
|
||||||
}
|
}
|
||||||
|
|
||||||
int data_sid = get_bv_sid(mem->width);
|
int data_sid = get_bv_sid(mem->width);
|
||||||
|
|
@ -871,7 +871,7 @@ struct BtorWorker
|
||||||
if (mem->memid[0] == '$')
|
if (mem->memid[0] == '$')
|
||||||
btorf("%d state %d\n", nid, sid);
|
btorf("%d state %d\n", nid, sid);
|
||||||
else
|
else
|
||||||
btorf("%d state %d %s\n", nid, sid, log_id(mem->memid));
|
btorf("%d state %d %s\n", nid, sid, mem->memid.unescape());
|
||||||
|
|
||||||
ywmap_state(cell);
|
ywmap_state(cell);
|
||||||
|
|
||||||
|
|
@ -948,21 +948,20 @@ struct BtorWorker
|
||||||
|
|
||||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
|
|
||||||
okay:
|
okay:
|
||||||
btorf_pop(log_id(cell));
|
btorf_pop(cell->name.unescape());
|
||||||
cell_recursion_guard.erase(cell);
|
cell_recursion_guard.erase(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1167,7 +1166,7 @@ struct BtorWorker
|
||||||
f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename)
|
f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename)
|
||||||
{
|
{
|
||||||
if (!info_filename.empty())
|
if (!info_filename.empty())
|
||||||
infof("name %s\n", log_id(module));
|
infof("name %s\n", module);
|
||||||
|
|
||||||
if (!ywmap_filename.empty())
|
if (!ywmap_filename.empty())
|
||||||
ywmap_json.write_to_file(ywmap_filename);
|
ywmap_json.write_to_file(ywmap_filename);
|
||||||
|
|
@ -1257,19 +1256,19 @@ struct BtorWorker
|
||||||
if (!wire->port_id || !wire->port_output)
|
if (!wire->port_id || !wire->port_output)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
btorf_push(stringf("output %s", log_id(wire)));
|
btorf_push(stringf("output %s", wire));
|
||||||
|
|
||||||
int nid = get_sig_nid(wire);
|
int nid = get_sig_nid(wire);
|
||||||
btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire));
|
btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire));
|
||||||
|
|
||||||
btorf_pop(stringf("output %s", log_id(wire)));
|
btorf_pop(stringf("output %s", wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
{
|
||||||
if (cell->type == ID($assume))
|
if (cell->type == ID($assume))
|
||||||
{
|
{
|
||||||
btorf_push(log_id(cell));
|
btorf_push(cell->name.unescape());
|
||||||
|
|
||||||
int sid = get_bv_sid(1);
|
int sid = get_bv_sid(1);
|
||||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||||
|
|
@ -1284,12 +1283,12 @@ struct BtorWorker
|
||||||
|
|
||||||
if (ywmap_json.active()) ywmap_assumes.emplace_back(cell);
|
if (ywmap_json.active()) ywmap_assumes.emplace_back(cell);
|
||||||
|
|
||||||
btorf_pop(log_id(cell));
|
btorf_pop(cell->name.unescape());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($assert))
|
if (cell->type == ID($assert))
|
||||||
{
|
{
|
||||||
btorf_push(log_id(cell));
|
btorf_push(cell->name.unescape());
|
||||||
|
|
||||||
int sid = get_bv_sid(1);
|
int sid = get_bv_sid(1);
|
||||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||||
|
|
@ -1313,12 +1312,12 @@ struct BtorWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btorf_pop(log_id(cell));
|
btorf_pop(cell->name.unescape());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($cover) && cover_mode)
|
if (cell->type == ID($cover) && cover_mode)
|
||||||
{
|
{
|
||||||
btorf_push(log_id(cell));
|
btorf_push(cell->name.unescape());
|
||||||
|
|
||||||
int sid = get_bv_sid(1);
|
int sid = get_bv_sid(1);
|
||||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||||
|
|
@ -1334,7 +1333,7 @@ struct BtorWorker
|
||||||
btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true));
|
btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
btorf_pop(log_id(cell));
|
btorf_pop(cell->name.unescape());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1343,7 +1342,7 @@ struct BtorWorker
|
||||||
if (wire->port_id || wire->name[0] == '$')
|
if (wire->port_id || wire->name[0] == '$')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
btorf_push(stringf("wire %s", log_id(wire)));
|
btorf_push(stringf("wire %s", wire));
|
||||||
|
|
||||||
int sid = get_bv_sid(GetSize(wire));
|
int sid = get_bv_sid(GetSize(wire));
|
||||||
int nid = get_sig_nid(sigmap(wire));
|
int nid = get_sig_nid(sigmap(wire));
|
||||||
|
|
@ -1356,7 +1355,7 @@ struct BtorWorker
|
||||||
if (info_clocks.count(nid))
|
if (info_clocks.count(nid))
|
||||||
info_clocks[this_nid] |= info_clocks[nid];
|
info_clocks[this_nid] |= info_clocks[nid];
|
||||||
|
|
||||||
btorf_pop(stringf("wire %s", log_id(wire)));
|
btorf_pop(stringf("wire %s", wire));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1370,14 +1369,14 @@ struct BtorWorker
|
||||||
int nid = it.first;
|
int nid = it.first;
|
||||||
Cell *cell = it.second;
|
Cell *cell = it.second;
|
||||||
|
|
||||||
btorf_push(stringf("next %s", log_id(cell)));
|
btorf_push(stringf("next %s", cell));
|
||||||
|
|
||||||
SigSpec sig = sigmap(cell->getPort(ID::D));
|
SigSpec sig = sigmap(cell->getPort(ID::D));
|
||||||
int nid_q = get_sig_nid(sig);
|
int nid_q = get_sig_nid(sig);
|
||||||
int sid = get_bv_sid(GetSize(sig));
|
int sid = get_bv_sid(GetSize(sig));
|
||||||
btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell));
|
btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell));
|
||||||
|
|
||||||
btorf_pop(stringf("next %s", log_id(cell)));
|
btorf_pop(stringf("next %s", cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<int, Mem*>> mtodo;
|
vector<pair<int, Mem*>> mtodo;
|
||||||
|
|
@ -1388,7 +1387,7 @@ struct BtorWorker
|
||||||
int nid = it.first;
|
int nid = it.first;
|
||||||
Mem *mem = it.second;
|
Mem *mem = it.second;
|
||||||
|
|
||||||
btorf_push(stringf("next %s", log_id(mem->memid)));
|
btorf_push(stringf("next %s", mem->memid.unescape()));
|
||||||
|
|
||||||
int abits = ceil_log2(mem->size);
|
int abits = ceil_log2(mem->size);
|
||||||
|
|
||||||
|
|
@ -1436,7 +1435,7 @@ struct BtorWorker
|
||||||
int nid2 = next_nid++;
|
int nid2 = next_nid++;
|
||||||
btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem)));
|
btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem)));
|
||||||
|
|
||||||
btorf_pop(stringf("next %s", log_id(mem->memid)));
|
btorf_pop(stringf("next %s", mem->memid.unescape()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1630,7 +1629,7 @@ struct BtorBackend : public Backend {
|
||||||
log_cmd_error("No top module found.\n");
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
*f << stringf("; BTOR description generated by %s for module %s.\n",
|
*f << stringf("; BTOR description generated by %s for module %s.\n",
|
||||||
yosys_maybe_version(), log_id(topmod));
|
yosys_maybe_version(), topmod);
|
||||||
|
|
||||||
BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename);
|
BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
yosys_backend(cxxrtl
|
||||||
|
cxxrtl_backend.cc
|
||||||
|
DATA_DIR
|
||||||
|
include/backends/cxxrtl
|
||||||
|
DATA_FILES
|
||||||
|
runtime/README.txt
|
||||||
|
runtime/cxxrtl/cxxrtl.h
|
||||||
|
runtime/cxxrtl/cxxrtl_vcd.h
|
||||||
|
runtime/cxxrtl/cxxrtl_time.h
|
||||||
|
runtime/cxxrtl/cxxrtl_replay.h
|
||||||
|
runtime/cxxrtl/capi/cxxrtl_capi.cc
|
||||||
|
runtime/cxxrtl/capi/cxxrtl_capi.h
|
||||||
|
runtime/cxxrtl/capi/cxxrtl_capi_vcd.cc
|
||||||
|
runtime/cxxrtl/capi/cxxrtl_capi_vcd.h
|
||||||
|
REQUIRES
|
||||||
|
hierarchy
|
||||||
|
flatten
|
||||||
|
proc
|
||||||
|
)
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/cxxrtl/cxxrtl_backend.o
|
|
||||||
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl.h))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_vcd.h))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_time.h))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_replay.h))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.cc))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi_vcd.cc))
|
|
||||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi_vcd.h))
|
|
||||||
|
|
@ -251,7 +251,7 @@ CxxrtlPortType cxxrtl_port_type(RTLIL::Module *module, RTLIL::IdString port)
|
||||||
bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync));
|
bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync));
|
||||||
if (is_comb && is_sync)
|
if (is_comb && is_sync)
|
||||||
log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n",
|
log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n",
|
||||||
log_id(module), log_signal(output_wire));
|
module, log_signal(output_wire));
|
||||||
else if (is_comb)
|
else if (is_comb)
|
||||||
return CxxrtlPortType::COMB;
|
return CxxrtlPortType::COMB;
|
||||||
else if (is_sync)
|
else if (is_sync)
|
||||||
|
|
@ -756,7 +756,7 @@ struct CxxrtlWorker {
|
||||||
// 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`.
|
// 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`.
|
||||||
// 2. An underscore is escaped with another underscore, i.e. `__`.
|
// 2. An underscore is escaped with another underscore, i.e. `__`.
|
||||||
// 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`.
|
// 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`.
|
||||||
std::string mangle_name(const RTLIL::IdString &name)
|
std::string mangle_name(RTLIL::IdString name)
|
||||||
{
|
{
|
||||||
std::string mangled;
|
std::string mangled;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
@ -786,7 +786,7 @@ struct CxxrtlWorker {
|
||||||
return mangled;
|
return mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mangle_module_name(const RTLIL::IdString &name, bool is_blackbox = false)
|
std::string mangle_module_name(RTLIL::IdString name, bool is_blackbox = false)
|
||||||
{
|
{
|
||||||
// Class namespace.
|
// Class namespace.
|
||||||
if (is_blackbox)
|
if (is_blackbox)
|
||||||
|
|
@ -794,19 +794,19 @@ struct CxxrtlWorker {
|
||||||
return mangle_name(name);
|
return mangle_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mangle_memory_name(const RTLIL::IdString &name)
|
std::string mangle_memory_name(RTLIL::IdString name)
|
||||||
{
|
{
|
||||||
// Class member namespace.
|
// Class member namespace.
|
||||||
return "memory_" + mangle_name(name);
|
return "memory_" + mangle_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mangle_cell_name(const RTLIL::IdString &name)
|
std::string mangle_cell_name(RTLIL::IdString name)
|
||||||
{
|
{
|
||||||
// Class member namespace.
|
// Class member namespace.
|
||||||
return "cell_" + mangle_name(name);
|
return "cell_" + mangle_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mangle_wire_name(const RTLIL::IdString &name)
|
std::string mangle_wire_name(RTLIL::IdString name)
|
||||||
{
|
{
|
||||||
// Class member namespace.
|
// Class member namespace.
|
||||||
return mangle_name(name);
|
return mangle_name(name);
|
||||||
|
|
@ -851,7 +851,7 @@ struct CxxrtlWorker {
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(module->attributes.at(ID(cxxrtl_template)).flags & RTLIL::CONST_FLAG_STRING))
|
if (!(module->attributes.at(ID(cxxrtl_template)).flags & RTLIL::CONST_FLAG_STRING))
|
||||||
log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module));
|
log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", module);
|
||||||
|
|
||||||
std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
|
std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
|
||||||
for (const auto ¶m_name : param_names) {
|
for (const auto ¶m_name : param_names) {
|
||||||
|
|
@ -861,7 +861,7 @@ struct CxxrtlWorker {
|
||||||
if (!isupper(param_name[0]))
|
if (!isupper(param_name[0]))
|
||||||
log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', "
|
log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', "
|
||||||
"which does not start with an uppercase letter.\n",
|
"which does not start with an uppercase letter.\n",
|
||||||
log_id(module), param_name.c_str());
|
module, param_name.c_str());
|
||||||
}
|
}
|
||||||
return param_names;
|
return param_names;
|
||||||
}
|
}
|
||||||
|
|
@ -907,12 +907,12 @@ struct CxxrtlWorker {
|
||||||
RTLIL::IdString id_param_name = '\\' + param_name;
|
RTLIL::IdString id_param_name = '\\' + param_name;
|
||||||
if (!cell->hasParam(id_param_name))
|
if (!cell->hasParam(id_param_name))
|
||||||
log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n",
|
log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n",
|
||||||
log_id(cell->module), log_id(cell), param_name.c_str(), log_id(cell_module));
|
cell->module, cell, param_name.c_str(), cell_module);
|
||||||
RTLIL::Const param_value = cell->getParam(id_param_name);
|
RTLIL::Const param_value = cell->getParam(id_param_name);
|
||||||
if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0)
|
if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0)
|
||||||
log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', "
|
log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', "
|
||||||
"is not a positive integer.\n",
|
"is not a positive integer.\n",
|
||||||
param_name.c_str(), log_id(cell->module), log_id(cell), log_id(cell_module));
|
param_name.c_str(), cell->module, cell, cell_module);
|
||||||
params += std::to_string(cell->getParam(id_param_name).as_int());
|
params += std::to_string(cell->getParam(id_param_name).as_int());
|
||||||
}
|
}
|
||||||
params += ">";
|
params += ">";
|
||||||
|
|
@ -2576,7 +2576,7 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
dec_indent();
|
dec_indent();
|
||||||
|
|
||||||
log_debug("Debug information statistics for module `%s':\n", log_id(module));
|
log_debug("Debug information statistics for module `%s':\n", module);
|
||||||
log_debug(" Scopes: %zu", count_scopes);
|
log_debug(" Scopes: %zu", count_scopes);
|
||||||
log_debug(" Public wires: %zu, of which:\n", count_public_wires);
|
log_debug(" Public wires: %zu, of which:\n", count_public_wires);
|
||||||
log_debug(" Member wires: %zu, of which:\n", count_member_wires);
|
log_debug(" Member wires: %zu, of which:\n", count_member_wires);
|
||||||
|
|
@ -2776,7 +2776,8 @@ struct CxxrtlWorker {
|
||||||
{
|
{
|
||||||
RTLIL::Module *top_module = nullptr;
|
RTLIL::Module *top_module = nullptr;
|
||||||
std::vector<RTLIL::Module*> modules;
|
std::vector<RTLIL::Module*> modules;
|
||||||
TopoSort<RTLIL::Module*> topo_design;
|
using Order = IdString::compare_ptr_by_name<RTLIL::NamedObject>;
|
||||||
|
TopoSort<RTLIL::Module*, Order> topo_design;
|
||||||
for (auto module : design->modules()) {
|
for (auto module : design->modules()) {
|
||||||
if (!design->selected_module(module))
|
if (!design->selected_module(module))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2939,7 +2940,7 @@ struct CxxrtlWorker {
|
||||||
RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];
|
RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];
|
||||||
if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire))
|
if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire))
|
||||||
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n",
|
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n",
|
||||||
log_id(module), log_signal(wire));
|
module, log_signal(wire));
|
||||||
|
|
||||||
std::string edges = wire->get_string_attribute(ID(cxxrtl_edge));
|
std::string edges = wire->get_string_attribute(ID(cxxrtl_edge));
|
||||||
for (int i = 0; i < GetSize(wire); i++) {
|
for (int i = 0; i < GetSize(wire); i++) {
|
||||||
|
|
@ -2952,7 +2953,7 @@ struct CxxrtlWorker {
|
||||||
default:
|
default:
|
||||||
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers "
|
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers "
|
||||||
"other than '-', 'p', 'n', or 'a'.\n",
|
"other than '-', 'p', 'n', or 'a'.\n",
|
||||||
log_id(module), log_signal(wire));
|
module, log_signal(wire));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2977,7 +2978,7 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
if (!cell->known())
|
if (!cell->known())
|
||||||
log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type));
|
log_cmd_error("Unknown cell `%s'.\n", cell->type.unescape());
|
||||||
|
|
||||||
if (cell->is_mem_cell())
|
if (cell->is_mem_cell())
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2986,7 +2987,7 @@ struct CxxrtlWorker {
|
||||||
if (cell_module &&
|
if (cell_module &&
|
||||||
cell_module->get_blackbox_attribute() &&
|
cell_module->get_blackbox_attribute() &&
|
||||||
!cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
|
!cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
|
||||||
log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type));
|
log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", cell->type.unescape());
|
||||||
|
|
||||||
if (cell_module &&
|
if (cell_module &&
|
||||||
cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) &&
|
cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) &&
|
||||||
|
|
@ -3115,9 +3116,9 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
if (!feedback_wires.empty()) {
|
if (!feedback_wires.empty()) {
|
||||||
has_feedback_arcs = true;
|
has_feedback_arcs = true;
|
||||||
log("Module `%s' contains feedback arcs through wires:\n", log_id(module));
|
log("Module `%s' contains feedback arcs through wires:\n", module);
|
||||||
for (auto wire : feedback_wires)
|
for (auto wire : feedback_wires)
|
||||||
log(" %s\n", log_id(wire));
|
log(" %s\n", wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment
|
// Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment
|
||||||
|
|
@ -3188,7 +3189,7 @@ struct CxxrtlWorker {
|
||||||
if (wire->name.isPublic() && !inline_public) continue;
|
if (wire->name.isPublic() && !inline_public) continue;
|
||||||
if (flow.is_inlinable(wire, live_wires[wire])) {
|
if (flow.is_inlinable(wire, live_wires[wire])) {
|
||||||
if (flow.wire_comb_defs[wire].size() > 1)
|
if (flow.wire_comb_defs[wire].size() > 1)
|
||||||
log_cmd_error("Wire %s.%s has multiple drivers!\n", log_id(module), log_id(wire));
|
log_cmd_error("Wire %s.%s has multiple drivers!\n", module, wire);
|
||||||
log_assert(flow.wire_comb_defs[wire].size() == 1);
|
log_assert(flow.wire_comb_defs[wire].size() == 1);
|
||||||
FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin();
|
FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin();
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
@ -3236,9 +3237,9 @@ struct CxxrtlWorker {
|
||||||
buffered_comb_wires.insert(wire);
|
buffered_comb_wires.insert(wire);
|
||||||
if (!buffered_comb_wires.empty()) {
|
if (!buffered_comb_wires.empty()) {
|
||||||
has_buffered_comb_wires = true;
|
has_buffered_comb_wires = true;
|
||||||
log("Module `%s' contains buffered combinatorial wires:\n", log_id(module));
|
log("Module `%s' contains buffered combinatorial wires:\n", module);
|
||||||
for (auto wire : buffered_comb_wires)
|
for (auto wire : buffered_comb_wires)
|
||||||
log(" %s\n", log_id(wire));
|
log(" %s\n", wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record whether eval() requires only one delta cycle in this module.
|
// Record whether eval() requires only one delta cycle in this module.
|
||||||
|
|
@ -3419,7 +3420,7 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
if (!design->selected_whole_module(module))
|
if (!design->selected_whole_module(module))
|
||||||
if (design->selected_module(module))
|
if (design->selected_module(module))
|
||||||
log_cmd_error("Can't handle partially selected module `%s'!\n", id2cstr(module->name));
|
log_cmd_error("Can't handle partially selected module `%s'!\n", module);
|
||||||
if (!design->selected_module(module))
|
if (!design->selected_module(module))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ struct value : public expr_base<value<Bits>> {
|
||||||
int64_t divisor_shift = divisor.ctlz() - dividend.ctlz();
|
int64_t divisor_shift = divisor.ctlz() - dividend.ctlz();
|
||||||
assert(divisor_shift >= 0);
|
assert(divisor_shift >= 0);
|
||||||
divisor = divisor.shl(value<Bits>{(chunk::type) divisor_shift});
|
divisor = divisor.shl(value<Bits>{(chunk::type) divisor_shift});
|
||||||
for (size_t step = 0; step <= divisor_shift; step++) {
|
for (size_t step = 0; step <= (uint64_t) divisor_shift; step++) {
|
||||||
quotient = quotient.shl(value<Bits>{1u});
|
quotient = quotient.shl(value<Bits>{1u});
|
||||||
if (!dividend.ucmp(divisor)) {
|
if (!dividend.ucmp(divisor)) {
|
||||||
dividend = dividend.sub(divisor);
|
dividend = dividend.sub(divisor);
|
||||||
|
|
@ -1119,7 +1119,7 @@ struct fmt_part {
|
||||||
|
|
||||||
case STRING: {
|
case STRING: {
|
||||||
buf.reserve(Bits/8);
|
buf.reserve(Bits/8);
|
||||||
for (int i = 0; i < Bits; i += 8) {
|
for (size_t i = 0; i < Bits; i += 8) {
|
||||||
char ch = 0;
|
char ch = 0;
|
||||||
for (int j = 0; j < 8 && i + j < int(Bits); j++)
|
for (int j = 0; j < 8 && i + j < int(Bits); j++)
|
||||||
if (val.bit(i + j))
|
if (val.bit(i + j))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(edif
|
||||||
|
edif.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/edif/edif.o
|
|
||||||
|
|
||||||
|
|
@ -23,16 +23,18 @@
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true)
|
#define EDIF_DEF(_id) edif_names(_id.unescape(), true)
|
||||||
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br)
|
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(_id.unescape(), true, _ren, _bl, _br)
|
||||||
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false)
|
#define EDIF_REF(_id) edif_names(_id.unescape(), false)
|
||||||
|
#define EDIF_DEF_STR(_id) edif_names(RTLIL::unescape_id(_id), true)
|
||||||
|
#define EDIF_REF_STR(_id) edif_names(RTLIL::unescape_id(_id), false)
|
||||||
|
|
||||||
struct EdifNames
|
struct EdifNames
|
||||||
{
|
{
|
||||||
|
|
@ -138,7 +140,7 @@ struct EdifBackend : public Backend {
|
||||||
bool lsbidx = false;
|
bool lsbidx = false;
|
||||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||||
bool nogndvcc = false, gndvccy = false, keepmode = false;
|
bool nogndvcc = false, gndvccy = false, keepmode = false;
|
||||||
CellTypes ct(design);
|
NewCellTypes ct(design);
|
||||||
EdifNames edif_names;
|
EdifNames edif_names;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
|
|
@ -207,9 +209,9 @@ struct EdifBackend : public Backend {
|
||||||
top_module_name = module->name.str();
|
top_module_name = module->name.str();
|
||||||
|
|
||||||
if (module->processes.size() != 0)
|
if (module->processes.size() != 0)
|
||||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name));
|
log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", module->name.unescape());
|
||||||
if (module->memories.size() != 0)
|
if (module->memories.size() != 0)
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", module->name.unescape());
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
{
|
||||||
|
|
@ -227,7 +229,7 @@ struct EdifBackend : public Backend {
|
||||||
if (top_module_name.empty())
|
if (top_module_name.empty())
|
||||||
log_error("No module found in design!\n");
|
log_error("No module found in design!\n");
|
||||||
|
|
||||||
*f << stringf("(edif %s\n", EDIF_DEF(top_module_name));
|
*f << stringf("(edif %s\n", EDIF_DEF_STR(top_module_name));
|
||||||
*f << stringf(" (edifVersion 2 0 0)\n");
|
*f << stringf(" (edifVersion 2 0 0)\n");
|
||||||
*f << stringf(" (edifLevel 0)\n");
|
*f << stringf(" (edifLevel 0)\n");
|
||||||
*f << stringf(" (keywordMap (keywordLevel 0))\n");
|
*f << stringf(" (keywordMap (keywordLevel 0))\n");
|
||||||
|
|
@ -317,12 +319,12 @@ struct EdifBackend : public Backend {
|
||||||
for (auto &dep : it.second)
|
for (auto &dep : it.second)
|
||||||
if (module_deps.count(dep) > 0)
|
if (module_deps.count(dep) > 0)
|
||||||
goto not_ready_yet;
|
goto not_ready_yet;
|
||||||
// log("Next in topological sort: %s\n", log_id(it.first->name));
|
// log("Next in topological sort: %s\n", it.first->name.unescape());
|
||||||
sorted_modules.push_back(it.first);
|
sorted_modules.push_back(it.first);
|
||||||
not_ready_yet:;
|
not_ready_yet:;
|
||||||
}
|
}
|
||||||
if (sorted_modules_idx == sorted_modules.size())
|
if (sorted_modules_idx == sorted_modules.size())
|
||||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name));
|
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape());
|
||||||
while (sorted_modules_idx < sorted_modules.size())
|
while (sorted_modules_idx < sorted_modules.size())
|
||||||
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +488,7 @@ struct EdifBackend : public Backend {
|
||||||
for (int i = 0; i < GetSize(sig); i++)
|
for (int i = 0; i < GetSize(sig); i++)
|
||||||
if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1)
|
if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1)
|
||||||
log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n",
|
log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n",
|
||||||
i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i]));
|
i, module, cell, p.first.unescape(), log_signal(sig[i]));
|
||||||
else {
|
else {
|
||||||
int member_idx = lsbidx ? i : GetSize(sig)-i-1;
|
int member_idx = lsbidx ? i : GetSize(sig)-i-1;
|
||||||
auto m = design->module(cell->type);
|
auto m = design->module(cell->type);
|
||||||
|
|
@ -534,7 +536,7 @@ struct EdifBackend : public Backend {
|
||||||
if (netname[i] == ' ' || netname[i] == '\\')
|
if (netname[i] == ' ' || netname[i] == '\\')
|
||||||
netname.erase(netname.begin() + i--);
|
netname.erase(netname.begin() + i--);
|
||||||
}
|
}
|
||||||
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
|
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
|
||||||
for (auto &ref : it.second)
|
for (auto &ref : it.second)
|
||||||
*f << stringf(" %s\n", ref.first);
|
*f << stringf(" %s\n", ref.first);
|
||||||
if (sig.wire == NULL) {
|
if (sig.wire == NULL) {
|
||||||
|
|
@ -572,7 +574,7 @@ struct EdifBackend : public Backend {
|
||||||
|
|
||||||
if (keepmode)
|
if (keepmode)
|
||||||
{
|
{
|
||||||
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
|
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
|
||||||
|
|
||||||
auto &refs = net_join_db.at(mapped_sig);
|
auto &refs = net_join_db.at(mapped_sig);
|
||||||
for (auto &ref : refs)
|
for (auto &ref : refs)
|
||||||
|
|
@ -588,7 +590,7 @@ struct EdifBackend : public Backend {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname));
|
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF_STR(netname));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -599,8 +601,8 @@ struct EdifBackend : public Backend {
|
||||||
}
|
}
|
||||||
*f << stringf(" )\n");
|
*f << stringf(" )\n");
|
||||||
|
|
||||||
*f << stringf(" (design %s\n", EDIF_DEF(top_module_name));
|
*f << stringf(" (design %s\n", EDIF_DEF_STR(top_module_name));
|
||||||
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name));
|
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF_STR(top_module_name));
|
||||||
*f << stringf(" )\n");
|
*f << stringf(" )\n");
|
||||||
|
|
||||||
*f << stringf(")\n");
|
*f << stringf(")\n");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
yosys_backend(firrtl
|
||||||
|
firrtl.cc
|
||||||
|
REQUIRES
|
||||||
|
pmuxtree
|
||||||
|
bmuxmap
|
||||||
|
demuxmap
|
||||||
|
bwmuxmap
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/firrtl/firrtl.o
|
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ const char *make_id(IdString id)
|
||||||
if (namecache.count(id) != 0)
|
if (namecache.count(id) != 0)
|
||||||
return namecache.at(id).c_str();
|
return namecache.at(id).c_str();
|
||||||
|
|
||||||
string new_id = log_id(id);
|
string new_id = id.unescape();
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(new_id); i++)
|
for (int i = 0; i < GetSize(new_id); i++)
|
||||||
{
|
{
|
||||||
|
|
@ -263,7 +263,7 @@ void emit_extmodule(RTLIL::Cell *cell, RTLIL::Module *mod_instance, std::ostream
|
||||||
|
|
||||||
if (wire->port_input && wire->port_output)
|
if (wire->port_input && wire->port_output)
|
||||||
{
|
{
|
||||||
log_error("Module port %s.%s is inout!\n", log_id(mod_instance), log_id(wire));
|
log_error("Module port %s.%s is inout!\n", mod_instance, wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n",
|
const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n",
|
||||||
|
|
@ -559,12 +559,12 @@ struct FirrtlWorker
|
||||||
if (wire->attributes.count(ID::init)) {
|
if (wire->attributes.count(ID::init)) {
|
||||||
log_warning("Initial value (%s) for (%s.%s) not supported\n",
|
log_warning("Initial value (%s) for (%s.%s) not supported\n",
|
||||||
wire->attributes.at(ID::init).as_string().c_str(),
|
wire->attributes.at(ID::init).as_string().c_str(),
|
||||||
log_id(module), log_id(wire));
|
module, wire);
|
||||||
}
|
}
|
||||||
if (wire->port_id)
|
if (wire->port_id)
|
||||||
{
|
{
|
||||||
if (wire->port_input && wire->port_output)
|
if (wire->port_input && wire->port_output)
|
||||||
log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
|
log_error("Module port %s.%s is inout!\n", module, wire);
|
||||||
port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output",
|
port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output",
|
||||||
wireName, wire->width, wireFileinfo.c_str()));
|
wireName, wire->width, wireFileinfo.c_str()));
|
||||||
}
|
}
|
||||||
|
|
@ -833,7 +833,7 @@ struct FirrtlWorker
|
||||||
primop = "shl";
|
primop = "shl";
|
||||||
int shiftAmount = b_sig.as_int();
|
int shiftAmount = b_sig.as_int();
|
||||||
if (shiftAmount < 0) {
|
if (shiftAmount < 0) {
|
||||||
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell));
|
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, module, cell);
|
||||||
}
|
}
|
||||||
b_expr = std::to_string(shiftAmount);
|
b_expr = std::to_string(shiftAmount);
|
||||||
firrtl_width = a_width + shiftAmount;
|
firrtl_width = a_width + shiftAmount;
|
||||||
|
|
@ -844,7 +844,7 @@ struct FirrtlWorker
|
||||||
firrtl_width = a_width + (1 << b_width) - 1;
|
firrtl_width = a_width + (1 << b_width) - 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell));
|
log_error("Non power 2: %s.%s\n", module, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -905,7 +905,7 @@ struct FirrtlWorker
|
||||||
{
|
{
|
||||||
bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool();
|
bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool();
|
||||||
if (clkpol == false)
|
if (clkpol == false)
|
||||||
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
|
log_error("Negative edge clock on FF %s.%s.\n", module, cell);
|
||||||
|
|
||||||
int width = cell->parameters.at(ID::WIDTH).as_int();
|
int width = cell->parameters.at(ID::WIDTH).as_int();
|
||||||
string expr = make_expr(cell->getPort(ID::D));
|
string expr = make_expr(cell->getPort(ID::D));
|
||||||
|
|
@ -983,7 +983,7 @@ struct FirrtlWorker
|
||||||
|
|
||||||
if (cell->type == ID($scopeinfo))
|
if (cell->type == ID($scopeinfo))
|
||||||
continue;
|
continue;
|
||||||
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
|
log_error("Cell type not supported: %s (%s.%s)\n", cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &mem : memories) {
|
for (auto &mem : memories) {
|
||||||
|
|
@ -991,10 +991,10 @@ struct FirrtlWorker
|
||||||
|
|
||||||
Const init_data = mem.get_init_data();
|
Const init_data = mem.get_init_data();
|
||||||
if (!init_data.is_fully_undef())
|
if (!init_data.is_fully_undef())
|
||||||
log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(mem.memid));
|
log_error("Memory with initialization data: %s.%s\n", module, mem.memid.unescape());
|
||||||
|
|
||||||
if (mem.start_offset != 0)
|
if (mem.start_offset != 0)
|
||||||
log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(mem.memid));
|
log_error("Memory with nonzero offset: %s.%s\n", module, mem.memid.unescape());
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(mem.rd_ports); i++)
|
for (int i = 0; i < GetSize(mem.rd_ports); i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1002,7 +1002,7 @@ struct FirrtlWorker
|
||||||
string port_name(stringf("%s.r%d", mem_id, i));
|
string port_name(stringf("%s.r%d", mem_id, i));
|
||||||
|
|
||||||
if (port.clk_enable)
|
if (port.clk_enable)
|
||||||
log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
log_error("Clocked read port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||||
|
|
||||||
std::ostringstream rpe;
|
std::ostringstream rpe;
|
||||||
|
|
||||||
|
|
@ -1023,12 +1023,12 @@ struct FirrtlWorker
|
||||||
string port_name(stringf("%s.w%d", mem_id, i));
|
string port_name(stringf("%s.w%d", mem_id, i));
|
||||||
|
|
||||||
if (!port.clk_enable)
|
if (!port.clk_enable)
|
||||||
log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
log_error("Unclocked write port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||||
if (!port.clk_polarity)
|
if (!port.clk_polarity)
|
||||||
log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
log_error("Negedge write port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||||
for (int i = 1; i < GetSize(port.en); i++)
|
for (int i = 1; i < GetSize(port.en); i++)
|
||||||
if (port.en[0] != port.en[i])
|
if (port.en[0] != port.en[i])
|
||||||
log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
log_error("Complex write enable on port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||||
|
|
||||||
std::ostringstream wpe;
|
std::ostringstream wpe;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
yosys_backend(functional_cxx
|
||||||
|
cxx.cc
|
||||||
|
)
|
||||||
|
yosys_backend(functional_smt2
|
||||||
|
smtlib.cc
|
||||||
|
)
|
||||||
|
yosys_backend(functional_rosette
|
||||||
|
smtlib_rosette.cc
|
||||||
|
)
|
||||||
|
yosys_test_pass(generic
|
||||||
|
test_generic.cc
|
||||||
|
)
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
OBJS += backends/functional/cxx.o
|
|
||||||
OBJS += backends/functional/smtlib.o
|
|
||||||
OBJS += backends/functional/smtlib_rosette.o
|
|
||||||
OBJS += backends/functional/test_generic.o
|
|
||||||
|
|
@ -89,7 +89,7 @@ struct CxxStruct {
|
||||||
}
|
}
|
||||||
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
|
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
|
||||||
for (auto p : types) {
|
for (auto p : types) {
|
||||||
f.print("\t\t\tfn(\"{}\", {});\n", RTLIL::unescape_id(p.first), scope(p.first, p.first));
|
f.print("\t\t\tfn(\"{}\", {});\n", p.first.unescape(), scope(p.first, p.first));
|
||||||
}
|
}
|
||||||
f.print("\t\t}}\n");
|
f.print("\t\t}}\n");
|
||||||
f.print("\t}};\n\n");
|
f.print("\t}};\n\n");
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ public:
|
||||||
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
|
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
|
||||||
void insert(IdString field_name, SmtSort sort) {
|
void insert(IdString field_name, SmtSort sort) {
|
||||||
field_names(field_name);
|
field_names(field_name);
|
||||||
auto accessor = scope.unique_name("\\" + name + "_" + RTLIL::unescape_id(field_name));
|
auto accessor = scope.unique_name("\\" + name + "_" + field_name.unescape());
|
||||||
fields.emplace_back(Field{sort, accessor});
|
fields.emplace_back(Field{sort, accessor});
|
||||||
}
|
}
|
||||||
void write_definition(SExprWriter &w) {
|
void write_definition(SExprWriter &w) {
|
||||||
|
|
@ -99,7 +99,7 @@ public:
|
||||||
w.open(list(name));
|
w.open(list(name));
|
||||||
for(auto field_name : field_names) {
|
for(auto field_name : field_names) {
|
||||||
w << fn(field_name);
|
w << fn(field_name);
|
||||||
w.comment(RTLIL::unescape_id(field_name), true);
|
w.comment(field_name.unescape(), true);
|
||||||
}
|
}
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ public:
|
||||||
w.open(list(name));
|
w.open(list(name));
|
||||||
for(auto field_name : field_names) {
|
for(auto field_name : field_names) {
|
||||||
w << fn(field_name);
|
w << fn(field_name);
|
||||||
w.comment(RTLIL::unescape_id(field_name), true);
|
w.comment(field_name.unescape(), true);
|
||||||
}
|
}
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
|
|
@ -188,20 +188,27 @@ struct SmtrModule {
|
||||||
Functional::IR ir;
|
Functional::IR ir;
|
||||||
SmtrScope scope;
|
SmtrScope scope;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
bool use_assoc_list_helpers;
|
||||||
|
std::optional<std::string> input_helper_name;
|
||||||
|
std::optional<std::string> output_helper_name;
|
||||||
|
|
||||||
SmtrStruct input_struct;
|
SmtrStruct input_struct;
|
||||||
SmtrStruct output_struct;
|
SmtrStruct output_struct;
|
||||||
SmtrStruct state_struct;
|
SmtrStruct state_struct;
|
||||||
|
|
||||||
SmtrModule(Module *module)
|
SmtrModule(Module *module, bool assoc_list_helpers)
|
||||||
: ir(Functional::IR::from_module(module))
|
: ir(Functional::IR::from_module(module)), scope(), name(scope.unique_name(module->name)), use_assoc_list_helpers(assoc_list_helpers),
|
||||||
, scope()
|
input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope),
|
||||||
, name(scope.unique_name(module->name))
|
output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope),
|
||||||
, input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope)
|
state_struct(scope.unique_name(module->name.str() + "_State"), scope)
|
||||||
, output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope)
|
|
||||||
, state_struct(scope.unique_name(module->name.str() + "_State"), scope)
|
|
||||||
{
|
{
|
||||||
scope.reserve(name + "_initial");
|
scope.reserve(name + "_initial");
|
||||||
|
if (assoc_list_helpers) {
|
||||||
|
input_helper_name = scope.unique_name(module->name.str() + "_inputs_helper");
|
||||||
|
scope.reserve(*input_helper_name);
|
||||||
|
output_helper_name = scope.unique_name(module->name.str() + "_outputs_helper");
|
||||||
|
scope.reserve(*output_helper_name);
|
||||||
|
}
|
||||||
for (auto input : ir.inputs())
|
for (auto input : ir.inputs())
|
||||||
input_struct.insert(input->name, input->sort);
|
input_struct.insert(input->name, input->sort);
|
||||||
for (auto output : ir.outputs())
|
for (auto output : ir.outputs())
|
||||||
|
|
@ -257,6 +264,45 @@ struct SmtrModule {
|
||||||
w.pop();
|
w.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_assoc_list_helpers(SExprWriter &w)
|
||||||
|
{
|
||||||
|
log_assert(output_helper_name && input_helper_name);
|
||||||
|
|
||||||
|
// Input struct keyword-based constructor.
|
||||||
|
w.push();
|
||||||
|
w.open(list("define"));
|
||||||
|
const auto inputs_name = "inputs";
|
||||||
|
w.open(list(*input_helper_name, inputs_name));
|
||||||
|
w.close();
|
||||||
|
w.open(list(input_struct.name));
|
||||||
|
for (auto input : ir.inputs()) {
|
||||||
|
w.push();
|
||||||
|
w.open(list("let"));
|
||||||
|
w.push();
|
||||||
|
w.open(list());
|
||||||
|
w.open(list("assoc-result"));
|
||||||
|
w << list("assoc", "\"" + input->name.unescape() + "\"", inputs_name);
|
||||||
|
w.pop();
|
||||||
|
w.open(list("if", "assoc-result"));
|
||||||
|
w << list("cdr", "assoc-result");
|
||||||
|
w.open(list("begin"));
|
||||||
|
w << list("fprintf", list("current-error-port"), "\"%s not found in inputs\"");
|
||||||
|
w << "'not-found";
|
||||||
|
w.pop();
|
||||||
|
}
|
||||||
|
w.pop();
|
||||||
|
// Output struct keyword-based destructuring
|
||||||
|
w.push();
|
||||||
|
w.open(list("define"));
|
||||||
|
const auto outputs_name = "outputs";
|
||||||
|
w << list(*output_helper_name, outputs_name);
|
||||||
|
w.open(list("list"));
|
||||||
|
for (auto output : ir.outputs()) {
|
||||||
|
w << list("cons", "\"" + output->name.unescape() + "\"", output_struct.access("outputs", output->name));
|
||||||
|
}
|
||||||
|
w.pop();
|
||||||
|
}
|
||||||
|
|
||||||
void write(std::ostream &out)
|
void write(std::ostream &out)
|
||||||
{
|
{
|
||||||
SExprWriter w(out);
|
SExprWriter w(out);
|
||||||
|
|
@ -265,6 +311,10 @@ struct SmtrModule {
|
||||||
output_struct.write_definition(w);
|
output_struct.write_definition(w);
|
||||||
state_struct.write_definition(w);
|
state_struct.write_definition(w);
|
||||||
|
|
||||||
|
if (use_assoc_list_helpers) {
|
||||||
|
write_assoc_list_helpers(w);
|
||||||
|
}
|
||||||
|
|
||||||
write_eval(w);
|
write_eval(w);
|
||||||
write_initial(w);
|
write_initial(w);
|
||||||
}
|
}
|
||||||
|
|
@ -282,12 +332,16 @@ struct FunctionalSmtrBackend : public Backend {
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -provides\n");
|
log(" -provides\n");
|
||||||
log(" include 'provide' statement(s) for loading output as a module\n");
|
log(" include 'provide' statement(s) for loading output as a module\n");
|
||||||
|
log(" -assoc-list-helpers\n");
|
||||||
|
log(" provide helper functions which convert inputs/outputs from/to association lists\n");
|
||||||
|
log(" \n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
auto provides = false;
|
auto provides = false;
|
||||||
|
auto assoc_list_helpers = false;
|
||||||
|
|
||||||
log_header(design, "Executing Functional Rosette Backend.\n");
|
log_header(design, "Executing Functional Rosette Backend.\n");
|
||||||
|
|
||||||
|
|
@ -296,6 +350,8 @@ struct FunctionalSmtrBackend : public Backend {
|
||||||
{
|
{
|
||||||
if (args[argidx] == "-provides")
|
if (args[argidx] == "-provides")
|
||||||
provides = true;
|
provides = true;
|
||||||
|
else if (args[argidx] == "-assoc-list-helpers")
|
||||||
|
assoc_list_helpers = true;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -307,8 +363,8 @@ struct FunctionalSmtrBackend : public Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto module : design->selected_modules()) {
|
for (auto module : design->selected_modules()) {
|
||||||
log("Processing module `%s`.\n", module->name);
|
log("Processing module `%s`.\n", module->name.c_str());
|
||||||
SmtrModule smtr(module);
|
SmtrModule smtr(module, assoc_list_helpers);
|
||||||
smtr.write(*f);
|
smtr.write(*f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,11 +146,11 @@ struct FunctionalTestGeneric : public Pass
|
||||||
log("Dumping module `%s'.\n", module->name);
|
log("Dumping module `%s'.\n", module->name);
|
||||||
auto fir = Functional::IR::from_module(module);
|
auto fir = Functional::IR::from_module(module);
|
||||||
for(auto node : fir)
|
for(auto node : fir)
|
||||||
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";
|
std::cout << node.name().unescape() << " = " << node.to_string([](auto n) { return n.name().unescape(); }) << "\n";
|
||||||
for(auto output : fir.all_outputs())
|
for(auto output : fir.all_outputs())
|
||||||
std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n";
|
std::cout << output->kind.unescape() << " " << output->name.unescape() << " = " << output->value().name().unescape() << "\n";
|
||||||
for(auto state : fir.all_states())
|
for(auto state : fir.all_states())
|
||||||
std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n";
|
std::cout << state->kind.unescape() << " " << state->name.unescape() << " = " << state->next_value().name().unescape() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} FunctionalCxxBackend;
|
} FunctionalCxxBackend;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(intersynth
|
||||||
|
intersynth.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/intersynth/intersynth.o
|
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
|
||||||
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
|
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
return RTLIL::unescape_id(sig.as_wire()->name);
|
return sig.as_wire()->name.unescape();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntersynthBackend : public Backend {
|
struct IntersynthBackend : public Backend {
|
||||||
|
|
@ -117,7 +117,7 @@ struct IntersynthBackend : public Backend {
|
||||||
|
|
||||||
std::set<std::string> conntypes_code, celltypes_code;
|
std::set<std::string> conntypes_code, celltypes_code;
|
||||||
std::string netlists_code;
|
std::string netlists_code;
|
||||||
CellTypes ct(design);
|
NewCellTypes ct(design);
|
||||||
|
|
||||||
for (auto lib : libs)
|
for (auto lib : libs)
|
||||||
ct.setup_design(lib);
|
ct.setup_design(lib);
|
||||||
|
|
@ -133,26 +133,26 @@ struct IntersynthBackend : public Backend {
|
||||||
|
|
||||||
if (selected && !design->selected_whole_module(module->name)) {
|
if (selected && !design->selected_whole_module(module->name)) {
|
||||||
if (design->selected_module(module->name))
|
if (design->selected_module(module->name))
|
||||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name));
|
log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log("Generating netlist %s.\n", log_id(module->name));
|
log("Generating netlist %s.\n", module->name.unescape());
|
||||||
|
|
||||||
if (module->memories.size() != 0 || module->processes.size() != 0)
|
if (module->memories.size() != 0 || module->processes.size() != 0)
|
||||||
log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n");
|
log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n");
|
||||||
|
|
||||||
std::set<std::string> constcells_code;
|
std::set<std::string> constcells_code;
|
||||||
netlists_code += stringf("# Netlist of module %s\n", log_id(module->name));
|
netlists_code += stringf("# Netlist of module %s\n", module->name.unescape());
|
||||||
netlists_code += stringf("netlist %s\n", log_id(module->name));
|
netlists_code += stringf("netlist %s\n", module->name.unescape());
|
||||||
|
|
||||||
// Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
|
// Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
if (wire->port_input || wire->port_output) {
|
if (wire->port_input || wire->port_output) {
|
||||||
celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n",
|
celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n",
|
||||||
log_id(wire->name), wire->width, wire->port_input ? "*" : "",
|
wire->name.unescape(), wire->width, wire->port_input ? "*" : "",
|
||||||
wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name)));
|
wire->port_input ? "input" : "output", wire->name.unescape(), wire->width, wire->name.unescape()));
|
||||||
netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name),
|
netlists_code += stringf("node %s %s PORT %s\n", wire->name.unescape(), wire->name.unescape(),
|
||||||
netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str());
|
netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,26 +163,26 @@ struct IntersynthBackend : public Backend {
|
||||||
std::string celltype_code, node_code;
|
std::string celltype_code, node_code;
|
||||||
|
|
||||||
if (!ct.cell_known(cell->type))
|
if (!ct.cell_known(cell->type))
|
||||||
log_error("Found unknown cell type %s in module!\n", log_id(cell->type));
|
log_error("Found unknown cell type %s in module!\n", cell->type.unescape());
|
||||||
|
|
||||||
celltype_code = stringf("celltype %s", log_id(cell->type));
|
celltype_code = stringf("celltype %s", cell->type.unescape());
|
||||||
node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type));
|
node_code = stringf("node %s %s", cell->name.unescape(), cell->type.unescape());
|
||||||
for (auto &port : cell->connections()) {
|
for (auto &port : cell->connections()) {
|
||||||
RTLIL::SigSpec sig = sigmap(port.second);
|
RTLIL::SigSpec sig = sigmap(port.second);
|
||||||
if (sig.size() != 0) {
|
if (sig.size() != 0) {
|
||||||
conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size()));
|
conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size()));
|
||||||
celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first));
|
celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", port.first.unescape());
|
||||||
node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig));
|
node_code += stringf(" %s %s", port.first.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto ¶m : cell->parameters) {
|
for (auto ¶m : cell->parameters) {
|
||||||
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first));
|
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), param.first.unescape());
|
||||||
if (param.second.size() != 32) {
|
if (param.second.size() != 32) {
|
||||||
node_code += stringf(" %s '", log_id(param.first));
|
node_code += stringf(" %s '", param.first.unescape());
|
||||||
for (int i = param.second.size()-1; i >= 0; i--)
|
for (int i = param.second.size()-1; i >= 0; i--)
|
||||||
node_code += param.second[i] == State::S1 ? "1" : "0";
|
node_code += param.second[i] == State::S1 ? "1" : "0";
|
||||||
} else
|
} else
|
||||||
node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int());
|
node_code += stringf(" %s 0x%x", param.first.unescape(), param.second.as_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
celltypes_code.insert(celltype_code + "\n");
|
celltypes_code.insert(celltype_code + "\n");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
yosys_backend(jny
|
||||||
|
jny.cc
|
||||||
|
PROVIDES
|
||||||
|
jny
|
||||||
|
)
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/jny/jny.o
|
|
||||||
|
|
@ -91,7 +91,7 @@ struct JnyWriter
|
||||||
{
|
{
|
||||||
_cells.clear();
|
_cells.clear();
|
||||||
for (auto cell : mod->cells()) {
|
for (auto cell : mod->cells()) {
|
||||||
const auto cell_type = escape_string(RTLIL::unescape_id(cell->type));
|
const auto cell_type = escape_string(cell->type.unescape());
|
||||||
|
|
||||||
if (_cells.find(cell_type) == _cells.end())
|
if (_cells.find(cell_type) == _cells.end())
|
||||||
_cells.emplace(cell_type, std::vector<Cell*>());
|
_cells.emplace(cell_type, std::vector<Cell*>());
|
||||||
|
|
@ -214,7 +214,7 @@ struct JnyWriter
|
||||||
void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) {
|
void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) {
|
||||||
const auto _indent = gen_indent(indent_level);
|
const auto _indent = gen_indent(indent_level);
|
||||||
f << _indent << " {\n";
|
f << _indent << " {\n";
|
||||||
f << _indent << " \"name\": \"" << escape_string(RTLIL::unescape_id(sig.first)) << "\",\n";
|
f << _indent << " \"name\": \"" << escape_string(sig.first.unescape()) << "\",\n";
|
||||||
f << _indent << " \"signals\": [\n";
|
f << _indent << " \"signals\": [\n";
|
||||||
|
|
||||||
write_sigspec(sig.second, indent_level + 2);
|
write_sigspec(sig.second, indent_level + 2);
|
||||||
|
|
@ -232,7 +232,7 @@ struct JnyWriter
|
||||||
const auto _indent = gen_indent(indent_level);
|
const auto _indent = gen_indent(indent_level);
|
||||||
|
|
||||||
f << _indent << "{\n";
|
f << _indent << "{\n";
|
||||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(mod->name)));
|
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(mod->name.unescape()));
|
||||||
f << _indent << " \"cell_sorts\": [\n";
|
f << _indent << " \"cell_sorts\": [\n";
|
||||||
|
|
||||||
bool first_sort{true};
|
bool first_sort{true};
|
||||||
|
|
@ -280,7 +280,7 @@ struct JnyWriter
|
||||||
f << ",\n";
|
f << ",\n";
|
||||||
|
|
||||||
f << _indent << " {\n";
|
f << _indent << " {\n";
|
||||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(con.first)));
|
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(con.first.unescape()));
|
||||||
f << _indent << " \"direction\": \"";
|
f << _indent << " \"direction\": \"";
|
||||||
if (port_cell->input(con.first))
|
if (port_cell->input(con.first))
|
||||||
f << "i";
|
f << "i";
|
||||||
|
|
@ -351,10 +351,10 @@ struct JnyWriter
|
||||||
f << stringf(",\n");
|
f << stringf(",\n");
|
||||||
const auto param_val = param.second;
|
const auto param_val = param.second;
|
||||||
if (!param_val.empty()) {
|
if (!param_val.empty()) {
|
||||||
f << stringf(" %s\"%s\": ", _indent, escape_string(RTLIL::unescape_id(param.first)));
|
f << stringf(" %s\"%s\": ", _indent, escape_string(param.first.unescape()));
|
||||||
write_param_val(param_val);
|
write_param_val(param_val);
|
||||||
} else {
|
} else {
|
||||||
f << stringf(" %s\"%s\": true", _indent, escape_string(RTLIL::unescape_id(param.first)));
|
f << stringf(" %s\"%s\": true", _indent, escape_string(param.first.unescape()));
|
||||||
}
|
}
|
||||||
|
|
||||||
first_param = false;
|
first_param = false;
|
||||||
|
|
@ -366,7 +366,7 @@ struct JnyWriter
|
||||||
log_assert(cell != nullptr);
|
log_assert(cell != nullptr);
|
||||||
|
|
||||||
f << _indent << " {\n";
|
f << _indent << " {\n";
|
||||||
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(RTLIL::unescape_id(cell->name)));
|
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(cell->name.unescape()));
|
||||||
|
|
||||||
if (_include_connections) {
|
if (_include_connections) {
|
||||||
f << ",\n" << _indent << " \"connections\": [\n";
|
f << ",\n" << _indent << " \"connections\": [\n";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
yosys_backend(json
|
||||||
|
json.cc
|
||||||
|
PROVIDES
|
||||||
|
json
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/json/json.o
|
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ struct JsonWriter
|
||||||
|
|
||||||
string get_name(IdString name)
|
string get_name(IdString name)
|
||||||
{
|
{
|
||||||
return get_string(RTLIL::unescape_id(name));
|
return get_string(name.unescape());
|
||||||
}
|
}
|
||||||
|
|
||||||
string get_bits(SigSpec sig)
|
string get_bits(SigSpec sig)
|
||||||
|
|
@ -152,7 +152,7 @@ struct JsonWriter
|
||||||
sigidcounter = 2;
|
sigidcounter = 2;
|
||||||
|
|
||||||
if (module->has_processes()) {
|
if (module->has_processes()) {
|
||||||
log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module));
|
log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", module);
|
||||||
}
|
}
|
||||||
|
|
||||||
f << stringf(" %s: {\n", get_name(module->name));
|
f << stringf(" %s: {\n", get_name(module->name));
|
||||||
|
|
@ -316,13 +316,13 @@ struct JsonWriter
|
||||||
f << stringf(" /* %3d */ [ ", node_idx);
|
f << stringf(" /* %3d */ [ ", node_idx);
|
||||||
if (node.portbit >= 0)
|
if (node.portbit >= 0)
|
||||||
f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "",
|
f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "",
|
||||||
log_id(node.portname), node.portbit);
|
node.portname.unescape(), node.portbit);
|
||||||
else if (node.left_parent < 0 && node.right_parent < 0)
|
else if (node.left_parent < 0 && node.right_parent < 0)
|
||||||
f << stringf("\"%s\"", node.inverter ? "true" : "false");
|
f << stringf("\"%s\"", node.inverter ? "true" : "false");
|
||||||
else
|
else
|
||||||
f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent);
|
f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent);
|
||||||
for (auto &op : node.outports)
|
for (auto &op : node.outports)
|
||||||
f << stringf(", \"%s\", %d", log_id(op.first), op.second);
|
f << stringf(", \"%s\", %d", op.first.unescape(), op.second);
|
||||||
f << stringf(" ]");
|
f << stringf(" ]");
|
||||||
node_idx++;
|
node_idx++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
yosys_backend(rtlil
|
||||||
|
rtlil_backend.cc
|
||||||
|
rtlil_backend.h
|
||||||
|
PROVIDES
|
||||||
|
dump
|
||||||
|
DATA_DIR
|
||||||
|
include/backends/rtlil
|
||||||
|
DATA_FILES
|
||||||
|
rtlil_backend.h
|
||||||
|
ESSENTIAL
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/rtlil/rtlil_backend.o
|
|
||||||
|
|
||||||
|
|
@ -61,7 +61,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f << stringf("%d'", width);
|
if ((data.flags & RTLIL::CONST_FLAG_UNSIZED) == 0) {
|
||||||
|
f << stringf("%d'", width);
|
||||||
|
}
|
||||||
if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
|
if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
|
||||||
f << stringf("s");
|
f << stringf("s");
|
||||||
}
|
}
|
||||||
|
|
@ -173,9 +175,10 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
|
||||||
dump_attributes(f, indent, cell);
|
dump_attributes(f, indent, cell);
|
||||||
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
|
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
|
||||||
for (const auto& [name, param] : reversed(cell->parameters)) {
|
for (const auto& [name, param] : reversed(cell->parameters)) {
|
||||||
f << stringf("%s parameter%s%s %s ", indent,
|
f << stringf("%s parameter%s%s%s %s ", indent,
|
||||||
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
||||||
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
|
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
|
||||||
|
(param.flags & RTLIL::CONST_FLAG_UNSIZED) != 0 ? " unsized" : "",
|
||||||
name);
|
name);
|
||||||
dump_const(f, param);
|
dump_const(f, param);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(simplec
|
||||||
|
simplec.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/simplec/simplec.o
|
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ struct HierDirtyFlags
|
||||||
for (Cell *cell : module->cells()) {
|
for (Cell *cell : module->cells()) {
|
||||||
Module *mod = module->design->module(cell->type);
|
Module *mod = module->design->module(cell->type);
|
||||||
if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
|
if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
|
||||||
prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name));
|
prefix + cid(cell->name) + ".", log_prefix + "." + prefix + cell->name.unescape());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,23 +354,23 @@ struct SimplecWorker
|
||||||
struct_declarations.push_back(" // Input Ports");
|
struct_declarations.push_back(" // Input Ports");
|
||||||
for (Wire *w : mod->wires())
|
for (Wire *w : mod->wires())
|
||||||
if (w->port_input)
|
if (w->port_input)
|
||||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||||
|
|
||||||
struct_declarations.push_back("");
|
struct_declarations.push_back("");
|
||||||
struct_declarations.push_back(" // Output Ports");
|
struct_declarations.push_back(" // Output Ports");
|
||||||
for (Wire *w : mod->wires())
|
for (Wire *w : mod->wires())
|
||||||
if (!w->port_input && w->port_output)
|
if (!w->port_input && w->port_output)
|
||||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||||
|
|
||||||
struct_declarations.push_back("");
|
struct_declarations.push_back("");
|
||||||
struct_declarations.push_back(" // Internal Wires");
|
struct_declarations.push_back(" // Internal Wires");
|
||||||
for (Wire *w : mod->wires())
|
for (Wire *w : mod->wires())
|
||||||
if (!w->port_input && !w->port_output)
|
if (!w->port_input && !w->port_output)
|
||||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||||
|
|
||||||
for (Cell *c : mod->cells())
|
for (Cell *c : mod->cells())
|
||||||
if (design->module(c->type))
|
if (design->module(c->type))
|
||||||
struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), log_id(c)));
|
struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), c));
|
||||||
|
|
||||||
struct_declarations.push_back(stringf("};"));
|
struct_declarations.push_back(stringf("};"));
|
||||||
struct_declarations.push_back("#endif");
|
struct_declarations.push_back("#endif");
|
||||||
|
|
@ -391,7 +391,7 @@ struct SimplecWorker
|
||||||
|
|
||||||
log_assert(y.wire);
|
log_assert(y.wire);
|
||||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||||
|
|
||||||
work->set_dirty(y);
|
work->set_dirty(y);
|
||||||
return;
|
return;
|
||||||
|
|
@ -418,7 +418,7 @@ struct SimplecWorker
|
||||||
|
|
||||||
log_assert(y.wire);
|
log_assert(y.wire);
|
||||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||||
|
|
||||||
work->set_dirty(y);
|
work->set_dirty(y);
|
||||||
return;
|
return;
|
||||||
|
|
@ -441,7 +441,7 @@ struct SimplecWorker
|
||||||
|
|
||||||
log_assert(y.wire);
|
log_assert(y.wire);
|
||||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||||
|
|
||||||
work->set_dirty(y);
|
work->set_dirty(y);
|
||||||
return;
|
return;
|
||||||
|
|
@ -466,7 +466,7 @@ struct SimplecWorker
|
||||||
|
|
||||||
log_assert(y.wire);
|
log_assert(y.wire);
|
||||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||||
|
|
||||||
work->set_dirty(y);
|
work->set_dirty(y);
|
||||||
return;
|
return;
|
||||||
|
|
@ -490,13 +490,13 @@ struct SimplecWorker
|
||||||
|
|
||||||
log_assert(y.wire);
|
log_assert(y.wire);
|
||||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||||
|
|
||||||
work->set_dirty(y);
|
work->set_dirty(y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
|
log_error("No C model for %s available at the moment (FIXME).\n", cell->type.unescape());
|
||||||
}
|
}
|
||||||
|
|
||||||
void eval_dirty(HierDirtyFlags *work)
|
void eval_dirty(HierDirtyFlags *work)
|
||||||
|
|
@ -517,7 +517,7 @@ struct SimplecWorker
|
||||||
if (chunk.wire == nullptr)
|
if (chunk.wire == nullptr)
|
||||||
continue;
|
continue;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
|
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, chunk.wire, chunk.offset+chunk.width-1, chunk.offset);
|
||||||
funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix, log_signal(chunk)));
|
funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix, log_signal(chunk)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -539,8 +539,8 @@ struct SimplecWorker
|
||||||
work->parent->set_dirty(parent_bit);
|
work->parent->set_dirty(parent_bit);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset,
|
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset,
|
||||||
work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
|
work->parent->log_prefix.c_str(), parent_bit.wire, parent_bit.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &port : bit2cell[work->module][bit])
|
for (auto &port : bit2cell[work->module][bit])
|
||||||
|
|
@ -556,12 +556,12 @@ struct SimplecWorker
|
||||||
child->set_dirty(child_bit);
|
child->set_dirty(child_bit);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset,
|
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset,
|
||||||
work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
|
work->log_prefix.c_str(), std::get<0>(port), child_bit.wire, child_bit.offset);
|
||||||
} else {
|
} else {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, log_id(std::get<0>(port)),
|
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, std::get<0>(port),
|
||||||
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
|
work->log_prefix.c_str(), bit.wire, bit.offset);
|
||||||
work->set_dirty(std::get<0>(port));
|
work->set_dirty(std::get<0>(port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -576,10 +576,10 @@ struct SimplecWorker
|
||||||
if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
|
if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
|
||||||
cell = c;
|
cell = c;
|
||||||
|
|
||||||
string hiername = work->log_prefix + "." + log_id(cell);
|
string hiername = work->log_prefix + "." + cell->name.unescape();
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Evaluating %s (%s, best of %d).\n", hiername, log_id(cell->type), GetSize(work->dirty_cells));
|
log(" Evaluating %s (%s, best of %d).\n", hiername, cell->type.unescape(), GetSize(work->dirty_cells));
|
||||||
|
|
||||||
if (activated_cells.count(hiername))
|
if (activated_cells.count(hiername))
|
||||||
reactivated_cells.insert(hiername);
|
reactivated_cells.insert(hiername);
|
||||||
|
|
@ -618,8 +618,8 @@ struct SimplecWorker
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
|
log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
|
||||||
work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
|
work->log_prefix.c_str(), canonical_bit.wire, canonical_bit.offset,
|
||||||
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
|
work->log_prefix.c_str(), bit.wire, bit.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
work->sticky_dirty_bits.clear();
|
work->sticky_dirty_bits.clear();
|
||||||
|
|
@ -716,7 +716,7 @@ struct SimplecWorker
|
||||||
{
|
{
|
||||||
create_module_struct(mod);
|
create_module_struct(mod);
|
||||||
|
|
||||||
HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name));
|
HierDirtyFlags work(mod, IdString(), nullptr, "state->", mod->name.unescape());
|
||||||
|
|
||||||
make_init_func(&work);
|
make_init_func(&work);
|
||||||
make_eval_func(&work);
|
make_eval_func(&work);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
yosys_backend(smt2
|
||||||
|
smt2.cc
|
||||||
|
REQUIRES
|
||||||
|
json11
|
||||||
|
DATA_DIR
|
||||||
|
python3
|
||||||
|
DATA_FILES
|
||||||
|
smtio.py
|
||||||
|
ywio.py
|
||||||
|
REQUIRES
|
||||||
|
bmuxmap
|
||||||
|
demuxmap
|
||||||
|
)
|
||||||
|
|
||||||
|
yosys_python_executable(yosys-smtbmc smtbmc.py
|
||||||
|
INSTALL_IF YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY
|
||||||
|
)
|
||||||
|
yosys_python_executable(yosys-witness witness.py
|
||||||
|
INSTALL_IF YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY
|
||||||
|
)
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/smt2/smt2.o
|
|
||||||
|
|
||||||
ifneq ($(CONFIG),mxe)
|
|
||||||
ifneq ($(CONFIG),emcc)
|
|
||||||
|
|
||||||
# MSYS targets support yosys-smtbmc, but require a launcher script
|
|
||||||
ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64))
|
|
||||||
TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc.exe $(PROGRAM_PREFIX)yosys-smtbmc-script.py
|
|
||||||
TARGETS += $(PROGRAM_PREFIX)yosys-witness.exe $(PROGRAM_PREFIX)yosys-witness-script.py
|
|
||||||
# Needed to find the Python interpreter for yosys-smtbmc scripts.
|
|
||||||
# Override if necessary, it is only used for msys2 targets.
|
|
||||||
PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3)
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-smtbmc-script.py: backends/smt2/smtbmc.py
|
|
||||||
$(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \
|
|
||||||
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-witness-script.py: backends/smt2/witness.py
|
|
||||||
$(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \
|
|
||||||
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-smtbmc.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-smtbmc-script.py
|
|
||||||
$(P) $(CXX) -DGUI=0 -O -s -o $@ $<
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-witness.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-witness-script.py
|
|
||||||
$(P) $(CXX) -DGUI=0 -O -s -o $@ $<
|
|
||||||
# Other targets
|
|
||||||
else
|
|
||||||
TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc $(PROGRAM_PREFIX)yosys-witness
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-smtbmc: backends/smt2/smtbmc.py
|
|
||||||
$(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new
|
|
||||||
$(Q) chmod +x $@.new
|
|
||||||
$(Q) mv $@.new $@
|
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys-witness: backends/smt2/witness.py
|
|
||||||
$(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new
|
|
||||||
$(Q) chmod +x $@.new
|
|
||||||
$(Q) mv $@.new $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/python3,backends/smt2/smtio.py))
|
|
||||||
$(eval $(call add_share_file,share/python3,backends/smt2/ywio.py))
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "libs/json11/json11.hpp"
|
#include "libs/json11/json11.hpp"
|
||||||
|
|
@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct Smt2Worker
|
struct Smt2Worker
|
||||||
{
|
{
|
||||||
CellTypes ct;
|
NewCellTypes ct;
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
|
bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
|
||||||
|
|
@ -60,7 +60,7 @@ struct Smt2Worker
|
||||||
const char *get_id(IdString n)
|
const char *get_id(IdString n)
|
||||||
{
|
{
|
||||||
if (ids.count(n) == 0) {
|
if (ids.count(n) == 0) {
|
||||||
std::string str = log_id(n);
|
std::string str = n.unescape();
|
||||||
for (int i = 0; i < GetSize(str); i++) {
|
for (int i = 0; i < GetSize(str); i++) {
|
||||||
if (str[i] == '\\')
|
if (str[i] == '\\')
|
||||||
str[i] = '/';
|
str[i] = '/';
|
||||||
|
|
@ -207,7 +207,7 @@ struct Smt2Worker
|
||||||
}
|
}
|
||||||
else if (is_output || !is_input)
|
else if (is_output || !is_input)
|
||||||
log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n",
|
log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n",
|
||||||
log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type));
|
conn.first.unescape(), module, cell, cell->type.unescape());
|
||||||
|
|
||||||
if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C))
|
if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C))
|
||||||
{
|
{
|
||||||
|
|
@ -448,7 +448,7 @@ struct Smt2Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||||
|
|
||||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||||
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(bit)));
|
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(bit)));
|
||||||
|
|
@ -498,7 +498,7 @@ struct Smt2Worker
|
||||||
processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr);
|
processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||||
|
|
||||||
if (type == 'b') {
|
if (type == 'b') {
|
||||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||||
|
|
@ -529,7 +529,7 @@ struct Smt2Worker
|
||||||
processed_expr += ch;
|
processed_expr += ch;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||||
|
|
||||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||||
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(sig_y)));
|
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(sig_y)));
|
||||||
|
|
@ -541,7 +541,7 @@ struct Smt2Worker
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log("%*s=> export_cell %s (%s) [%s]\n", 2+2*GetSize(recursive_cells), "",
|
log("%*s=> export_cell %s (%s) [%s]\n", 2+2*GetSize(recursive_cells), "",
|
||||||
log_id(cell), log_id(cell->type), exported_cells.count(cell) ? "old" : "new");
|
cell, cell->type.unescape(), exported_cells.count(cell) ? "old" : "new");
|
||||||
|
|
||||||
if (recursive_cells.count(cell))
|
if (recursive_cells.count(cell))
|
||||||
log_error("Found logic loop in module %s! See cell %s.\n", get_id(module), get_id(cell));
|
log_error("Found logic loop in module %s! See cell %s.\n", get_id(module), get_id(cell));
|
||||||
|
|
@ -750,7 +750,7 @@ struct Smt2Worker
|
||||||
get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str());
|
get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str());
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||||
|
|
||||||
RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y));
|
RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y));
|
||||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||||
|
|
@ -786,9 +786,9 @@ struct Smt2Worker
|
||||||
has_async_wr = true;
|
has_async_wr = true;
|
||||||
}
|
}
|
||||||
if (has_async_wr && has_sync_wr)
|
if (has_async_wr && has_sync_wr)
|
||||||
log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
|
log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", cell, module);
|
||||||
|
|
||||||
decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync"));
|
decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", mem->memid.unescape(), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync"));
|
||||||
decls.push_back(witness_memory(get_id(mem->memid), cell, mem));
|
decls.push_back(witness_memory(get_id(mem->memid), cell, mem));
|
||||||
|
|
||||||
string memstate;
|
string memstate;
|
||||||
|
|
@ -813,7 +813,7 @@ struct Smt2Worker
|
||||||
|
|
||||||
if (port.clk_enable)
|
if (port.clk_enable)
|
||||||
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
||||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
|
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module);
|
||||||
|
|
||||||
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||||
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
||||||
|
|
@ -857,7 +857,7 @@ struct Smt2Worker
|
||||||
|
|
||||||
if (port.clk_enable)
|
if (port.clk_enable)
|
||||||
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
||||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
|
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module);
|
||||||
|
|
||||||
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||||
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
||||||
|
|
@ -928,30 +928,30 @@ struct Smt2Worker
|
||||||
|
|
||||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type, module, cell);
|
||||||
}
|
}
|
||||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type, module, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify_smtlib2_module()
|
void verify_smtlib2_module()
|
||||||
{
|
{
|
||||||
if (!module->get_blackbox_attribute())
|
if (!module->get_blackbox_attribute())
|
||||||
log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", log_id(module));
|
log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", module);
|
||||||
if (module->cells().size() > 0)
|
if (module->cells().size() > 0)
|
||||||
log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", log_id(module));
|
log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", module);
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
if (!wire->port_id)
|
if (!wire->port_id)
|
||||||
log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", log_id(module),
|
log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", module,
|
||||||
log_id(wire));
|
wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
|
|
@ -991,8 +991,8 @@ struct Smt2Worker
|
||||||
}
|
}
|
||||||
bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr);
|
bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr);
|
||||||
if (is_smtlib2_comb_expr && !is_smtlib2_module)
|
if (is_smtlib2_comb_expr && !is_smtlib2_module)
|
||||||
log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", log_id(module),
|
log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", module,
|
||||||
log_id(wire));
|
wire);
|
||||||
if (wire->port_id || is_register || contains_clock || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) {
|
if (wire->port_id || is_register || contains_clock || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) {
|
||||||
RTLIL::SigSpec sig = sigmap(wire);
|
RTLIL::SigSpec sig = sigmap(wire);
|
||||||
std::vector<std::string> comments;
|
std::vector<std::string> comments;
|
||||||
|
|
@ -1023,10 +1023,10 @@ struct Smt2Worker
|
||||||
smtlib2_comb_expr =
|
smtlib2_comb_expr =
|
||||||
"(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)";
|
"(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)";
|
||||||
if (wire->port_input || !wire->port_output)
|
if (wire->port_input || !wire->port_output)
|
||||||
log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", log_id(module), log_id(wire));
|
log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", module, wire);
|
||||||
if (!bvmode && GetSize(sig) > 1)
|
if (!bvmode && GetSize(sig) > 1)
|
||||||
log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s",
|
log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s",
|
||||||
log_id(module), log_id(wire));
|
module, wire);
|
||||||
|
|
||||||
comments.push_back(witness_signal("blackbox", wire->width, 0, get_id(wire), -1, wire));
|
comments.push_back(witness_signal("blackbox", wire->width, 0, get_id(wire), -1, wire));
|
||||||
}
|
}
|
||||||
|
|
@ -1075,7 +1075,7 @@ struct Smt2Worker
|
||||||
if (wire->attributes.count(ID::init)) {
|
if (wire->attributes.count(ID::init)) {
|
||||||
if (is_smtlib2_module)
|
if (is_smtlib2_module)
|
||||||
log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s",
|
log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s",
|
||||||
log_id(module), log_id(wire));
|
module, wire);
|
||||||
|
|
||||||
RTLIL::SigSpec sig = sigmap(wire);
|
RTLIL::SigSpec sig = sigmap(wire);
|
||||||
Const val = wire->attributes.at(ID::init);
|
Const val = wire->attributes.at(ID::init);
|
||||||
|
|
@ -1381,7 +1381,7 @@ struct Smt2Worker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) log("=> finalizing SMT2 representation of %s.\n", log_id(module));
|
if (verbose) log("=> finalizing SMT2 representation of %s.\n", module);
|
||||||
|
|
||||||
for (auto c : hiercells) {
|
for (auto c : hiercells) {
|
||||||
assert_list.push_back(stringf("(|%s_a| (|%s_h %s| state))", get_id(c->type), get_id(module), get_id(c->name)));
|
assert_list.push_back(stringf("(|%s_a| (|%s_h %s| state))", get_id(c->type), get_id(module), get_id(c->name)));
|
||||||
|
|
@ -1867,12 +1867,12 @@ struct Smt2Backend : public Backend {
|
||||||
for (auto &dep : it.second)
|
for (auto &dep : it.second)
|
||||||
if (module_deps.count(dep) > 0)
|
if (module_deps.count(dep) > 0)
|
||||||
goto not_ready_yet;
|
goto not_ready_yet;
|
||||||
// log("Next in topological sort: %s\n", log_id(it.first->name));
|
// log("Next in topological sort: %s\n", it.first->name.unescape());
|
||||||
sorted_modules.push_back(it.first);
|
sorted_modules.push_back(it.first);
|
||||||
not_ready_yet:;
|
not_ready_yet:;
|
||||||
}
|
}
|
||||||
if (sorted_modules_idx == sorted_modules.size())
|
if (sorted_modules_idx == sorted_modules.size())
|
||||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name));
|
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape());
|
||||||
while (sorted_modules_idx < sorted_modules.size())
|
while (sorted_modules_idx < sorted_modules.size())
|
||||||
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
||||||
}
|
}
|
||||||
|
|
@ -1902,7 +1902,7 @@ struct Smt2Backend : public Backend {
|
||||||
if (module->has_processes_warn())
|
if (module->has_processes_warn())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));
|
log("Creating SMT-LIBv2 representation of module %s.\n", module);
|
||||||
|
|
||||||
Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache);
|
Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache);
|
||||||
worker.run();
|
worker.run();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!@PYTHON_SHEBANG@
|
||||||
#
|
#
|
||||||
# yosys -- Yosys Open SYnthesis Suite
|
# yosys -- Yosys Open SYnthesis Suite
|
||||||
#
|
#
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import os, sys, getopt, re, bisect, json
|
import os, sys, getopt, re, bisect, json
|
||||||
##yosys-sys-path##
|
sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/@YOSYS_PROGRAM_PREFIX@yosys/python3"]]
|
||||||
from smtio import SmtIo, SmtOpts, MkVcd
|
from smtio import SmtIo, SmtOpts, MkVcd
|
||||||
from ywio import ReadWitness, WriteWitness, WitnessValues
|
from ywio import ReadWitness, WriteWitness, WitnessValues
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
@ -735,6 +735,12 @@ def ywfile_signal(sig, step, mask=None):
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
|
def ywfile_signal_error(reason, detail=None):
|
||||||
|
msg = f"Yosys witness signal mismatch for {sig.pretty()}: {reason}"
|
||||||
|
if detail:
|
||||||
|
msg += f" ({detail})"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if sig.path in smt_wires:
|
if sig.path in smt_wires:
|
||||||
for wire in smt_wires[sig.path]:
|
for wire in smt_wires[sig.path]:
|
||||||
width, offset = wire["width"], wire["offset"]
|
width, offset = wire["width"], wire["offset"]
|
||||||
|
|
@ -765,6 +771,12 @@ def ywfile_signal(sig, step, mask=None):
|
||||||
for mem in smt_mems[sig.memory_path]:
|
for mem in smt_mems[sig.memory_path]:
|
||||||
width, size, bv = mem["width"], mem["size"], mem["statebv"]
|
width, size, bv = mem["width"], mem["size"], mem["statebv"]
|
||||||
|
|
||||||
|
if sig.memory_addr is not None and sig.memory_addr >= size:
|
||||||
|
ywfile_signal_error(
|
||||||
|
"memory address out of bounds",
|
||||||
|
f"address={sig.memory_addr} size={size}",
|
||||||
|
)
|
||||||
|
|
||||||
smt_expr = smt.net_expr(topmod, f"s{step}", mem["smtpath"])
|
smt_expr = smt.net_expr(topmod, f"s{step}", mem["smtpath"])
|
||||||
|
|
||||||
if bv:
|
if bv:
|
||||||
|
|
@ -781,18 +793,34 @@ def ywfile_signal(sig, step, mask=None):
|
||||||
smt_expr = "((_ extract %d %d) %s)" % (slice_high, sig.offset, smt_expr)
|
smt_expr = "((_ extract %d %d) %s)" % (slice_high, sig.offset, smt_expr)
|
||||||
|
|
||||||
output.append((0, sig.width, smt_expr))
|
output.append((0, sig.width, smt_expr))
|
||||||
|
else:
|
||||||
|
ywfile_signal_error("memory not found in design")
|
||||||
|
|
||||||
output.sort()
|
output.sort()
|
||||||
|
|
||||||
output = [chunk for chunk in output if chunk[0] != chunk[1]]
|
output = [chunk for chunk in output if chunk[0] != chunk[1]]
|
||||||
|
|
||||||
|
if not output:
|
||||||
|
if sig.memory_path:
|
||||||
|
ywfile_signal_error("memory signal has no matching bits in design")
|
||||||
|
else:
|
||||||
|
ywfile_signal_error("signal not found in design")
|
||||||
|
|
||||||
pos = 0
|
pos = 0
|
||||||
|
|
||||||
for start, end, smt_expr in output:
|
for start, end, smt_expr in output:
|
||||||
assert start == pos
|
if start != pos:
|
||||||
|
ywfile_signal_error(
|
||||||
|
"signal width/offset mismatch",
|
||||||
|
f"expected coverage at bit {pos}",
|
||||||
|
)
|
||||||
pos = end
|
pos = end
|
||||||
|
|
||||||
assert pos == sig.width
|
if pos != sig.width:
|
||||||
|
ywfile_signal_error(
|
||||||
|
"signal width/offset mismatch",
|
||||||
|
f"covered {pos} of {sig.width} bits",
|
||||||
|
)
|
||||||
|
|
||||||
if len(output) == 1:
|
if len(output) == 1:
|
||||||
return output[0][-1]
|
return output[0][-1]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!@PYTHON_SHEBANG@
|
||||||
#
|
#
|
||||||
# yosys -- Yosys Open SYnthesis Suite
|
# yosys -- Yosys Open SYnthesis Suite
|
||||||
#
|
#
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import os, sys, itertools, re
|
import os, sys, itertools, re
|
||||||
##yosys-sys-path##
|
sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/@YOSYS_PROGRAM_PREFIX@yosys/python3"]]
|
||||||
import json
|
import json
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
yosys_backend(smv
|
||||||
|
smv.cc
|
||||||
|
REQUIRES
|
||||||
|
bmuxmap
|
||||||
|
demuxmap
|
||||||
|
bwmuxmap
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/smv/smv.o
|
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/newcelltypes.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct SmvWorker
|
struct SmvWorker
|
||||||
{
|
{
|
||||||
CellTypes ct;
|
NewCellTypes ct;
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
std::ostream &f;
|
std::ostream &f;
|
||||||
|
|
@ -217,7 +217,7 @@ struct SmvWorker
|
||||||
partial_assignment_wires.insert(wire);
|
partial_assignment_wires.insert(wire);
|
||||||
|
|
||||||
if (wire->port_input)
|
if (wire->port_input)
|
||||||
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire)));
|
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, wire));
|
||||||
|
|
||||||
if (wire->attributes.count(ID::init))
|
if (wire->attributes.count(ID::init))
|
||||||
assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init))));
|
assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init))));
|
||||||
|
|
@ -579,18 +579,18 @@ struct SmvWorker
|
||||||
if (cell->type[0] == '$') {
|
if (cell->type[0] == '$') {
|
||||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n",
|
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
|
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
|
||||||
|
|
@ -799,7 +799,7 @@ struct SmvBackend : public Backend {
|
||||||
|
|
||||||
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
log("Creating SMV representation of module %s.\n", log_id(module));
|
log("Creating SMV representation of module %s.\n", module);
|
||||||
SmvWorker worker(module, verbose, *f);
|
SmvWorker worker(module, verbose, *f);
|
||||||
worker.run();
|
worker.run();
|
||||||
|
|
||||||
|
|
@ -819,7 +819,7 @@ struct SmvBackend : public Backend {
|
||||||
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
for (auto module : modules) {
|
for (auto module : modules) {
|
||||||
log("Creating SMV representation of module %s.\n", log_id(module));
|
log("Creating SMV representation of module %s.\n", module);
|
||||||
SmvWorker worker(module, verbose, *f);
|
SmvWorker worker(module, verbose, *f);
|
||||||
worker.run();
|
worker.run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(spice
|
||||||
|
spice.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/spice/spice.o
|
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
static string spice_id2str(IdString id)
|
static string spice_id2str(IdString id)
|
||||||
{
|
{
|
||||||
static const char *escape_chars = "$\\[]()<>=";
|
static const char *escape_chars = "$\\[]()<>=";
|
||||||
string s = RTLIL::unescape_id(id);
|
string s = id.unescape();
|
||||||
|
|
||||||
for (auto &ch : s)
|
for (auto &ch : s)
|
||||||
if (strchr(escape_chars, ch) != nullptr) ch = '_';
|
if (strchr(escape_chars, ch) != nullptr) ch = '_';
|
||||||
|
|
@ -82,7 +82,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De
|
||||||
if (design->module(cell->type) == nullptr)
|
if (design->module(cell->type) == nullptr)
|
||||||
{
|
{
|
||||||
log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n",
|
log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n",
|
||||||
log_id(cell->type), log_id(module), log_id(cell));
|
cell->type.unescape(), module, cell);
|
||||||
for (auto &conn : cell->connections()) {
|
for (auto &conn : cell->connections()) {
|
||||||
RTLIL::SigSpec sig = sigmap(conn.second);
|
RTLIL::SigSpec sig = sigmap(conn.second);
|
||||||
port_sigs.push_back(sig);
|
port_sigs.push_back(sig);
|
||||||
|
|
@ -224,9 +224,9 @@ struct SpiceBackend : public Backend {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (module->processes.size() != 0)
|
if (module->processes.size() != 0)
|
||||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module));
|
log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", module);
|
||||||
if (module->memories.size() != 0)
|
if (module->memories.size() != 0)
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", module);
|
||||||
|
|
||||||
if (module->name == RTLIL::escape_id(top_module_name)) {
|
if (module->name == RTLIL::escape_id(top_module_name)) {
|
||||||
top_module = module;
|
top_module = module;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
yosys_backend(table
|
||||||
|
table.cc
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/table/table.o
|
|
||||||
|
|
||||||
|
|
@ -77,8 +77,8 @@ struct TableBackend : public Backend {
|
||||||
if (wire->port_id == 0)
|
if (wire->port_id == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*f << log_id(module) << "\t";
|
*f << module->name.unescape() << "\t";
|
||||||
*f << log_id(wire) << "\t";
|
*f << wire->name.unescape() << "\t";
|
||||||
*f << "-" << "\t";
|
*f << "-" << "\t";
|
||||||
*f << "-" << "\t";
|
*f << "-" << "\t";
|
||||||
|
|
||||||
|
|
@ -97,10 +97,10 @@ struct TableBackend : public Backend {
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
for (auto conn : cell->connections())
|
for (auto conn : cell->connections())
|
||||||
{
|
{
|
||||||
*f << log_id(module) << "\t";
|
*f << module->name.unescape() << "\t";
|
||||||
*f << log_id(cell) << "\t";
|
*f << cell->name.unescape() << "\t";
|
||||||
*f << log_id(cell->type) << "\t";
|
*f << cell->type.unescape() << "\t";
|
||||||
*f << log_id(conn.first) << "\t";
|
*f << conn.first.unescape() << "\t";
|
||||||
|
|
||||||
if (cell->input(conn.first) && cell->output(conn.first))
|
if (cell->input(conn.first) && cell->output(conn.first))
|
||||||
*f << "inout" << "\t";
|
*f << "inout" << "\t";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
yosys_backend(verilog
|
||||||
|
verilog_backend.cc
|
||||||
|
verilog_backend.h
|
||||||
|
REQUIRES
|
||||||
|
bmuxmap
|
||||||
|
demuxmap
|
||||||
|
clean_zerowidth
|
||||||
|
)
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
OBJS += backends/verilog/verilog_backend.o
|
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@ USING_YOSYS_NAMESPACE
|
||||||
|
|
||||||
using namespace VERILOG_BACKEND;
|
using namespace VERILOG_BACKEND;
|
||||||
|
|
||||||
const pool<string> VERILOG_BACKEND::verilog_keywords() {
|
const pool<string> &VERILOG_BACKEND::verilog_keywords() {
|
||||||
static const pool<string> res = {
|
static const pool<string> res = {
|
||||||
// IEEE 1800-2017 Annex B
|
// IEEE 1800-2017 Annex B
|
||||||
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
||||||
|
|
@ -95,7 +95,8 @@ bool VERILOG_BACKEND::id_is_verilog_escaped(const std::string &str) {
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs,
|
||||||
|
noparallelcase, default_params;
|
||||||
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
|
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
|
||||||
dict<RTLIL::IdString, int> auto_name_map;
|
dict<RTLIL::IdString, int> auto_name_map;
|
||||||
std::set<RTLIL::IdString> reg_wires;
|
std::set<RTLIL::IdString> reg_wires;
|
||||||
|
|
@ -108,22 +109,30 @@ IdString initial_id;
|
||||||
|
|
||||||
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
|
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
|
||||||
{
|
{
|
||||||
const char *str = id.c_str();
|
auto it = id.begin();
|
||||||
|
auto it_end = id.end();
|
||||||
if (*str == '$' && may_rename && !norename)
|
if (it == it_end)
|
||||||
auto_name_map[id] = auto_name_counter++;
|
|
||||||
|
|
||||||
if (str[0] != '\\' || str[1] != '_' || str[2] == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 2; str[i] != 0; i++) {
|
if (*it == '$' && may_rename && !norename)
|
||||||
if (str[i] == '_' && str[i+1] == 0)
|
auto_name_map[id] = auto_name_counter++;
|
||||||
continue;
|
|
||||||
if (str[i] < '0' || str[i] > '9')
|
if (*it != '\\' || (it + 1) == it_end || *(it + 1) != '_' || (it + 2) == it_end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
it += 2;
|
||||||
|
while (it != it_end) {
|
||||||
|
char ch = *it;
|
||||||
|
if (ch == '_' && (it + 1) == it_end)
|
||||||
|
break;
|
||||||
|
if (ch < '0' || ch > '9')
|
||||||
return;
|
return;
|
||||||
|
s.push_back(ch);
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num = atoi(str+2);
|
int num = atoi(s.c_str());
|
||||||
if (num >= auto_name_offset)
|
if (num >= auto_name_offset)
|
||||||
auto_name_offset = num + 1;
|
auto_name_offset = num + 1;
|
||||||
}
|
}
|
||||||
|
|
@ -413,6 +422,13 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_parameter(std::ostream &f, std::string indent, RTLIL::IdString id_string, RTLIL::Const parameter)
|
||||||
|
{
|
||||||
|
f << stringf("%sparameter %s = ", indent.c_str(), id(id_string).c_str());
|
||||||
|
dump_const(f, parameter);
|
||||||
|
f << ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
|
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, wire->attributes, "\n", /*modattr=*/false, /*regattr=*/reg_wires.count(wire->name));
|
dump_attributes(f, indent, wire->attributes, "\n", /*modattr=*/false, /*regattr=*/reg_wires.count(wire->name));
|
||||||
|
|
@ -2135,6 +2151,9 @@ void dump_case_actions(std::ostream &f, std::string indent, RTLIL::CaseRule *cs)
|
||||||
|
|
||||||
bool dump_proc_switch_ifelse(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
|
bool dump_proc_switch_ifelse(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
|
||||||
{
|
{
|
||||||
|
if (sw->cases.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
|
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
|
||||||
if ((*it)->compare.size() == 0) {
|
if ((*it)->compare.size() == 0) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -2369,7 +2388,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
||||||
log_warning("Module %s contains RTLIL processes with sync rules. Such RTLIL "
|
log_warning("Module %s contains RTLIL processes with sync rules. Such RTLIL "
|
||||||
"processes can't always be mapped directly to Verilog always blocks. "
|
"processes can't always be mapped directly to Verilog always blocks. "
|
||||||
"unintended changes in simulation behavior are possible! Use \"proc\" "
|
"unintended changes in simulation behavior are possible! Use \"proc\" "
|
||||||
"to convert processes to logic networks and registers.\n", log_id(module));
|
"to convert processes to logic networks and registers.\n", module);
|
||||||
|
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
|
for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
|
||||||
|
|
@ -2427,6 +2446,10 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
||||||
f << indent + " " << "reg " << id(initial_id) << " = 0;\n";
|
f << indent + " " << "reg " << id(initial_id) << " = 0;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (default_params)
|
||||||
|
for (auto p : module->parameter_default_values)
|
||||||
|
dump_parameter(f, indent + " ", p.first, p.second);
|
||||||
|
|
||||||
// first dump input / output according to their order in module->ports
|
// first dump input / output according to their order in module->ports
|
||||||
for (auto port : module->ports)
|
for (auto port : module->ports)
|
||||||
dump_wire(f, indent + " ", module->wire(port));
|
dump_wire(f, indent + " ", module->wire(port));
|
||||||
|
|
@ -2534,6 +2557,10 @@ struct VerilogBackend : public Backend {
|
||||||
log(" use 'defparam' statements instead of the Verilog-2001 syntax for\n");
|
log(" use 'defparam' statements instead of the Verilog-2001 syntax for\n");
|
||||||
log(" cell parameters.\n");
|
log(" cell parameters.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -default_params\n");
|
||||||
|
log(" emit module parameter declarations from\n");
|
||||||
|
log(" parameter_default_values.\n");
|
||||||
|
log("\n");
|
||||||
log(" -blackboxes\n");
|
log(" -blackboxes\n");
|
||||||
log(" usually modules with the 'blackbox' attribute are ignored. with\n");
|
log(" usually modules with the 'blackbox' attribute are ignored. with\n");
|
||||||
log(" this option set only the modules with the 'blackbox' attribute\n");
|
log(" this option set only the modules with the 'blackbox' attribute\n");
|
||||||
|
|
@ -2571,6 +2598,7 @@ struct VerilogBackend : public Backend {
|
||||||
siminit = false;
|
siminit = false;
|
||||||
simple_lhs = false;
|
simple_lhs = false;
|
||||||
noparallelcase = false;
|
noparallelcase = false;
|
||||||
|
default_params = false;
|
||||||
auto_prefix = "";
|
auto_prefix = "";
|
||||||
|
|
||||||
bool blackboxes = false;
|
bool blackboxes = false;
|
||||||
|
|
@ -2631,6 +2659,10 @@ struct VerilogBackend : public Backend {
|
||||||
defparam = true;
|
defparam = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-defaultparams") {
|
||||||
|
default_params = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "-decimal") {
|
if (arg == "-decimal") {
|
||||||
decimal = true;
|
decimal = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2682,7 +2714,7 @@ struct VerilogBackend : public Backend {
|
||||||
continue;
|
continue;
|
||||||
if (selected && !design->selected_whole_module(module->name)) {
|
if (selected && !design->selected_whole_module(module->name)) {
|
||||||
if (design->selected_module(module->name))
|
if (design->selected_module(module->name))
|
||||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name));
|
log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log("Dumping module `%s'.\n", module->name);
|
log("Dumping module `%s'.\n", module->name);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
namespace VERILOG_BACKEND {
|
namespace VERILOG_BACKEND {
|
||||||
|
|
||||||
const pool<string> verilog_keywords();
|
const pool<string> &verilog_keywords();
|
||||||
bool char_is_verilog_escaped(char c);
|
bool char_is_verilog_escaped(char c);
|
||||||
bool id_is_verilog_escaped(const std::string &str);
|
bool id_is_verilog_escaped(const std::string &str);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
include(CheckSourceCompiles)
|
||||||
|
include(CheckCXXSymbolExists)
|
||||||
|
|
||||||
|
function(check_glob)
|
||||||
|
check_cxx_symbol_exists(glob "glob.h" HAVE_GLOB)
|
||||||
|
return (PROPAGATE HAVE_BLOB)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(check_pthread_create)
|
||||||
|
if (Threads_FOUND)
|
||||||
|
# On WASI, `pthread_create()` is always available, but always fails on triples without threading
|
||||||
|
# support. Probe for it while requesting the stub implementation to be hidden, otherwise we will
|
||||||
|
# end up always crashing at runtime on thread creation.
|
||||||
|
cmake_push_check_state(RESET)
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS -D_WASI_STRICT_PTHREAD)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
check_source_compiles(CXX [[
|
||||||
|
#include <pthread.h>
|
||||||
|
int main() {
|
||||||
|
pthread_create(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
]] HAVE_PTHREAD_CREATE)
|
||||||
|
cmake_pop_check_state()
|
||||||
|
endif()
|
||||||
|
return (PROPAGATE HAVE_PTHREAD_CREATE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(check_system)
|
||||||
|
check_cxx_symbol_exists(system "stdlib.h" HAVE_SYSTEM)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(check_popen)
|
||||||
|
check_cxx_symbol_exists(popen "stdio.h" HAVE_POPEN)
|
||||||
|
if (NOT HAVE_POPEN)
|
||||||
|
unset(HAVE_POPEN CACHE)
|
||||||
|
# https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen
|
||||||
|
check_cxx_symbol_exists(_popen "stdio.h" HAVE_POPEN)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Syntax:
|
||||||
|
#
|
||||||
|
# condition(<var> <expr>...)
|
||||||
|
#
|
||||||
|
# If `<expr>...` is truthful (evaluated as in `if()`) then assigns 1 to `<var>`, else assigns 0.
|
||||||
|
# The assigned value is `0`/`1` rather than `TRUE`/`FALSE` for ease of use in generator expressions.
|
||||||
|
# Note that `<expr>...` *must* be unquoted.
|
||||||
|
#
|
||||||
|
# To understand how a certain outcome is reached, reconfigure the project with `--log-level VERBOSE`.
|
||||||
|
#
|
||||||
|
# Believe it or not, CMake doesn't have this built in!
|
||||||
|
#
|
||||||
|
macro(condition var)
|
||||||
|
if (${ARGN})
|
||||||
|
set(${var} 1)
|
||||||
|
else()
|
||||||
|
set(${var} 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_debug_expr)
|
||||||
|
foreach (token ${ARGN})
|
||||||
|
if (DEFINED ${token})
|
||||||
|
if (${${token}})
|
||||||
|
list(APPEND _debug_expr "${token}:1")
|
||||||
|
else()
|
||||||
|
list(APPEND _debug_expr "${token}:0")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
list(APPEND _debug_expr "${token}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
string(JOIN " " _debug_expr ${_debug_expr})
|
||||||
|
message(VERBOSE " ${var} = ${${var}} (${_debug_expr})")
|
||||||
|
unset(_debug_expr)
|
||||||
|
endmacro()
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
include(CheckCXXSymbolExists)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if (WIN32 OR MSYS)
|
||||||
|
# Windows; dlopen is available via a polyfill `libs/dlfcn-win32`.
|
||||||
|
set(Dlfcn_LIBRARIES dlfcn)
|
||||||
|
else()
|
||||||
|
# Unix and Wasm; dlopen may or may not be available depending on platform.
|
||||||
|
cmake_push_check_state(RESET)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
|
||||||
|
check_cxx_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN)
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
if (HAVE_DLOPEN)
|
||||||
|
add_library(dlfcn INTERFACE)
|
||||||
|
target_link_libraries(dlfcn INTERFACE ${CMAKE_DL_LIBS})
|
||||||
|
set(Dlfcn_LIBRARIES dlfcn)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(Dlfcn
|
||||||
|
REQUIRED_VARS Dlfcn_LIBRARIES
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
# We need a *third* `FindPython`-style call in this codebase because the host
|
||||||
|
# `Python3_EXECUTABLE` may not have pybind11 and cxxheaderparser installed,
|
||||||
|
# and installing it can be onerous. To work around this problem we try to detect
|
||||||
|
# whether the host interpreter has the necessary dependencies first, and if it
|
||||||
|
# does not, fall back to using `uv`.
|
||||||
|
|
||||||
|
foreach (strategy virtualenv host uv fail)
|
||||||
|
if (strategy STREQUAL "virtualenv")
|
||||||
|
set(PyosysEnv_PYTHON $ENV{VIRTUAL_ENV}/bin/python)
|
||||||
|
elseif (strategy STREQUAL "host")
|
||||||
|
set(PyosysEnv_PYTHON ${Python3_EXECUTABLE})
|
||||||
|
elseif (strategy STREQUAL "uv")
|
||||||
|
set(PyosysEnv_PYTHON uv run --no-project --with pybind11>3,<4 --with cxxheaderparser python)
|
||||||
|
else()
|
||||||
|
set(PyosysEnv_PYTHON)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${PyosysEnv_PYTHON} -m pybind11 --includes
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
OUTPUT_VARIABLE output
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if (result EQUAL 0)
|
||||||
|
string(REGEX REPLACE " ?-I" ";" pybind11_INCLUDE_DIR "${output}")
|
||||||
|
list(FILTER pybind11_INCLUDE_DIR INCLUDE REGEX "/pybind11/")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${PyosysEnv_PYTHON} ${CMAKE_SOURCE_DIR}/pyosys/generator.py --help
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if (result EQUAL 0)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(PyosysEnv
|
||||||
|
REQUIRED_VARS PyosysEnv_PYTHON pybind11_INCLUDE_DIR
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Wrapper to improve behavior of `FindPython3` during cross-compilation.
|
||||||
|
# Does not entirely fix the problem; CMake 4.0 introduces `Python_ARTIFACTS_PREFIX`, which will.
|
||||||
|
|
||||||
|
# Stash the package found status
|
||||||
|
get_property(packages_found GLOBAL PROPERTY PACKAGES_FOUND)
|
||||||
|
get_property(packages_not_found GLOBAL PROPERTY PACKAGES_NOT_FOUND)
|
||||||
|
get_property(required_version GLOBAL PROPERTY _CMAKE_Python3_REQUIRED_VERSION)
|
||||||
|
|
||||||
|
# A hack to make pyosys buildable in wheel-only environments.
|
||||||
|
# `Interpreter` is a part of the component set to ensure that a Python implementation without
|
||||||
|
# an interpreter that's earlier in the search order won't be selected instead of the desired one.
|
||||||
|
# (This is awful and should be removed once CMake 4.0 is here.)
|
||||||
|
if (YOSYS_BUILD_PYTHON_ONLY)
|
||||||
|
set(components Interpreter Development.Module)
|
||||||
|
else()
|
||||||
|
set(components Interpreter Development)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The `EXACT` specifier prevents the situation of `FindPython3` discovering a newer libpython-dev
|
||||||
|
# than the interpreter found in the past, rejecting it because it is too new, and giving up.
|
||||||
|
find_package(Python3 EXACT ${Python3_VERSION} COMPONENTS ${components})
|
||||||
|
if (Python3_Development.Embed_FOUND OR Python3_Development.Module_FOUND)
|
||||||
|
set(Python3Devel_FOUND YES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY PACKAGES_FOUND "${packages_found}")
|
||||||
|
set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${packages_not_found}")
|
||||||
|
set_property(GLOBAL PROPERTY _CMAKE_Python3_REQUIRED_VERSION "${required_version}")
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
cmake_minimum_required(VERSION 3.27)
|
||||||
|
set(CMAKE_MESSAGE_LOG_LEVEL ERROR)
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
include(YosysVersion)
|
||||||
|
|
||||||
|
yosys_extract_version()
|
||||||
|
if (YOSYS_VERSION_COMMIT EQUAL "0")
|
||||||
|
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}")
|
||||||
|
elseif (YOSYS_VERSION_COMMIT STREQUAL "")
|
||||||
|
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}.post9999")
|
||||||
|
else()
|
||||||
|
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}.post${YOSYS_VERSION_COMMIT}")
|
||||||
|
endif()
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${yosys_version}")
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Syntax:
|
||||||
|
#
|
||||||
|
# pkg_config_import(<package>)
|
||||||
|
#
|
||||||
|
# To use this command, `find_package(PkgConfig)` must be used beforehand, but it does
|
||||||
|
# not have to succeed. If the `PkgConfig` package is not found, all imports silently fail.
|
||||||
|
#
|
||||||
|
# Imports `<package>` as a CMake `IMPORTED` target `PkgConfig::<package>`.
|
||||||
|
# Updates the global `PACKAGES_FOUND` and `PACKAGES_NOT_FOUND` properties and defines
|
||||||
|
# the `<package>_FOUND` variable.
|
||||||
|
#
|
||||||
|
function(pkg_config_import arg_PREFIX)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "MODULES")
|
||||||
|
if (NOT arg_MODULES)
|
||||||
|
set(arg_MODULES ${arg_PREFIX})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (PkgConfig_FOUND)
|
||||||
|
# Once CMake 4.1 is available, this call should be replaced with `cmake_pkg_config()`.
|
||||||
|
pkg_check_modules(${arg_PREFIX} IMPORTED_TARGET ${arg_MODULES})
|
||||||
|
if (${arg_PREFIX}_FOUND)
|
||||||
|
# We found the pkgconfig file, but is it actually a usable package?
|
||||||
|
# The main cause of failure here would be cross-compiling, which pkg-config does not
|
||||||
|
# handle very well (especially pre-`cmake_pkg_config()`).
|
||||||
|
try_compile(is_usable
|
||||||
|
SOURCE_FROM_CONTENT "main.cc" "int main() {}"
|
||||||
|
LINK_LIBRARIES PkgConfig::${arg_PREFIX}
|
||||||
|
LOG_DESCRIPTION "Checking if PkgConfig::${arg_PREFIX} is usable"
|
||||||
|
)
|
||||||
|
if (NOT is_usable)
|
||||||
|
message(STATUS "Modules '${arg_MODULES}' unusable (bad \$PKG_CONFIG_LIBDIR?)")
|
||||||
|
set(${arg_PREFIX}_FOUND 0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (${arg_PREFIX}_FOUND)
|
||||||
|
set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND ${arg_PREFIX})
|
||||||
|
else()
|
||||||
|
set_property(GLOBAL APPEND PROPERTY PACKAGES_NOT_FOUND ${arg_PREFIX})
|
||||||
|
endif()
|
||||||
|
return (PROPAGATE ${arg_PREFIX}_FOUND)
|
||||||
|
endfunction()
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Syntax:
|
||||||
|
#
|
||||||
|
# pmgen_command(<output>
|
||||||
|
# [<input>...]
|
||||||
|
# [PREFIX <prefix>]
|
||||||
|
# [DEBUG]
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# Builds `<output>_pm.h` in the current binary directory from pmgen source files `<input>`, which must have
|
||||||
|
# the `*.pmg` extension. If `<input>...` contains more than one file, `<prefix>` must be provided.
|
||||||
|
#
|
||||||
|
# Defines the following variables:
|
||||||
|
# - `PMGEN_<output>_DEFINED`: Boolean indicating whether this command was successfully invoked.
|
||||||
|
# - `PMGEN_<output>_OUTPUT`: The header file generated by `pmgen`.
|
||||||
|
#
|
||||||
|
# Usage example:
|
||||||
|
#
|
||||||
|
# pmgen_command(my_dsp
|
||||||
|
# my_dsp.pmg
|
||||||
|
# )
|
||||||
|
# yosys_pass(my_dsp
|
||||||
|
# my_dsp.cc
|
||||||
|
# ${PMGEN_my_dsp_OUTPUT}
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# Usage example with multiple files:
|
||||||
|
#
|
||||||
|
# pmgen_command(my_dsp
|
||||||
|
# my_dsp_macc.pmg
|
||||||
|
# my_dsp_carry.pmg
|
||||||
|
# PREFIX
|
||||||
|
# my_dsp
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
function(pmgen_command arg_NAME)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 1 arg "DEBUG" "PREFIX" "")
|
||||||
|
set(arg_INPUTS ${arg_UNPARSED_ARGUMENTS})
|
||||||
|
|
||||||
|
set(pmgen_script ${CMAKE_SOURCE_DIR}/passes/pmgen/pmgen.py)
|
||||||
|
set(pmgen_output ${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}_pm.h)
|
||||||
|
cmake_path(RELATIVE_PATH pmgen_output BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE pmgen_output_rel)
|
||||||
|
add_custom_command(
|
||||||
|
DEPENDS ${pmgen_script} ${arg_INPUTS}
|
||||||
|
OUTPUT ${pmgen_output}
|
||||||
|
COMMAND ${Python3_EXECUTABLE}
|
||||||
|
${pmgen_script}
|
||||||
|
"$<$<BOOL:${arg_DEBUG}>:-g>"
|
||||||
|
"$<$<BOOL:${arg_PREFIX}>:-p;${arg_PREFIX}>"
|
||||||
|
-o ${pmgen_output}
|
||||||
|
${arg_INPUTS}
|
||||||
|
COMMAND_EXPAND_LISTS
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
VERBATIM
|
||||||
|
COMMENT "Compiling pattern matcher ${pmgen_output_rel}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# The usage of this command is somewhat inspired by `flex_target()` and `bison_target()`.
|
||||||
|
set(PMGEN_${arg_NAME}_DEFINED TRUE)
|
||||||
|
set(PMGEN_${arg_NAME}_OUTPUT ${pmgen_output} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
include(CheckCompilerFlag)
|
||||||
|
|
||||||
|
define_property(TARGET PROPERTY YOSYS_IS_ABC)
|
||||||
|
|
||||||
|
function(target_safe_compile_options target scope)
|
||||||
|
foreach (lang C CXX)
|
||||||
|
foreach (flag ${ARGN})
|
||||||
|
check_compiler_flag(${lang} ${flag} HAVE_${lang}_${flag})
|
||||||
|
if (HAVE_${lang}_${flag})
|
||||||
|
target_compile_options(${target} ${scope} $<$<COMPILE_LANGUAGE:${lang}>:${flag}>)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(_yosys_abc_extract_makefile result vardecl filename)
|
||||||
|
# Parse a Makefile fragment and extracts the first matching variable assignment into
|
||||||
|
# a list of values.
|
||||||
|
file(READ ${filename} contents)
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filename})
|
||||||
|
if ("${contents}" MATCHES "${vardecl}(\\\\\n|[ \t])*(([^\\\\\n]|\\\\\n)+)")
|
||||||
|
string(REGEX REPLACE "(\\\\\n|[ \t])+" ";" ${result} "${CMAKE_MATCH_2}")
|
||||||
|
endif()
|
||||||
|
return (PROPAGATE ${result})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(yosys_abc_target arg_LIBNAME arg_EXENAME)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 2 arg "" "INSTALL_IF" "")
|
||||||
|
|
||||||
|
# Instead of using either the ABC Make or CMake build system, we parse the source
|
||||||
|
# of truth: ABC's `module.make` files. This turns out to be quite trivial.
|
||||||
|
# This way, no assumptions about the environment are made, and Yosys can be compiled
|
||||||
|
# on Windows without MSYS as a result (while benefitting other platforms as well).
|
||||||
|
set(all_sources)
|
||||||
|
_yosys_abc_extract_makefile(module_files "MODULES :=" ${CMAKE_SOURCE_DIR}/abc/Makefile)
|
||||||
|
_yosys_abc_extract_makefile(module_files_cudd "MODULES \\+=" ${CMAKE_SOURCE_DIR}/abc/Makefile)
|
||||||
|
list(REMOVE_ITEM module_files "$(wildcard" "src/ext*)")
|
||||||
|
foreach (module_file ${module_files} ${module_files_cudd})
|
||||||
|
_yosys_abc_extract_makefile(module_sources "SRC \\+=" ${CMAKE_SOURCE_DIR}/abc/${module_file}/module.make)
|
||||||
|
list(APPEND all_sources ${module_sources})
|
||||||
|
endforeach()
|
||||||
|
list(TRANSFORM all_sources PREPEND abc/)
|
||||||
|
|
||||||
|
# Required to get `-DABC_NAMESPACE` below to work consistently.
|
||||||
|
set_source_files_properties(${all_sources} PROPERTIES LANGUAGE CXX)
|
||||||
|
|
||||||
|
set(main_source abc/src/base/main/main.c)
|
||||||
|
list(REMOVE_ITEM all_sources ${main_source})
|
||||||
|
|
||||||
|
find_package(Threads)
|
||||||
|
yosys_cxx_library(${arg_LIBNAME} STATIC
|
||||||
|
OUTPUT_NAME ${arg_LIBNAME}
|
||||||
|
)
|
||||||
|
target_sources(${arg_LIBNAME} PRIVATE ${all_sources})
|
||||||
|
target_include_directories(${arg_LIBNAME} PRIVATE abc/src)
|
||||||
|
target_compile_definitions(${arg_LIBNAME} PUBLIC
|
||||||
|
WIN32_NO_DLL
|
||||||
|
ABC_NAMESPACE=abc
|
||||||
|
ABC_USE_STDINT_H=1
|
||||||
|
ABC_USE_CUDD=1
|
||||||
|
ABC_NO_DYNAMIC_LINKING
|
||||||
|
$<${YOSYS_ENABLE_THREADS}:ABC_USE_PTHREADS>
|
||||||
|
$<${YOSYS_ENABLE_READLINE}:ABC_USE_READLINE>
|
||||||
|
ABC_NO_RLIMIT
|
||||||
|
)
|
||||||
|
target_safe_compile_options(${arg_LIBNAME} PRIVATE
|
||||||
|
-fpermissive
|
||||||
|
-fno-exceptions
|
||||||
|
-Wno-write-strings
|
||||||
|
-Wno-changes-meaning
|
||||||
|
-Wno-attributes
|
||||||
|
-Wno-deprecated-declarations
|
||||||
|
-Wno-deprecated-comma-subscript
|
||||||
|
-Wno-format
|
||||||
|
-Wno-constant-logical-operand
|
||||||
|
)
|
||||||
|
target_link_libraries(${arg_LIBNAME} PUBLIC
|
||||||
|
$<${YOSYS_ENABLE_THREADS}:Threads::Threads>
|
||||||
|
$<${YOSYS_ENABLE_READLINE}:PkgConfig::readline>
|
||||||
|
$<$<BOOL:${WIN32}>:-lshlwapi>
|
||||||
|
)
|
||||||
|
set_target_properties(${arg_LIBNAME} PROPERTIES
|
||||||
|
YOSYS_IS_ABC ON
|
||||||
|
)
|
||||||
|
|
||||||
|
yosys_cxx_executable(${arg_EXENAME}
|
||||||
|
OUTPUT_NAME ${arg_EXENAME}
|
||||||
|
INSTALL_IF "${arg_INSTALL_IF}"
|
||||||
|
)
|
||||||
|
target_sources(${arg_EXENAME} PRIVATE ${main_source})
|
||||||
|
target_include_directories(${arg_EXENAME} PRIVATE abc/src)
|
||||||
|
target_link_libraries(${arg_EXENAME} PRIVATE ${arg_LIBNAME})
|
||||||
|
set_target_properties(${arg_EXENAME} PROPERTIES
|
||||||
|
YOSYS_IS_ABC ON
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
# depends on YosysVersion.cmake
|
||||||
|
|
||||||
|
function(yosys_check_abc_submodule)
|
||||||
|
yosys_call_git(status)
|
||||||
|
set(yosys_status "tarball")
|
||||||
|
if (git_result EQUAL 0)
|
||||||
|
set(yosys_status "git")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
yosys_call_git(submodule status abc)
|
||||||
|
set(git_commit)
|
||||||
|
if (EXISTS "${CMAKE_SOURCE_DIR}/abc/.gitcommit")
|
||||||
|
file(READ "${CMAKE_SOURCE_DIR}/abc/.gitcommit" git_commit)
|
||||||
|
string(STRIP "${git_commit}" git_commit)
|
||||||
|
endif()
|
||||||
|
set(abc_status "none")
|
||||||
|
if (git_result EQUAL 0 AND git_output MATCHES "^ ")
|
||||||
|
set(abc_status "git")
|
||||||
|
elseif (git_result EQUAL 0 AND git_output MATCHES "^\\+")
|
||||||
|
set(abc_status "git-changed")
|
||||||
|
elseif (git_result EQUAL 0 AND git_output MATCHES "^U")
|
||||||
|
set(abc_status "git-conflict")
|
||||||
|
elseif (git_commit MATCHES "^[0-9a-fA-F]+$")
|
||||||
|
set(abc_status "tarball")
|
||||||
|
elseif (git_commit MATCHES "\\$Format:%[hH]\\$")
|
||||||
|
set(abc_status "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (abc_status STREQUAL "git" OR abc_status STREQUAL "tarball")
|
||||||
|
# Normal submodule or a tarball.
|
||||||
|
elseif (abc_status STREQUAL "git-changed")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"'abc' submodule does not match expected commit.\n"
|
||||||
|
"Run 'git submodule update' to check out the correct version.\n"
|
||||||
|
"Note: If testing a different version of ABC, call 'git commit abc' "
|
||||||
|
"in the Yosys source directory to update the expected commit.\n"
|
||||||
|
)
|
||||||
|
elseif (abc_status STREQUAL "git-conflict")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"'abc' submodule has merge conflicts.\n"
|
||||||
|
"Please resolve merge conflicts before continuing.\n"
|
||||||
|
)
|
||||||
|
elseif (abc_status STREQUAL "unknown") # OK
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Error: 'abc' is not configured as a git submodule.\n"
|
||||||
|
"To resolve this:\n"
|
||||||
|
"1. Back up your changes: Save any modifications from the 'abc' directory to another location.\n"
|
||||||
|
"2. Remove the existing 'abc' directory: Delete the 'abc' directory and all its contents.\n"
|
||||||
|
"3. Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule.\n"
|
||||||
|
"4. Reapply your changes: Move your saved changes back to the 'abc' directory, if necessary.\n"
|
||||||
|
)
|
||||||
|
elseif (yosys_status STREQUAL "git") # OK
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule.\n"
|
||||||
|
)
|
||||||
|
else() #
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"${CMAKE_SOURCE_DIR} is not configured as a git repository, and 'abc' folder is missing.\n"
|
||||||
|
"If you already have ABC, set 'ABCEXTERNAL' make variable to point to ABC executable.\n"
|
||||||
|
"Otherwise, download release archive 'yosys.tar.gz' from https://github.com/YosysHQ/yosys/releases.\n"
|
||||||
|
" ('Source code' archive does not contain submodules.)\n"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue