mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-22 21:17:06 -04:00
Compare commits
1105 commits
Author | SHA1 | Date | |
---|---|---|---|
|
229fecd4a1 | ||
|
c559c6d0f9 | ||
|
9b40a05837 | ||
|
19ea858e84 | ||
|
f3409b240f | ||
|
35402a2bde | ||
|
7f2bccbef2 | ||
|
41ea95f805 | ||
|
bd39421664 | ||
|
110b2a1e00 | ||
|
e0f4bacaf4 | ||
|
4cf81af23b | ||
|
4b3af464dc | ||
|
35cf16ea56 | ||
|
67b2e94f82 | ||
|
bd9e062abe | ||
|
83606a9eb0 | ||
|
8c1e69b872 | ||
|
fd2d784298 | ||
|
545b8c3770 | ||
|
0af9894e69 | ||
|
638cd8878d | ||
|
919f00125d | ||
|
52a2e889d0 | ||
|
bd7c4c3281 | ||
|
2073047272 | ||
|
8968b5a3fa | ||
|
7beb9887a6 | ||
|
8c191a2824 | ||
|
3ee790d25c | ||
|
1175f195df | ||
|
457ae5c7e5 | ||
|
5f58e0c7c6 | ||
|
6aeb6d4d43 | ||
|
26d6f61d49 | ||
|
e52251d88c | ||
|
25d13df1b4 | ||
|
55d6b2f597 | ||
|
30871d3381 | ||
|
fe5e6dd95b | ||
|
0effdecbe6 | ||
|
35e5f4cad8 | ||
|
62577a7a11 | ||
|
7c6c7a6fe5 | ||
|
b6118e5cc2 | ||
|
940fb507a5 | ||
|
17915162f3 | ||
|
cdd8454349 | ||
|
1849aa4419 | ||
|
ec31ed30cf | ||
|
79e2ae248b | ||
|
53f79b1879 | ||
|
00534dc4a8 | ||
|
9baba6d11f | ||
|
b6f6120ec6 | ||
|
e71b1be8a2 | ||
|
f1d64eccc8 | ||
|
63f1025a15 | ||
|
4220602ba5 | ||
|
e6998d1cb3 | ||
|
11cc9b1cf2 | ||
|
beeec94344 | ||
|
05df181257 | ||
|
0f17b395bd | ||
|
07b0d7788b | ||
|
a2a60bf6bc | ||
|
281818af9c | ||
|
4e051ed2a3 | ||
|
960f8682ea | ||
|
e21dc6cda5 | ||
|
acf6ad3bfd | ||
|
213e4b863a | ||
|
220a2733be | ||
|
ff922ec601 | ||
|
9fd127d6d9 | ||
|
73733dd8b1 | ||
|
3739b9ac88 | ||
|
5ef1bc775f | ||
|
badf13be02 | ||
|
1721ac253e | ||
|
fd0f23abb6 | ||
|
1746af1cfe | ||
|
5860dc2321 | ||
|
d95c9356fa | ||
|
7f647f9d8d | ||
|
050b4d8c62 | ||
|
760a0fced5 | ||
|
b81029f619 | ||
|
ba6dcb1789 | ||
|
8fc5f35d29 | ||
|
7649157946 | ||
|
051080e060 | ||
|
d966c4efe1 | ||
|
c52433575d | ||
|
d8f6f28020 | ||
|
320867e135 | ||
|
f3d7442e2d | ||
|
95e61a7951 | ||
|
cb0bacfce9 | ||
|
b4d5a315cf | ||
|
9c2e05cce0 | ||
|
e357420d11 | ||
|
f0bb6e94e4 | ||
|
a33380894c | ||
|
e754c5c3a0 | ||
|
eeb65ed1c0 | ||
|
c69852c0cc | ||
|
8195bec788 | ||
|
8c5071ce42 | ||
|
b01490b5f3 | ||
|
570720fdd8 | ||
|
0e59a56bd1 | ||
|
bba022b746 | ||
|
385a195d16 | ||
|
a755d839b3 | ||
|
5b47564024 | ||
|
4972a27ae9 | ||
|
0aa8cb11e0 | ||
|
13061b8b2e | ||
|
876222d886 | ||
|
25eda80fee | ||
|
94f19032f0 | ||
|
6be1531d36 | ||
|
1179c6551f | ||
|
f11c642cd6 | ||
|
3cf8508db1 | ||
|
153445ff21 | ||
|
cf70bc6b1f | ||
|
b03b00a5c4 | ||
|
5493c55ab0 | ||
|
5f67075e30 | ||
|
b29eb542f2 | ||
|
c655abbb1e | ||
|
49246e757f | ||
|
13d66b3ae4 | ||
|
6f76a45e7d | ||
|
d7e9c726c3 | ||
|
c5689e512c | ||
|
a40d5f19b2 | ||
|
344b2d4eda | ||
|
9605b663bf | ||
|
220b599c9a | ||
|
366f09a14a | ||
|
15a665af53 | ||
|
c57da3c7dc | ||
|
d078297496 | ||
|
a780eec616 | ||
|
33e820bdf9 | ||
|
3ae51cdeb8 | ||
|
692f604dd5 | ||
|
cbc89093b3 | ||
|
9acc5ddc1c | ||
|
fc9a9d25ed | ||
|
e83bc5312e | ||
|
2bc6e70f03 | ||
|
7d3a862183 | ||
|
aea2e90d1e | ||
|
94f2ea6dec | ||
|
0aa6e0573d | ||
|
ed5babaaab | ||
|
2297f8aea0 | ||
|
0963eb06bd | ||
|
6650d0549d | ||
|
c8dff13391 | ||
|
df52fab7d1 | ||
|
8a6a926401 | ||
|
11f391eadf | ||
|
bf3521f86a | ||
|
b86047901a | ||
|
51b69a1527 | ||
|
773f268f37 | ||
|
fb084327da | ||
|
eafeb5fe49 | ||
|
a25ae96d33 | ||
|
572ca3fcfa | ||
|
5a8cdee884 | ||
|
4ae7386904 | ||
|
e19e59b55c | ||
|
663174bc73 | ||
|
36c3346e51 | ||
|
5e17ab62d6 | ||
|
fe68b8494e | ||
|
2504f9b9b9 | ||
|
0bfaf06a4a | ||
|
f71234786f | ||
|
d70794f252 | ||
|
5d0deb20b3 | ||
|
9f6186cd9a | ||
|
6289ebcbe4 | ||
|
a6c29766da | ||
|
ab7b2cff3b | ||
|
7fd55c7851 | ||
|
0e531515ac | ||
|
63dd787bce | ||
|
220af95043 | ||
|
0979f8ba80 | ||
|
17d52ce58f | ||
|
486d17d245 | ||
|
662943522f | ||
|
95c656ceef | ||
|
0313f84419 | ||
|
4cd3f65296 | ||
|
87c8822f55 | ||
|
959e48a353 | ||
|
7b9891829a | ||
|
051d140c33 | ||
|
fda7da00c2 | ||
|
e3e21994b4 | ||
|
54412bde30 | ||
|
24795ef09b | ||
|
a650000f0b | ||
|
b1252f47de | ||
|
1303c0ca7c | ||
|
1ce4c6e493 | ||
|
8ab9a9b12e | ||
|
0f6d0f022c | ||
|
771eaf431e | ||
|
e6dfcac0be | ||
|
4c4913c703 | ||
|
209fc719e8 | ||
|
48cf4120f2 | ||
|
0872852387 | ||
|
b39557e226 | ||
|
a553d3b476 | ||
|
8d0f7781de | ||
|
ba908ebada | ||
|
9c768be7af | ||
|
78f0a7f13e | ||
|
8df2dcbd40 | ||
|
4fff62d3fe | ||
|
e0eb00573c | ||
|
6326736401 | ||
|
27772a65dd | ||
|
8d6cb26421 | ||
|
9506b0b8f1 | ||
|
9772e6775d | ||
|
5fe1fb07d4 | ||
|
17007586e8 | ||
|
bd74833900 | ||
|
8a8e976493 | ||
|
ea7a18c7f4 | ||
|
3b8270b82b | ||
|
53d52692de | ||
|
db34033593 | ||
|
32a5206541 | ||
|
e6c21996a4 | ||
|
2d2017465e | ||
|
ccff48f872 | ||
|
4bddb091ae | ||
|
5dc91a8be4 | ||
|
b2e61caf9e | ||
|
9149c42065 | ||
|
51b8865b66 | ||
|
e1620c68b2 | ||
|
e558b79582 | ||
|
9d3b83366c | ||
|
36f57d5eb7 | ||
|
5b45ddab1b | ||
|
e4fde184d9 | ||
|
807aa98d37 | ||
|
77e361e91e | ||
|
5714680278 | ||
|
62c07670af | ||
|
4dd650736f | ||
|
378c0f8723 | ||
|
8b2f107d46 | ||
|
7d9a50357f | ||
|
57dd80a566 | ||
|
9c34a1fd2e | ||
|
b8e904e43f | ||
|
6e77f32087 | ||
|
da53de360f | ||
|
f46ad43f39 | ||
|
349993b235 | ||
|
fe6c391fe4 | ||
|
34e5cafb75 | ||
|
4824827b7e | ||
|
a340798840 | ||
|
53a3330340 | ||
|
dd12047aa7 | ||
|
0539dd7110 | ||
|
6c5908f7a3 | ||
|
411d946a58 | ||
|
acf14385d8 | ||
|
9df704cad9 | ||
|
a3807660e3 | ||
|
df03c99ab2 | ||
|
c3c3a94c5d | ||
|
97a3c1955b | ||
|
35754a0709 | ||
|
8c0fbcadac | ||
|
5f5f4afbf2 | ||
|
b807254759 | ||
|
65cda95176 | ||
|
c1481ae244 | ||
|
42bb1ab591 | ||
|
68e704f309 | ||
|
efd3cd4737 | ||
|
cc9f3e753a | ||
|
bc561c30eb | ||
|
5c7e4a0294 | ||
|
3deeab42fd | ||
|
805bd56077 | ||
|
671bd30953 | ||
|
ba8f5f966a | ||
|
b717f228d6 | ||
|
c242744d02 | ||
|
f3f9b79f9a | ||
|
5fc4125763 | ||
|
3028c19389 | ||
|
5f2fcc7d0f | ||
|
66bcd7fca7 | ||
|
0cdad37fff | ||
|
91b3e79485 | ||
|
a4c86130cc | ||
|
9bc7dce857 | ||
|
28a75afe7a | ||
|
c79357d1b2 | ||
|
a380c3a36c | ||
|
551e76d244 | ||
|
3702ea03c0 | ||
|
df7ac05db9 | ||
|
cdd8a7e94a | ||
|
1017b316b8 | ||
|
d67fe72de9 | ||
|
1497001ebd | ||
|
1ee45eeb0a | ||
|
0e89ebeced | ||
|
e1e1be5797 | ||
|
646911a373 | ||
|
87f100dac1 | ||
|
156a84e76f | ||
|
342b06128f | ||
|
2a4ca0b249 | ||
|
6cde5f9315 | ||
|
0272d66971 | ||
|
3a4ab7ad51 | ||
|
4bdeb7731b | ||
|
243d0ec664 | ||
|
d49f8d1b58 | ||
|
24a534acff | ||
|
4490254d3d | ||
|
4a2dc0ff5f | ||
|
6471014131 | ||
|
4b0763b43d | ||
|
a5f66623b7 | ||
|
61f68f0729 | ||
|
6066d8bc26 | ||
|
72328e7bc4 | ||
|
2de35e6116 | ||
|
8122cc9b5e | ||
|
1c3b9e93a2 | ||
|
91195b1a0a | ||
|
fe739b907a | ||
|
1bd33a369e | ||
|
5a7c71259d | ||
|
47110a97a3 | ||
|
ac1a6715d7 | ||
|
e78c0546a0 | ||
|
5dd7e6e065 | ||
|
b1fd24665e | ||
|
f1d7c294ee | ||
|
a34d6ffb83 | ||
|
f35d5cd2ba | ||
|
1470069dbd | ||
|
d194867b19 | ||
|
2a5bf9e993 | ||
|
6ca917b5cc | ||
|
d4ab5e971b | ||
|
d72e9fad3f | ||
|
fb8694aa8d | ||
|
334df7010c | ||
|
d15f358b44 | ||
|
ff2b7c64a4 | ||
|
f10f9246dd | ||
|
fa2899a1a2 | ||
|
45e67ccf56 | ||
|
0a0998fcea | ||
|
32e4ea406f | ||
|
bfe65da1eb | ||
|
79bc09e69a | ||
|
4e41654a84 | ||
|
15137742fc | ||
|
9e65b769cf | ||
|
b41db0af93 | ||
|
bf399cc927 | ||
|
21d24eb07f | ||
|
36c896f95b | ||
|
66f5c3079b | ||
|
73893ce5d9 | ||
|
a42c089119 | ||
|
9ac6625ef3 | ||
|
a8721b02de | ||
|
9462496386 | ||
|
6f481f51ef | ||
|
21c91c6b70 | ||
|
925edd160e | ||
|
704423f27f | ||
|
8495fe3dde | ||
|
da458dea7e | ||
|
80f64f0f9f | ||
|
6956db2b21 | ||
|
099dea743b | ||
|
f6e620196d | ||
|
1a0aa37d6f | ||
|
530554d19c | ||
|
e23687c45d | ||
|
02c572b6f1 | ||
|
0d628b4706 | ||
|
5aa1f2e996 | ||
|
341c159d06 | ||
|
3a34b8dae2 | ||
|
ff4e5e4666 | ||
|
adc37b269c | ||
|
845cfcb966 | ||
|
67d2f72a4b | ||
|
75bbb28ef6 | ||
|
e384bfe145 | ||
|
fd234bbf9e | ||
|
aee8841438 | ||
|
ec507308e7 | ||
|
bdc52097b6 | ||
|
0530d22a1d | ||
|
caf1bde49b | ||
|
4bdab667cc | ||
|
636d53cf63 | ||
|
81c193af1f | ||
|
de81da36eb | ||
|
de09ed3fcb | ||
|
be81cc1e0e | ||
|
47673863fb | ||
|
b1f4c06d4e | ||
|
a6e89fe05c | ||
|
3f226b758c | ||
|
e504afbf18 | ||
|
8537d18b16 | ||
|
1e647f799c | ||
|
06b7a91de4 | ||
|
f180ba2fc9 | ||
|
8b2a2afb6f | ||
|
1752b9e6d6 | ||
|
fe690528f7 | ||
|
3b99090879 | ||
|
7d3b35c32c | ||
|
9a25a12879 | ||
|
82dfd10dba | ||
|
b6eda1ad7a | ||
|
e97c2de837 | ||
|
88dffc21f7 | ||
|
889cc5fde2 | ||
|
1fe993ad10 | ||
|
bf6a64b6b5 | ||
|
bf0829231d | ||
|
008fadeaa9 | ||
|
6170243283 | ||
|
f278900cbe | ||
|
0f1ca72171 | ||
|
936e5823dc | ||
|
3710fd3492 | ||
|
02b5b9b05c | ||
|
8e7e736e3e | ||
|
8eb8356dea | ||
|
1d0eecdcb0 | ||
|
ef011fa0d4 | ||
|
a87cb202b1 | ||
|
d92adfbad0 | ||
|
6ee45a1014 | ||
|
36b3cd9188 | ||
|
98eaeaabc8 | ||
|
6aa6191240 | ||
|
c51b0fcafe | ||
|
0997592768 | ||
|
3c4df1e963 | ||
|
fc3e6a6d0a | ||
|
1ae84ea83b | ||
|
195e4c422d | ||
|
444bcdba0a | ||
|
3334364f5f | ||
|
f818fb3ba4 | ||
|
d6e8a5ef22 | ||
|
ce143e06f2 | ||
|
bdb5bc1180 | ||
|
7d79685fe2 | ||
|
4bd637cf88 | ||
|
bcd140fc42 | ||
|
ccd13b7e9e | ||
|
50a69d8d4a | ||
|
6c13e6458f | ||
|
ac5844f393 | ||
|
15d79ef330 | ||
|
828ea96006 | ||
|
11349a71fa | ||
|
9f18045329 | ||
|
a7d148d0ff | ||
|
f826a2ce51 | ||
|
8c4fae8bf2 | ||
|
ed68c8cf04 | ||
|
d7220031d4 | ||
|
d4b877d415 | ||
|
6cb498cdb2 | ||
|
a9d8c0a19f | ||
|
3cda7c1f1b | ||
|
04499c0b76 | ||
|
85dd5dbf8e | ||
|
5e6c645461 | ||
|
8761d0d9ee | ||
|
6e0be6e18c | ||
|
930bdf9dda | ||
|
780ad01ac0 | ||
|
d2855fcfca | ||
|
c59499ec03 | ||
|
eaff52b264 | ||
|
6da09967f8 | ||
|
7d699dcc13 | ||
|
f2ce2eab00 | ||
|
763eebeeba | ||
|
5cb5061d9b | ||
|
9a6931a54c | ||
|
987de8fb6a | ||
|
14c39a0070 | ||
|
872aa19d83 | ||
|
d5b1a8f565 | ||
|
45ff78d068 | ||
|
c5023ad973 | ||
|
1b65a9e523 | ||
|
2d0ebf1ef5 | ||
|
e0ae46e794 | ||
|
832218dbec | ||
|
ba523c627a | ||
|
dae633aa7d | ||
|
d1691e9478 | ||
|
c1b0869c21 | ||
|
1b2a2ebaca | ||
|
05e725174c | ||
|
9abe19317d | ||
|
97fe279f7b | ||
|
dc9246715d | ||
|
4209dc2792 | ||
|
576e21d75d | ||
|
abebeaea1f | ||
|
fc2c8a7c37 | ||
|
fe342c347c | ||
|
d490f903ea | ||
|
6c8e97f825 | ||
|
4ece59385d | ||
|
e58daee088 | ||
|
ec55187033 | ||
|
bbaa0520c0 | ||
|
8bd1785233 | ||
|
72f85ef6c0 | ||
|
b7e7faebad | ||
|
65e6f6054b | ||
|
98de02051e | ||
|
9d35e75fb5 | ||
|
3f5e771a5c | ||
|
de820daf74 | ||
|
49488d19af | ||
|
775b336ee0 | ||
|
8e466dd13c | ||
|
4c3cad97d3 | ||
|
c489143442 | ||
|
7dcaa0c390 | ||
|
69d5ba239a | ||
|
cc423cbe49 | ||
|
15bda15bc9 | ||
|
9f62f37538 | ||
|
da666ade49 | ||
|
fe5401f835 | ||
|
da73317912 | ||
|
5f0aec7570 | ||
|
4f5ba6b044 | ||
|
f6931784a5 | ||
|
d0a572de98 | ||
|
32f778613f | ||
|
60ee7e2b4c | ||
|
51070d0e69 | ||
|
06584518da | ||
|
a404078117 | ||
|
c51e25f8c4 | ||
|
32539dfe6d | ||
|
0da94ac66f | ||
|
062509deee | ||
|
c12f9a378d | ||
|
f0f2cf61da | ||
|
c18bc12cb2 | ||
|
490c1f6b02 | ||
|
b0cd88c462 | ||
|
2e8a059c77 | ||
|
cb5597818d | ||
|
1f9fce6388 | ||
|
760d2f74d0 | ||
|
d6455817e7 | ||
|
71760ea372 | ||
|
3dafe8708b | ||
|
0668046407 | ||
|
97c2dc270c | ||
|
89c13bedbd | ||
|
73f88e47cb | ||
|
db50f04653 | ||
|
08189ee907 | ||
|
2942d0652a | ||
|
5e5c730959 | ||
|
bc4a2c3747 | ||
|
18cce053a3 | ||
|
a64fd9cf3b | ||
|
380afa3130 | ||
|
c3540bc6e0 | ||
|
24b676ce30 | ||
|
b901651ab5 | ||
|
c74b03b4de | ||
|
cf60989ae1 | ||
|
42fef8bbcd | ||
|
685c914227 | ||
|
0471c7ad76 | ||
|
cb44a474fc | ||
|
63511b19a2 | ||
|
b592b0bff8 | ||
|
0a159f06b2 | ||
|
0e76cf9ac8 | ||
|
41ee8fd226 | ||
|
8e025aeeaa | ||
|
fc0f3a2020 | ||
|
6323caf265 | ||
|
ed4a89e4af | ||
|
8043feebd5 | ||
|
09724e907b | ||
|
c16f2ed787 | ||
|
b0f7f37ac8 | ||
|
93b386e16e | ||
|
f0745eb0d9 | ||
|
09ac23b78f | ||
|
f5f30615ba | ||
|
dc0da9662a | ||
|
7c50fa6d55 | ||
|
9e9d28bfa6 | ||
|
86e0cbc1f3 | ||
|
7b80e1fc30 | ||
|
eee9927baf | ||
|
23b8c40cab | ||
|
03a0445775 | ||
|
4a49b23636 | ||
|
3ba509931c | ||
|
5fd0b220cd | ||
|
0c59dd9ed3 | ||
|
3fb123a64a | ||
|
3885e52bb7 | ||
|
4016b1fc52 | ||
|
056bf63866 | ||
|
b389878d23 | ||
|
0e55caacab | ||
|
b383b4b98b | ||
|
8e8b64feaa | ||
|
a1b6353d6b | ||
|
ad2d2e411a | ||
|
af128ec9eb | ||
|
4a49e6d91f | ||
|
befecc7ed6 | ||
|
8c0e534c6b | ||
|
ebe070f9dd | ||
|
d5a52caab8 | ||
|
d88d04dbc4 | ||
|
fd52f9ba50 | ||
|
73c21177e5 | ||
|
b9ceabf128 | ||
|
46207abbc4 | ||
|
a00605b10c | ||
|
467a2bc488 | ||
|
abbfaf6bcf | ||
|
4a9b8c1f72 | ||
|
0ad0f5ed3f | ||
|
f71f360e32 | ||
|
296cb44bc4 | ||
|
1d0e180e1d | ||
|
861df664cf | ||
|
6922f80a87 | ||
|
9e1817a280 | ||
|
0c8ea4a368 | ||
|
1ef099e308 | ||
|
5eaa5ba4db | ||
|
6e239fb280 | ||
|
f20eb4d541 | ||
|
ddc59bc404 | ||
|
5aa0b86d96 | ||
|
a52b833727 | ||
|
a107e45116 | ||
|
ca72a421be | ||
|
2eec18de65 | ||
|
f2ef8e95ab | ||
|
ff074459ad | ||
|
c9bbf0d12a | ||
|
31d2aaa05b | ||
|
2dac7dae32 | ||
|
b3215e8beb | ||
|
31667b18d8 | ||
|
97258c214a | ||
|
c122365a52 | ||
|
95237b23ea | ||
|
ab2f4cd2b7 | ||
|
5f90702b2f | ||
|
defe3c5558 | ||
|
04bf1a4ced | ||
|
7a5afb86a5 | ||
|
97db4f02a0 | ||
|
44005ebf31 | ||
|
2c6076ba97 | ||
|
b7ae902bbc | ||
|
58af94269e | ||
|
50ec0a1917 | ||
|
505d0b700a | ||
|
0a212c91fd | ||
|
ff5cfc0dde | ||
|
12463e40a4 | ||
|
fd37962a58 | ||
|
ef5398ce21 | ||
|
54581f6d9e | ||
|
78d4660282 | ||
|
ea5464ea26 | ||
|
02545b9bea | ||
|
559260020b | ||
|
0c7556ad7f | ||
|
25d880f6c7 | ||
|
c94d8f1c6c | ||
|
492310e6fa | ||
|
76d063f20a | ||
|
f88b259eba | ||
|
999a868c14 | ||
|
485b4a5838 | ||
|
fad09e805f | ||
|
67d2071a32 | ||
|
c8016e90a4 | ||
|
01e5112680 | ||
|
5ea0b57d1b | ||
|
41008551c1 | ||
|
4ad1215873 | ||
|
befc54a444 | ||
|
32fade50e5 | ||
|
59508d5b57 | ||
|
a684d5e4d1 | ||
|
a7440426fd | ||
|
f63c4db469 | ||
|
53a29e35e9 | ||
|
e0cd9a6e06 | ||
|
0e0a568743 | ||
|
e23295f06e | ||
|
9e75e2cb58 | ||
|
8be50b8e3d | ||
|
ebfa9e6577 | ||
|
29f85a7ae2 | ||
|
0c255e2404 | ||
|
3d34d754a9 | ||
|
d241f35625 | ||
|
f1959ff830 | ||
|
6edab1eb34 | ||
|
b728b60051 | ||
|
6547eefffd | ||
|
ecee7122a5 | ||
|
163611bd11 | ||
|
fd961dccb5 | ||
|
10da093422 | ||
|
38a573a48c | ||
|
ee36c36fdd | ||
|
390645e581 | ||
|
5b8febb977 | ||
|
c01c256757 | ||
|
b5374433a5 | ||
|
ac79cc6fe6 | ||
|
badc38d645 | ||
|
1fb1e358bb | ||
|
2bcddd333d | ||
|
95ec47e5b8 | ||
|
97b2838d18 | ||
|
195318b665 | ||
|
de9f704de2 | ||
|
f01da9c73b | ||
|
49f502aef4 | ||
|
bfb0b54f9b | ||
|
b66de1a3c0 | ||
|
b866dcb07f | ||
|
061ebd1b2c | ||
|
4c7025b964 | ||
|
2a06907902 | ||
|
3b494e97cd | ||
|
052c8dd602 | ||
|
0702f97806 | ||
|
e25dfb4fbf | ||
|
744b040c70 | ||
|
7ae218704e | ||
|
b290b25f7a | ||
|
6d0d70364c | ||
|
4fe7fa56c7 | ||
|
bb405e705b | ||
|
f6e707a639 | ||
|
8839f8a8e9 | ||
|
2bf6a536c9 | ||
|
bd2787b562 | ||
|
f2a5134621 | ||
|
bb9261773b | ||
|
67028cdb48 | ||
|
8091a872f3 | ||
|
2d56c6738c | ||
|
b4c75d4898 | ||
|
a2b49ae000 | ||
|
310c325eaa | ||
|
711eed1e77 | ||
|
3fc0a74102 | ||
|
51d22d4a8c | ||
|
319d162f67 | ||
|
5df56bea79 | ||
|
ca228a392e | ||
|
8d8c301662 | ||
|
49944643d2 | ||
|
bf82829e9e | ||
|
ace963b542 | ||
|
e1795e59d5 | ||
|
e8236dfebe | ||
|
be18d8fa5a | ||
|
b8b053e706 | ||
|
fdc95debef | ||
|
0b79c637b6 | ||
|
fe385da850 | ||
|
88eb8e4e47 | ||
|
6ed41f7361 | ||
|
d94cee13f0 | ||
|
5ac443b745 | ||
|
6951f5b8e6 | ||
|
84602f89b0 | ||
|
0efcaa505d | ||
|
86f5af5ca9 | ||
|
94f1707d65 | ||
|
8813e071bc | ||
|
64a2815544 | ||
|
e76435c6c6 | ||
|
c8280a9a88 | ||
|
b65ef189eb | ||
|
b91df10b21 | ||
|
b0199297fd | ||
|
955e70206c | ||
|
5f0c7a7faf | ||
|
5085877eed | ||
|
6124ec7b14 | ||
|
6a2584b840 | ||
|
39c3f408e5 | ||
|
423355ecbf | ||
|
28a11976da | ||
|
a2569e76c0 | ||
|
624c641af5 | ||
|
b2e06ae198 | ||
|
20cbd4012f | ||
|
1257b056dc | ||
|
12c3ab16ae | ||
|
635ef51f82 | ||
|
9656604848 | ||
|
4cf7e5b98f | ||
|
60c9c094a7 | ||
|
46e9d5566a | ||
|
7c3c4e8c81 | ||
|
a3a0c402bc | ||
|
617f4742cd | ||
|
d603de1bfe | ||
|
c8ab99cd0b | ||
|
21ec368927 | ||
|
afbf0ea777 | ||
|
066ddc23e6 | ||
|
21c8933bbb | ||
|
5b53440d27 | ||
|
0e95154869 | ||
|
bd46dd88aa | ||
|
24e1e3018c | ||
|
5243e46ffb | ||
|
af0755d8cf | ||
|
0e2d40c37f | ||
|
357681a5c6 | ||
|
0df4ec45ad | ||
|
56f7c27d18 | ||
|
64e8919e89 | ||
|
38a464a829 | ||
|
4a40184b35 | ||
|
94606d38e2 | ||
|
206c7ca638 | ||
|
f6f94ad7c1 | ||
|
9b49638654 | ||
|
8abc06c8f2 | ||
|
49b4b61a1a | ||
|
f249bbc60a | ||
|
b40dc06b29 | ||
|
0301ced000 | ||
|
4ce9d805b4 | ||
|
3753f64429 | ||
|
abb7bd99ab | ||
|
8201cff7ff | ||
|
db307075cf | ||
|
01db217ab9 | ||
|
3094f8b349 | ||
|
91f6bf5139 | ||
|
d27fa4766d | ||
|
d12decde80 | ||
|
8f1b980337 | ||
|
5f18705358 | ||
|
c738246610 | ||
|
7d99a70e9c | ||
|
02db756b21 | ||
|
fa13e46e87 | ||
|
d1e215e312 | ||
|
b2f387ccac | ||
|
6fc5406901 | ||
|
0edc781b36 | ||
|
10255f2f81 | ||
|
d64589cc48 | ||
|
431bec84fb | ||
|
017e17f9fa | ||
|
74e5cc49f9 | ||
|
a331f35724 | ||
|
b654d824ad | ||
|
266bdccc2e | ||
|
4078f84e8f | ||
|
c6dbaa52f6 | ||
|
633e057d11 | ||
|
14efe6ffda | ||
|
d7ca153c8b | ||
|
0e10c460c3 | ||
|
4cbb93cfc8 | ||
|
1c86bf7514 | ||
|
4efa3b0d45 | ||
|
d18dcc0540 | ||
|
fc4c078f17 | ||
|
7e91b5e446 | ||
|
963805ad48 | ||
|
edde3e3011 | ||
|
5cd74d2845 | ||
|
3b0f2e9551 | ||
|
06e63252e4 | ||
|
b49076ecab | ||
|
ac5517f199 | ||
|
728a5ff20f | ||
|
a496638c72 | ||
|
e47b76fa67 | ||
|
2810ff05b0 | ||
|
b79b02152b | ||
|
d2b324e32b | ||
|
6f04c02cd2 | ||
|
8c7407967e | ||
|
61d25e931e | ||
|
5d1ec604b2 | ||
|
9ac1d3d59e | ||
|
a12ca43284 | ||
|
3301a1b364 | ||
|
d5723968da | ||
|
8421328ee1 | ||
|
13b774b535 | ||
|
41ff87f83b | ||
|
63cd5f42af | ||
|
fdd2194c8f | ||
|
b329ee85ad | ||
|
ece1e73547 | ||
|
caa37a8028 | ||
|
6b22594961 | ||
|
926b74a203 | ||
|
189cadfbb3 | ||
|
d7f6c18c0a | ||
|
9b6b65b8b4 | ||
|
a6dc530441 | ||
|
fd42e7701e | ||
|
21cb8615fd | ||
|
32921491b8 | ||
|
fd15a938c5 | ||
|
c2595273ec | ||
|
f89ee0d422 | ||
|
4fd36454d7 | ||
|
39a4aa5e26 | ||
|
ffafc27104 | ||
|
6df3e57843 | ||
|
21b4ae8f2f | ||
|
e7f3dd5553 | ||
|
ddf0f06834 | ||
|
acaa931e11 | ||
|
9e72971ff0 | ||
|
82c894932a | ||
|
aeb418a99e | ||
|
5a6665e57f | ||
|
8459d423b8 | ||
|
60a41bfc75 | ||
|
f5d4e745c7 | ||
|
446e9625af | ||
|
888e1c0b8a | ||
|
8e6010fd71 | ||
|
4f0a02594c | ||
|
f8b438d9dc | ||
|
de1c9c6fea | ||
|
3f7a859e07 | ||
|
922c18ee49 | ||
|
066f562c5e | ||
|
8be40e637b | ||
|
fd4da77084 | ||
|
bc0af02c97 | ||
|
1dff9aff8a | ||
|
e74a5a71eb | ||
|
369a3d0f5f | ||
|
c7314cc606 | ||
|
de500ad8f9 | ||
|
9383445e0b | ||
|
1a36f2689d | ||
|
29980016f3 | ||
|
9fff419346 | ||
|
391cff69d3 | ||
|
0c48729611 | ||
|
ad27007c3c | ||
|
53c05c31c7 | ||
|
b0522cb491 | ||
|
6038730e53 | ||
|
9ac4998478 | ||
|
ac06111163 | ||
|
0bed511a6c | ||
|
43c3922a3d | ||
|
f113946e66 | ||
|
b69c474fa2 | ||
|
7a9f7c4fb9 | ||
|
94fc2c3ecf | ||
|
1c3fd5c38b | ||
|
1ec11dc03d | ||
|
c34f5413a3 | ||
|
d63c6818df | ||
|
9d55283b3b | ||
|
3d5e941aef | ||
|
e28702eb40 | ||
|
6c0608f0dd | ||
|
d70f970b15 | ||
|
ea62fd0e16 | ||
|
1afad4f240 | ||
|
95c3e436dc | ||
|
0656a49332 | ||
|
7159237104 | ||
|
505bff6f45 | ||
|
3652ede130 | ||
|
9139b4d269 | ||
|
597336b491 | ||
|
f7b793b7bf | ||
|
e4cdc2397a | ||
|
2b458fc642 | ||
|
af2acbd46e | ||
|
59a2817e5c | ||
|
3f5605f22e | ||
|
02a6312912 | ||
|
b7ddd02fc6 | ||
|
ea56481ead | ||
|
7cbe399f1f | ||
|
6f2e5a0eb7 | ||
|
39b2803914 | ||
|
6c2fe934fd | ||
|
130a69eeae | ||
|
d205f88fb8 | ||
|
3c66f7c58a | ||
|
ee402ec5dc | ||
|
3a38fe4130 | ||
|
ccc3b63d7c | ||
|
8f22365959 | ||
|
46f10bacb2 | ||
|
3fbc2f4458 | ||
|
915db9d6c9 | ||
|
001ca45c57 | ||
|
c490838202 | ||
|
ffa489d211 | ||
|
b63395435f | ||
|
5bc53c08ce | ||
|
03663ce91a | ||
|
9a61ff8347 | ||
|
2e0b63bc67 | ||
|
bad60f39cd | ||
|
434793711b | ||
|
b9922105f0 | ||
|
e0214056ce | ||
|
7594cbd902 | ||
|
5c6cc29304 | ||
|
c9f4a09de0 | ||
|
e0c8ac01d2 | ||
|
11f55359c6 | ||
|
56e3321394 | ||
|
285f6bb6ac | ||
|
f4598fbd0a | ||
|
8f1b4cc8e5 | ||
|
b5caca54cd | ||
|
f4f854ae4f | ||
|
dcdfa79024 | ||
|
414d2aba54 | ||
|
927ab6d127 | ||
|
92065a1a10 | ||
|
dd42e30c61 | ||
|
d617bafb08 | ||
|
1da055dc34 | ||
|
961abb3cf1 | ||
|
76ebfb2243 | ||
|
d9029c2efc | ||
|
281d61bbe1 | ||
|
1fbb81a4d9 | ||
|
cf80c63c22 | ||
|
f121ce1ed5 | ||
|
9330945623 | ||
|
52419fd7ad | ||
|
68fdbe60cc | ||
|
6334f430fe | ||
|
eca54585b0 | ||
|
ac1ed40b80 | ||
|
3d71045159 | ||
|
58d7a4784d | ||
|
b1b7da4f10 | ||
|
ae85698a2b |
344 changed files with 81281 additions and 9146 deletions
69
.github/workflows/scala.yml
vendored
Normal file
69
.github/workflows/scala.yml
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
name: Scala CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-v2
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Cache SBT
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ivy2/cache
|
||||
~/.sbt
|
||||
key: ${{ runner.os }}-sbt-${{ hashFiles('**/build.sbt') }}
|
||||
|
||||
- name: Cache tools
|
||||
id: tools
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/tools
|
||||
key: ${{ runner.os }}-tools_v4
|
||||
|
||||
- name: Setup env
|
||||
run: echo "$HOME/tools/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Install cached tools
|
||||
if: steps.tools.outputs.cache-hit != 'true'
|
||||
run: source tools.sh && (cd ~/ && install_verilator)
|
||||
|
||||
- name: Install uncached tools
|
||||
run: (cd .. && git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev)
|
||||
|
||||
- name: Compile tests
|
||||
run: sbt "+test:compile"
|
||||
|
||||
- name: Test Dhrystones
|
||||
run: make regression_dhrystone -C scripts/regression
|
||||
|
||||
- name: Test Baremetal
|
||||
run: make regression_random_baremetal -C scripts/regression
|
||||
|
||||
- name: Test Machine OS
|
||||
run: make regression_random_machine_os -C scripts/regression
|
||||
|
||||
- name: Test Linux
|
||||
run: make regression_random_linux -C scripts/regression
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
*.class
|
||||
*.log
|
||||
*.bak
|
||||
.*.swp
|
||||
|
||||
# sbt specific
|
||||
.cache/
|
||||
|
@ -24,6 +25,7 @@ out
|
|||
bin/
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
.cache-main
|
||||
|
||||
|
@ -33,17 +35,22 @@ bin/
|
|||
*.cf
|
||||
*.json
|
||||
*.vcd
|
||||
*.fst*
|
||||
!tester/src/test/resources/*.vhd
|
||||
obj_dir
|
||||
*.logTrace
|
||||
*.yaml
|
||||
*.memTrace
|
||||
*.regTrace
|
||||
*.debugTrace
|
||||
*.tcl
|
||||
*.o
|
||||
*.bin
|
||||
explor
|
||||
|
||||
mill
|
||||
|
||||
simWorkspace/
|
||||
tmp/
|
||||
/archive.tar.gz
|
||||
*.out32
|
||||
*.out32
|
||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/test/resources/VexRiscvRegressionData"]
|
||||
path = src/test/resources/VexRiscvRegressionData
|
||||
url = https://github.com/SpinalHDL/VexRiscvRegressionData.git
|
107
.travis.yml
107
.travis.yml
|
@ -1,64 +1,89 @@
|
|||
language: scala
|
||||
|
||||
dist: xenial
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
|
||||
# See 'project/Version.scala'
|
||||
scala:
|
||||
- 2.11.6
|
||||
- 2.11.12
|
||||
|
||||
sbt_args: -no-colors -J-Xss2m
|
||||
|
||||
script:
|
||||
- export VEXRISCV_REGRESSION_CONFIG_COUNT=100
|
||||
- export VEXRISCV_REGRESSION_FREERTOS_COUNT=no
|
||||
- sbt -jvm-opts travis/jvmopts.compile compile
|
||||
- sbt -jvm-opts travis/jvmopts.test test
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- git
|
||||
- make
|
||||
- autoconf
|
||||
- g++
|
||||
- flex
|
||||
- bison
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
# - oraclejdk7
|
||||
# - openjdk7
|
||||
- openjdk10
|
||||
|
||||
env:
|
||||
- secure: "v7FHP8yK/zixpv1ML05qcRhZfDVDFdTmTPjfMZHL7gmrJveVDgze22x4tY4tB1+JEXhKuVTYvimOrX/Ok+rOOT5gVKLowv4PUQwCR+HgWVIbqjcfZNLsa369v03/p4K/zbjJSiXFahZYOXa0ApED2KWHcVfCrNsPv0UF7YZGiIa1Q/lPBwfmpN1rLih2Mpgn4KVaJky22t7JXJyVrNdGVmIA51slVbyFwFAE8Ww/0tkC+i2PUcWWRMIxtXP4iyq/9Npcq5VdqOatKfWHqAElLfKSPNMYLMlcyxyNpNx4paq8cL6fQxFcBLi9M2msz2i/qpKv30a0tzNo5bQQgucAXOQJB2Buks728upLuqsr+k25hwcqrtjyMOr9UQkt7qXAJH/0kimW7aW1yoMxbm/6mNG98X9D1EzNRewHAKatwJeFy1bw5qIuSQxPBwQMGloManrHOHGotmHKk7Y+dgM/z1UlaAdxSQuKWGXBc8QlQvif8puPYEdJMoInJNRxiWfYu06XnmzTXgMketK7RdULM9DVYzw8hzS2EIWKu8Oa0zn0PTevD2YeJNd4G8mDqO0vz5hloIc7pFsq/exQUB/kFozfCsnvhW8P+MPN0LpuSpptBQTsLWbM5BH0hd46HoWcneDdlMvVrUcgsTPmmSroIkLIEUo+Y2iN5eQHPPp85Cw="
|
||||
jobs:
|
||||
include:
|
||||
- stage: prepare cache-verilator
|
||||
script:
|
||||
- cp scripts/regression/verilator.mk $HOME/makefile
|
||||
- cd $HOME
|
||||
- make verilator_binary
|
||||
- &test
|
||||
stage: Test
|
||||
name: Dhrystone
|
||||
script:
|
||||
- make regression_dhrystone -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Baremetal
|
||||
script:
|
||||
- make regression_random_baremetal -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Machine OS
|
||||
script:
|
||||
- make regression_random_machine_os -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Machine OS
|
||||
script:
|
||||
- make regression_random_machine_os -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Mixed
|
||||
script:
|
||||
- make regression_random -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Linux
|
||||
script:
|
||||
- make regression_random_linux -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Linux
|
||||
script:
|
||||
- make regression_random_linux -C scripts/regression
|
||||
|
||||
before_install:
|
||||
# JDK fix
|
||||
- cat /etc/hosts # optionally check the content *before*
|
||||
- sudo hostname "$(hostname | cut -c1-63)"
|
||||
- sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts
|
||||
- cat /etc/hosts # optionally check the content *after*
|
||||
- cd ..
|
||||
|
||||
# Verilator
|
||||
- sudo apt-get install git make autoconf g++ flex bison -y # First time prerequisites
|
||||
- git clone http://git.veripool.org/git/verilator # Only first time
|
||||
- unset VERILATOR_ROOT # For bash
|
||||
- cd verilator
|
||||
- git pull # Make sure we're up-to-date
|
||||
- git checkout verilator_3_916
|
||||
- autoconf # Create ./configure script
|
||||
- ./configure
|
||||
- make -j$(nproc)
|
||||
- sudo make install
|
||||
- cd ..
|
||||
|
||||
- git clone https://github.com/SpinalHDL/SpinalHDL.git
|
||||
|
||||
- git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
|
||||
- cd VexRiscv
|
||||
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
|
||||
#- curl -X POST -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/publish
|
||||
#- sbt compile
|
||||
|
||||
- export VERILATOR_ROOT=$HOME/verilator
|
||||
- export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||
|
||||
before_cache:
|
||||
# Tricks to avoid unnecessary cache updates
|
||||
- find $HOME/.ivy2 -name "ivydata-*.properties" -delete
|
||||
- find $HOME/.sbt -name "*.lock" -delete
|
||||
- rm -fv $HOME/.ivy2/.sbt.ivy.lock
|
||||
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
|
||||
- find $HOME/.sbt -name "*.lock" -print -delete
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.ivy2/cache
|
||||
- $HOME/.sbt/boot/
|
||||
- $HOME/.sbt
|
||||
- $HOME/verilator
|
||||
|
||||
|
|
BIN
assets/fpuDesign.png
Normal file
BIN
assets/fpuDesign.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 130 KiB |
46
build.sbt
46
build.sbt
|
@ -1,46 +1,20 @@
|
|||
//name := "VexRiscv"
|
||||
//
|
||||
//organization := "com.github.spinalhdl"
|
||||
//
|
||||
//version := "1.0.0"
|
||||
//
|
||||
//scalaVersion := "2.11.6"
|
||||
//
|
||||
//EclipseKeys.withSource := true
|
||||
//
|
||||
//libraryDependencies ++= Seq(
|
||||
// "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.1",
|
||||
// "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.1",
|
||||
// "org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
// "org.yaml" % "snakeyaml" % "1.8"
|
||||
//)
|
||||
//
|
||||
//
|
||||
//
|
||||
//addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
||||
//scalacOptions += "-P:continuations:enable"
|
||||
//fork := true
|
||||
val spinalVersion = "1.10.2a"
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
inThisBuild(List(
|
||||
organization := "com.github.spinalhdl",
|
||||
scalaVersion := "2.11.6",
|
||||
version := "1.0.0"
|
||||
scalaVersion := "2.12.18",
|
||||
version := "2.0.0"
|
||||
)),
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.2",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.2",
|
||||
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
"com.github.spinalhdl" %% "spinalhdl-core" % spinalVersion,
|
||||
"com.github.spinalhdl" %% "spinalhdl-lib" % spinalVersion,
|
||||
compilerPlugin("com.github.spinalhdl" %% "spinalhdl-idsl-plugin" % spinalVersion),
|
||||
"org.scalatest" %% "scalatest" % "3.2.17",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
),
|
||||
name := "VexRiscv"
|
||||
)/*.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
||||
lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "SpinalHDL-sim")
|
||||
lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "SpinalHDL-core")
|
||||
lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "SpinalHDL-lib")*/
|
||||
)
|
||||
|
||||
|
||||
addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
||||
scalacOptions += "-P:continuations:enable"
|
||||
fork := true
|
||||
fork := true
|
||||
|
|
28
build.sc
Normal file
28
build.sc
Normal file
|
@ -0,0 +1,28 @@
|
|||
import mill._, scalalib._
|
||||
|
||||
val spinalVersion = "1.10.1"
|
||||
|
||||
object ivys {
|
||||
val sv = "2.11.12"
|
||||
val spinalCore = ivy"com.github.spinalhdl::spinalhdl-core:$spinalVersion"
|
||||
val spinalLib = ivy"com.github.spinalhdl::spinalhdl-lib:$spinalVersion"
|
||||
val spinalPlugin = ivy"com.github.spinalhdl::spinalhdl-idsl-plugin:$spinalVersion"
|
||||
val scalatest = ivy"org.scalatest::scalatest:3.2.5"
|
||||
val macroParadise = ivy"org.scalamacros:::paradise:2.1.1"
|
||||
val yaml = ivy"org.yaml:snakeyaml:1.8"
|
||||
}
|
||||
|
||||
trait Common extends ScalaModule {
|
||||
override def scalaVersion = ivys.sv
|
||||
override def scalacPluginIvyDeps = Agg(ivys.macroParadise, ivys.spinalPlugin)
|
||||
override def ivyDeps = Agg(ivys.spinalCore, ivys.spinalLib, ivys.yaml, ivys.scalatest)
|
||||
override def scalacOptions = Seq("-Xsource:2.11")
|
||||
}
|
||||
|
||||
object VexRiscv extends Common with SbtModule{
|
||||
override def millSourcePath = os.pwd
|
||||
override def moduleDeps: Seq[JavaModule] = super.moduleDeps
|
||||
|
||||
object test extends SbtModuleTests with TestModule.ScalaTest
|
||||
}
|
||||
|
1
doc/diagram.drawio
Normal file
1
doc/diagram.drawio
Normal file
|
@ -0,0 +1 @@
|
|||
<mxfile host="Electron" modified="2022-10-26T08:46:23.573Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="UNzW2AFYAA4diG_noPwE" version="16.5.1" type="device"><diagram id="U7yDgwaCbtEdI7JvCxo2" name="Page-1">7VxtV6s4EP41/aiH99KPSvWuu3WPR929ez9GSEv2UtINwbb3128CAQppC9am1VqPR8mQTMMzzyQzYbRnetPFNwJm4T0OYNQztGDRM4c9w3Asl/3kgqUQaGYumBAU5CK9EjyhX1AINSFNUQCTWkeKcUTRrC70cRxDn9ZkgBA8r3cb46j+qTMwgZLgyQeRLP2OAhrmUtfWKvlvEE3C4pN1TdyZgqKzECQhCPB8RWTe9EyPYEzzq+nCgxHHrsAlH3e74W45MQJj2mXAMHwxk/tnL70xvNtbPe6nf/y6EFpeQZSKB+4ZTsT0XSczEPNZ06WAwvkv5VO9HuOYXiSZoa5YB92YLaqb7GrCf99C6oeFKjanXFt+T8BRKjYITuMA8mnq7PY8RBQ+zYDP784ZqZgspNNI3OYfL2ji8mlSgn+WpuEdApCEpTLeeACUQhJnEjbfcgavkFC42IimXtqIcRviKaRkybqIAaYlzCp4bZuiPa9Y4ghRuEKQgg1A8HJSaq5Mxy6E9d5gSVOy5N9w8YgS//VqgawRitPFQ4R8L0LsAZsWYDjQEkwPR5gweYxjyAFHUdQQgQhNOJ4RHPNhHEjEXOZKiKcoCLhmziEfxZNR1m1oVZJHAQgXYTZ8HGWeEbKBkGm4nmE2ywwh+5p9M8w87dLu2WyuHmvrVZt98+6Eejhm0wcoMx8ECZ3DhE+OYAooeMmeVCv4I55c3wMRDLdOBGsgE0F31zDBVMUES2LCXc+wtnid1u51ewDK0ts9xjikx9gSTsMPidMaQq3DyVWFk6NojxhCn0ULX2qTcI68SfQVmfJmAf2Ufi1brnHLg9rSVWTLezjFfHpfx5SOcWRTDhSZ8jth5ngB/s8vZU37yNYs9u+NMQSLVkM8wTGIRhjPBD7/QkqXAk6QUlzHmmFBlv/w8SzsFc0fQl3WGC5qrWXRWiC6Moy1fhQa2XU1iDfKMXFwxTPnXhnvM8kt4iBk9/Ong4GUODcsxhDAKfHhNqjyfhSQCaRtIYjMAAIjQNFrfR7r7CmGPuAs+SkjLWNwadcXdatBivwJxLjV5LqpypJUOQ1V+UNKqjKKlc/0DtbpZ9Z1ZJ3TkXV9Jawz3Q1B4Vs5JynqH5hxxplxHRnX78g49zCMG+yJcY52YMaZZ8Z1ZJzbkXGDgzDOaQZbOzOueWqmmnFt50HvYlyNbxX9Whinr/CtYt/RGdc1lrPOu+pWxjkKGXehXWr6oE473TgG8bJPeIAEMbwgOd6Oa5933K1s7Ktg437WpP3ng1oD7F3XkOYRvqRItdVUHSjd3/91ykdJVoeDQfOQR0mGyqOksvG28KO4/mjhx+CoK77k8vrOa8fg0tEH1dd2tYpXkgKIva8k3tPjKa8kxmBDALCyklgHXUnk+pCH0Z3Xsryof9vdBGrdkntYoOTyCW909+fzh0Nq3cvkwyJlq9icWtKGnVKR3fLtPW5ORtfkWM2Rs7Q5NXPazpuT0aJI9XakMjn+RAeA+09Ym0VHzWqizgnrpuqlQzFEScJ6Zohk2J0DXElRc4NSzRBVhTND+JJOTjmolSoTjx2BmCrS4zVp7naXPZpLWmbDk+zBpWvuuLPb7boUO6YppyjBdZpIJuZIj8ALjOqGK4rSfYY6P1HeXJZOIHPllZLwerX5cJuziD8zEYN7JbVXjb2Fqhtdi20RfU0EN+9khe7WR+DxOIFqDKbi5djndT/bZC7jauVXQ+GuntiiVrVTylXy6HSccsO7yE/tlO6Xdkqj34wumfc4u3mifDYl61LtfvKbnFmE/DvuTSSlp+KHG+qe9u+HF1bDfuoc0VJakPm2o6wPXjqiqLx3f69kjlsSYqk403jzkt7Gh4ShQIsefgSSBPmFWHTTj7kzSHGV845sqd+uSzUp5GOM35+vvp3GhmBtOAf/mIEZa1Z/xp93r/4XgnnzPw==</diagram></mxfile>
|
592
doc/gcdPeripheral/README.md
Normal file
592
doc/gcdPeripheral/README.md
Normal file
|
@ -0,0 +1,592 @@
|
|||
# Tutorial on Implementing a Peripheral for the VexRiscv Based Murax SoC
|
||||
**By**
|
||||
|
||||
**Sallar Ahmadi-Pour - Researcher, University of Bremen, Group of Computer Architecture**
|
||||
|
||||
[http://www.informatik.uni-bremen.de/agra/projects/risc-v/](http://www.informatik.uni-bremen.de/agra/projects/risc-v/)
|
||||
|
||||
[http://www.informatik.uni-bremen.de/agra/](http://www.informatik.uni-bremen.de/agra/)
|
||||
|
||||
|
||||
## 1. Introduction
|
||||
Traditional hardware design often requires using languages like VHDL and Verilog and tooling that don't catch errors that can be caught with static analysis of the design. Additionally, information developers receive from the tools is scarce and often lead inexperienced developers on an odyssey. Currently emerging tools (Verilator, Yosys, etc.) for hardware design and languages for hardware description (SpinalHDL, Amaranth, etc.) tackle these and other existing issues.
|
||||
|
||||
Projects like SpinalHDL and the thereon based highly configurable VexRiscv processor experience a rise in popularity and usage amongst academic and commercial users. The increased popularity also requires an increase in educational resources. Due to the specific popularity in the academic environment it only seems natural that researchers document their approaches and insights (not only in peer reviewed publications in a journal). This will allow the next generation of hardware designers to extend and explore big projects like VexRiscv.
|
||||
|
||||
## 2. Our Goal for this Tutorial
|
||||
Murax SoC is a VexRiscv configuration that is a very lightweight RISC-V platform.
|
||||
It features a basic set of peripherals (UART, GPIO, Prescalers and Timers) around a pipelined memory bus and Apb3 peripheral bus.
|
||||
The Murax SoC features enough to more than a toy system and being small and thus offering space for extension.
|
||||
|
||||
For the choice of possible algorithms, that we want to describe in hardware rather than software, the algorithm for calculating the Greatest Common Divisor (GCD) is a good example to start off. There are many digital design resources available on designing a GCD module.
|
||||
|
||||
We will add the hardware peripheral module to the Murax on the Apb3 bus with memory mapped registers to control the module and transfer the data around for the calculation.
|
||||
In this way we transfer the resources the software to the hardware implementation.
|
||||
The aspects we will shed some light upon will be
|
||||
|
||||
a) How do we implement an algorithm that we know from the software domain in a hardware implementation suited for FPGAs?
|
||||
|
||||
b) How do we prepare and integrate a new peripheral into the Murax domain and map its control and data ports via memory mapped registers?
|
||||
|
||||
c) How do we extend the software to use the peripheral easily in our baremetal code?
|
||||
|
||||
For a) we will start off the pseudocode of the GCD and work our way to a hardware implementation in SpinalHDL.
|
||||
We will evaluate that design in a SpinalHDL testbench with Verilator as the simulation backend and drive the testbench with randomly generated values which we compare to a software implementation of the same algorithm.
|
||||
For b) we will look into the features of SpinalHDL and the structure of the Murax SoC to get an idea where and how to integrate our peripheral.
|
||||
Before adding the peripheral into the Murax we also need to decide on the details of memory mapping our control and data ports to memory mapped registers (i.e, addresses, write/read/clear modes, etc.).
|
||||
|
||||
At the end there is a small list of possible extensions from which anyone can continue with their own additions.
|
||||
|
||||
## 3. GCD HW Implementation
|
||||
Let us start the HW implementation by looking at some kind of specification.
|
||||
|
||||
```c
|
||||
// Pseudocode of the Euclids algorithm for calculating the GCD
|
||||
inputs: [a, b]
|
||||
outputs: [ready, a]
|
||||
ready := False
|
||||
while(!ready):
|
||||
if(a > b):
|
||||
a := a - b
|
||||
else if(b > a):
|
||||
b := b - a
|
||||
else:
|
||||
ready := True
|
||||
```
|
||||
|
||||
The pseudocode shows the GCD algorithm we want to implement in hardware.
|
||||
Implementing algorithms in hardware in the Register Transfer Level (RTL) style will require you to separate the control path (so if, else, while, for) and the data path (moving, calculating and comparing data).
|
||||
Inevitably results from data and comparisons affect the control flow and the control flow affects the data flow.
|
||||
Thus the two paths need to communicate the shared information.
|
||||
But let us start at defining the interface of our module that will calculate the GCD.
|
||||
|
||||

|
||||
|
||||
Our pseudocode already defines some in- and outputs that can aid us in defining the interface for our module.
|
||||
At this point we don't want to think about which bus we connect our module to (APB, AXI, Wishbone, etc.).
|
||||
We take care about that part later.
|
||||
We simply know we have our input integers A and B, a signal to indicate the start of the calculation, the result and a signal indicating the completion of the calculation.
|
||||
We choose 32 bit integers and use a valid-ready mechanism (we add a valid signal to kick of the calculation).
|
||||
The interface features the values A, B and result as the data signals, valid and ready are control signals.
|
||||
Signals for reset and clock are omitted for readability (unless explicitly used these are handled by SpinalHDL internally anyways).
|
||||
|
||||
From this top level perspective we can describe the behavior as follows: Once we apply a set of operands A and B and then apply the valid signal the module calculates the GCD for a variable amount of clock cycles.
|
||||
We know the result is ready and can be read once the ready signal is asserted.
|
||||
Inside the GCD module we will have two other modules: the data path GCDData and the control path GCDCtrl.
|
||||
We notice again, the data signals (opA, opB and result) belong to our data path and the control signals (valid and ready) belong to our control path.
|
||||
|
||||

|
||||
|
||||
The data path will consist of some basic RTL blocks like multiplexers, a subtraction, comparators and registers.
|
||||
The elements are connected and arranged such that they represent the dataflow of the algorithm.
|
||||
Parts of the data path are enabled by the control path.
|
||||
The control path will be represented by a Finite State Machine (FSM), which orchestrates the data paths calculation of the result.
|
||||
|
||||

|
||||
|
||||
The diagram of the data path shows the processing elements for our algorithm in hardware, with their control input and outputs respectively.
|
||||
From this we can already see what the interface towards the control path looks like.
|
||||
The control path needs to know the results of the comparisons.
|
||||
Vice versa the data path gets controlled through selecting the subtract operands (or more precisely their order), the register enables and an initiation signal for a defined start state.
|
||||
In the data path, the D-Flipflops (DFF) hold the values A and B that are used for the calculation and they change value throughout the computation.
|
||||
A subtraction which is set up for a computation such that `r = x - y` with x being the "left" and y being the "right" operand.
|
||||
The left and right operands are multiplexed from our control path inputs.
|
||||
Two comparators compute the greater than (cmpAgtB) and less than (cmpAltB) operation.
|
||||
The result, the GCD of A and B, will be available in the A register after the calculation is done.
|
||||
Completion of the calculation is signaled by the control path.
|
||||
|
||||

|
||||
|
||||
In the diagram of the control path we see the same interface (with inverse directions — this information will be helpful later in SpinalHDL).
|
||||
The interface of the control path are the top level valid signal, the ready signal indicating the finished computation, the results of the two comparisons `A > B` (*cmpAgtB*) and `B > A` (*cmpAltB*).
|
||||
Initially the FSM is in an idle state, waiting for the valid signal to be asserted, on exit of this state, the init signal is set to 1 to clock in the values of A and B into their respective registers.
|
||||
Similar to the pseudocode the FSM loops for the calculation and based on the comparators of the data path and orchestrates the data path to calculate either `a := a - b` or `b := b - a`.
|
||||
If both if the comparators outputs are 0, the end of the calculation is reached.
|
||||
Within the `calcDone` state the `ready` signal is set to 1.
|
||||
With the entry of the `idle` state the module becomes ready to calculate another GCD.
|
||||
The control path drives all the outputs based on the state in the state machine (Moore FSM).
|
||||
The guards on the transitions show the condition with which the respective transition occurs.
|
||||
These block diagrams, digital logic and the FSM can be quickly implemented in SpinalHDL, things like the `DataControlIF` that interconnect between the data path and control path can be quickly created and connected in SpinalHDL as well.
|
||||
|
||||
## 4. SpinalHDL implementation
|
||||
First we can take a look at the interface between the data and control path.
|
||||
|
||||
```scala
|
||||
// in GCDTop.scala
|
||||
case class GCDDataControl() extends Bundle with IMasterSlave{
|
||||
val cmpAgtB = Bool
|
||||
val cmpAltB = Bool
|
||||
val loadA = Bool
|
||||
val loadB = Bool
|
||||
val init = Bool
|
||||
val selL = Bool
|
||||
val selR = Bool
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(loadA, loadB, selL, selR, init)
|
||||
in(cmpAgtB, cmpAltB)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We can define a Bundle that implements the `IMasterSlave` Interface (see the [Bundle documentation](https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Data%20types/bundle.html?highlight=master%20slave#master-slave)), which allows us to use a operator (`<>`) to interconnect modules and their signals without explicitly describing each wire and connection (other than inside the Bundle from above).
|
||||
In the Bundle we can define the signals with their types.
|
||||
We override the `asMaster()` Method (line 10 to 13) from the `IMasterSlave` interface.
|
||||
In the `asMaster()` Method we define the signal direction from the point of view of the control path.
|
||||
Thus `cmpAgtB` and `cmpAltB` are inputs and `loadA`, `loadB`, `selL`, `selR`, `init` are outputs.
|
||||
SpinalHDL will infer the directions for the data path side when we will use the `<>`-Operator.
|
||||
With that our top level module will look very tidy:
|
||||
|
||||
```scala
|
||||
// in GCDTop.scala
|
||||
class GCDTop() extends Component {
|
||||
val io = new Bundle {
|
||||
val valid = in Bool()
|
||||
val ready = out Bool()
|
||||
val a = in(UInt(32 bits))
|
||||
val b = in(UInt(32 bits))
|
||||
val res = out(UInt(32 bits))
|
||||
}
|
||||
val gcdCtr = new GCDCtrl()
|
||||
gcdCtr.io.valid := io.valid
|
||||
io.ready := gcdCtr.io.ready
|
||||
val gcdDat = new GCDData()
|
||||
gcdDat.io.a := io.a
|
||||
gcdDat.io.b := io.b
|
||||
io.res := gcdDat.io.res
|
||||
gcdCtr.io.dataCtrl <> gcdDat.io.dataCtrl
|
||||
}
|
||||
```
|
||||
|
||||
Lines 2 to 8 define the input/output Bundle inline, lines 9 and 12 instantiate the control and data path. All other lines are interconnecting the IO signals. Note in line 16 we interconnect the control and data path by using the `<>`-Operator as they use the shared interface description from earlier as a input (called `dataCtrl` in the design). We will see this in the respective modules input/output bundles.
|
||||
|
||||
Our data path in SpinalHDL looks like this:
|
||||
|
||||
```scala
|
||||
// in GCDData.scala
|
||||
class GCDData() extends Component {
|
||||
val io = new Bundle {
|
||||
val a = in(UInt(32 bits))
|
||||
val b = in(UInt(32 bits))
|
||||
val res = out(UInt(32 bits))
|
||||
val dataCtrl = slave(GCDDataControl())
|
||||
}
|
||||
//registers
|
||||
val regA = Reg(UInt(32 bits)) init(0)
|
||||
val regB = Reg(UInt(32 bits)) init(0)
|
||||
// compare
|
||||
val xGTy = regA > regB
|
||||
val xLTy = regA < regB
|
||||
// mux
|
||||
val chX = io.dataCtrl.selL ? regB | regA
|
||||
val chY = io.dataCtrl.selR ? regB | regA
|
||||
// subtract
|
||||
val subXY = chX - chY
|
||||
// load logic
|
||||
when(io.dataCtrl.init){
|
||||
regA := io.a
|
||||
regB := io.b
|
||||
}
|
||||
when(io.dataCtrl.loadA){
|
||||
regA := subXY
|
||||
}
|
||||
when(io.dataCtrl.loadB){
|
||||
regB := subXY
|
||||
}
|
||||
io.dataCtrl.cmpAgtB := xGTy
|
||||
io.dataCtrl.cmpAltB := xLTy
|
||||
io.res := regA
|
||||
}
|
||||
```
|
||||
|
||||
Lines 2 to 7 show the Bundle for the IO signals. Note the signal in line 6 (`dataCtrl`), we use the defined Bundle from earlier and give it the direction `slave()` instead `in()` or `out()`.
|
||||
This tells SpinalHDL to infer the directions of the Bundle signals according to the `asMaster()` method (in that case the inverse directions).
|
||||
We will see this again in the control path.
|
||||
The rest of the module (or components, thats how SpinalHDL modules are called) consists of defining signals, registers, and behavior.
|
||||
Registers can be defined through a `Reg()` components that takes a type and optionally a reset value (via `init()`).
|
||||
We can write to the register in our `when()` Blocks which could be interpreted as the enable signals for the registers.
|
||||
(* Side note: technically we describe a multiplexing onto each register as we have multiple cases of enables and different data sources, but we can abstract from that in SpinalHDL a bit and keep it in the back of our minds*).
|
||||
|
||||
Now for the control path of our GCD module:
|
||||
```scala
|
||||
// in GCDCtrl.scala
|
||||
class GCDCtrl() extends Component {
|
||||
val io = new Bundle {
|
||||
val valid = in Bool()
|
||||
val ready = out Bool()
|
||||
val dataCtrl = master(GCDDataControl())
|
||||
}
|
||||
val fsm = new StateMachine{
|
||||
io.dataCtrl.loadA := False
|
||||
io.dataCtrl.loadB := False
|
||||
io.dataCtrl.init := False
|
||||
io.dataCtrl.selL := False
|
||||
io.dataCtrl.selR := False
|
||||
io.ready := False
|
||||
val idle : State = new State with EntryPoint{
|
||||
whenIsActive{
|
||||
when(io.valid){
|
||||
io.dataCtrl.init := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
}
|
||||
val calculate : State = new State{
|
||||
whenIsActive{
|
||||
when(io.dataCtrl.cmpAgtB){
|
||||
goto(calcA)
|
||||
}.elsewhen(io.dataCtrl.cmpAltB){
|
||||
goto(calcB)
|
||||
}.elsewhen(!io.dataCtrl.cmpAgtB & !io.dataCtrl.cmpAgtB){
|
||||
goto(calcDone)
|
||||
}
|
||||
}
|
||||
}
|
||||
val calcA : State = new State{
|
||||
whenIsActive{
|
||||
io.dataCtrl.selR := True
|
||||
io.dataCtrl.loadA := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
val calcB : State = new State{
|
||||
whenIsActive{
|
||||
io.dataCtrl.selL := True
|
||||
io.dataCtrl.loadB := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
val calcDone : State = new State{
|
||||
whenIsActive{
|
||||
io.ready := True
|
||||
goto(idle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The lines 2 to 6 show the input/output signals again, and this time the `dataCtrl` signal, at line 5, shows the direction as `master()`.
|
||||
This will apply the directions that we set in the first code snipped.
|
||||
SpinalHDL offers a library to build FSMs and since this module is only that, our control path is descriptive.
|
||||
We set default values for outputs (lines 8 to 13) and apply the according value in the respective state.
|
||||
|
||||
The API for FSMs in SpinalHDL offers much more than we use here.
|
||||
In each state we can describe actions for `onEntry`, `onExit`, `whenIsNext` and for `whenIsActive` phases (see the [State Machine documentation](https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Libraries/fsm.html)).
|
||||
The `onEntry` phase refers to the cycle before entering the state, `onExit` will be executed if the next cycle will be in a different state, and `whenIsNext` will be executed if the state machine will be in that state in the next cycle.
|
||||
That resembles the capabilities of FSM we have in UML/SysML or in StateCharts.
|
||||
There is also the possibility to nest FSMs hierarchically or have delay states for a certain amount of cycles.
|
||||
Describing these things in classic HDL is a lot of boilerplate that SpinalHDL can generate for us instead.
|
||||
|
||||
But with these modules we can already run some first simulations, testing our design for functionality.
|
||||
And as traditional HDLs go we need a testbench for this.
|
||||
This applies to SpinalHDL as well.
|
||||
The default way for [simulation in SpinalHDL](https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Simulation/index.html) is by writing a testbench with SpinalHDL and Scala and then getting it simulated through Verilator.
|
||||
Verilator compiles our HDL (generated from SpinalHDL) to a C++ simulation model, our testbench interacts with that and thus we can have a fast simulation at hand.
|
||||
Lets jump straight into the simulation testbench and see how SpinalHDL aids our work here:
|
||||
|
||||
```scala
|
||||
// in GCDTopSim.scala
|
||||
object GCDTopSim {
|
||||
def main(args: Array[String]) {
|
||||
SimConfig.doSim(new GCDTop()){dut =>
|
||||
def gcd(a: Long,b: Long): Long = {
|
||||
if(b==0) a else gcd(b, a%b)
|
||||
}
|
||||
def RndNextUInt32(): Long = {
|
||||
ThreadLocalRandom.current().nextLong(Math.pow(2, 32).toLong - 1)
|
||||
}
|
||||
var a = 0L
|
||||
var b = 0L
|
||||
var model = 0L
|
||||
dut.io.a #= 0
|
||||
dut.io.b #= 0
|
||||
dut.io.valid #= false
|
||||
|
||||
dut.clockDomain.forkStimulus(period = 10)
|
||||
dut.clockDomain.waitRisingEdge()
|
||||
|
||||
for(idx <- 0 to 50000){
|
||||
a = RndNextUInt32()
|
||||
b = RndNextUInt32()
|
||||
model = gcd(a,b)
|
||||
dut.io.a #= a
|
||||
dut.io.b #= b
|
||||
dut.io.valid #= true
|
||||
dut.clockDomain.waitRisingEdge()
|
||||
dut.io.valid #= false
|
||||
waitUntil(dut.io.ready.toBoolean)
|
||||
assert(
|
||||
assertion = (dut.io.res.toBigInt == model),
|
||||
message = "test " + idx + " failed. Expected " + model + ", retrieved: " + dut.io.res.toBigInt
|
||||
)
|
||||
waitUntil(!dut.io.ready.toBoolean)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In line 3 we basically setup our Design Under Test (DUT), and we could setup some other simulations options like generating the VCD wavetrace.
|
||||
We want to generate some arbitrary amount of testcases and compare the results against a (different) implementation of the GCD algorithm in software.
|
||||
Doing this for enough random cases can give confidence in the design, tho it will not always cover edge cases and other aspects that are covered by a constrained random approach, white box testing or formal methods to verify our design.
|
||||
Lines 4 to 6 are our (recursive) software implementation.
|
||||
Lines 7 to 9 generate a random number in the range of a UInt32 — we have to do this by hand because of the nature of Java, Scala and SpinalHDL and how they interact with each other when it comes to numeric values and types.
|
||||
Lines 10 to 15 setup our input for the DUT and in line 17 and 18 we set up the clock and trigger the first event for our signals to be applied to the inputs.
|
||||
Lines 20 to 35 describe the application of 50k random integers to our design, and our software model, and then comparing them after we waited for the hardware cycles to pass.
|
||||
We use the `assert` to output a message to the terminal in case a testcase doesn't match with the software model.
|
||||
If we add `.withWave` to the line 3 we can obtain a wavetrace (tho its recommended not to run as many testcases, as the dump will be huge otherwise).
|
||||
|
||||

|
||||
|
||||
## 5. GCD Murax Integration
|
||||
Now that we have a standalone module that we want to integrate into the Murax SoC.
|
||||
|
||||
Since the Murax is using the APB bus for the peripherals, our module needs to map the IO signals into the memory mapped space of the APB bus.
|
||||
|
||||
```scala
|
||||
// in Apb3GCDCtrl.scala
|
||||
object Apb3GCDCtrl {
|
||||
def getApb3Config = Apb3Config(
|
||||
addressWidth = 5,
|
||||
dataWidth = 32,
|
||||
selWidth = 1,
|
||||
useSlaveError = false
|
||||
)
|
||||
}
|
||||
|
||||
class Apb3GCDCtrl(apb3Config : Apb3Config) extends Component {
|
||||
val io = new Bundle {
|
||||
val apb = slave(Apb3(Apb3GCDCtrl.getApb3Config))
|
||||
}
|
||||
val gcdCtrl = new GCDTop()
|
||||
val apbCtrl = Apb3SlaveFactory(io.apb)
|
||||
apbCtrl.driveAndRead(gcdCtrl.io.a, address=0)
|
||||
apbCtrl.driveAndRead(gcdCtrl.io.b, address=4)
|
||||
val resSyncBuf = RegNextWhen(gcdCtrl.io.res, gcdCtrl.io.ready)
|
||||
apbCtrl.read(resSyncBuf, address=8)
|
||||
apbCtrl.onRead(8)(resSyncBuf := 0)
|
||||
apbCtrl.onRead(8)(rdySyncBuf := False)
|
||||
val rdySyncBuf = RegNextWhen(gcdCtrl.io.ready, gcdCtrl.io.ready)
|
||||
apbCtrl.read(rdySyncBuf, address=12)
|
||||
gcdCtrl.io.valid := apbCtrl.setOnSet(RegNext(False) init(False), address=16, 0)
|
||||
}
|
||||
```
|
||||
|
||||
Looking at the other peripherals in the Murax, we get an idea how to implement our own Apb3 Mapping (this is also part of the SpinalHDL Workshop).
|
||||
|
||||
The components uses the APB3 Bus as a slave peripheral.
|
||||
In line 14 we create a instance of our GCD module, in line 15 we create a [APB3 Slave Factory](https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Libraries/bus_slave_factory.html) (for our APB bus connection of the component).
|
||||
This factory offers us to add memory mapped registers very easily that create all the logic needed to interconnect with our module properly.
|
||||
A register which can be read and written to can be seen in line 16 and 17 (`driveAndRead()`).
|
||||
We pass the signal we want to be buffered through that register and an address.
|
||||
Our result is [buffered with a `RegNextWhen`](https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Sequential%20logic/registers.html#instantiation) (which buffers the first argument `gcdCtrl.io.res` based on the enable signal that is the second argument `gcdCtrl.io.ready`).
|
||||
We need this because our result is visible for the clock cycle that the ready signal is asserted true by the control path.
|
||||
We do something similar with the ready signal, and keep it buffered for longer than just one clock cycle (since we don't know when the software will check these registers).
|
||||
The result and ready registers will be read-only (`read()`) on their respective addresses.
|
||||
If the result is read (even if ready was not checked) we will flush both registers as if we fetched the result and don't need it anymore.
|
||||
The valid signal shouldn't be asserted longer than one clock cycle, this is achieved in line 24.
|
||||
We use a register that sets itself to 0/false whenever its written to.
|
||||
So if we write a 1/true into it, after one cycle its set to 0/false again.
|
||||
|
||||
| Address | Name | Description | Mode |
|
||||
|---------|-------|----------------------------------------------|----------------------------------|
|
||||
| 0 | a | Operand A of the GCD(a,b) | R/W |
|
||||
| 4 | b | Operand B of the GCD(a,b) | R/W |
|
||||
| 8 | res | Result of GCD(a,b) | RO, clears res and ready on read |
|
||||
| 12 | ready | Ready, 1 if result available, 0 otherwise | RO |
|
||||
| 16 | valid | Valid, write 1 to start calculating GCD(a,b) | WO, clear after write |
|
||||
|
||||
|
||||
In this way we implemented this memory mapped register bank with various modes.
|
||||
Now all thats left is to attach our module to the APB bus of the Murax SoC and write some bare metal firmware to access it.
|
||||
|
||||
We created our modules inside the VexRiscv structure as follows:
|
||||
```
|
||||
src/main/scala/
|
||||
├── spinal
|
||||
└── vexriscv
|
||||
├── demo
|
||||
├── ip
|
||||
├── periph <--- we add this directory with subdir
|
||||
│ └── gcd
|
||||
│ ├── Apb3GCDCtrl.scala
|
||||
│ ├── GCDCtrl.scala
|
||||
│ ├── GCDData.scala
|
||||
│ ├── GCDTop.scala
|
||||
│ └── GCDTopSim.scala
|
||||
├── plugin
|
||||
└── test
|
||||
|
||||
```
|
||||
|
||||
To integrate our `Apb3GCDCtrl` peripheral into the Murax we need to modify the Murax SoC (`src/main/scala/vexriscv/demo/Murax.scala`) directly.
|
||||
Deep in the source there will be a comment designating the start of the APB peripherals (`//******** APB peripherals *********`).
|
||||
There we are going to add our peripheral and designate some memory mapped space to it.
|
||||
|
||||
This step is straightforward as we can add the peripheral similarly to the existing ones.
|
||||
After the code for the timer `MuraxApb3Timer` module we add our GCD peripheral:
|
||||
|
||||
```scala
|
||||
val gcd = new Apb3GCDCtrl(
|
||||
apb3Config = Apb3Config(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
)
|
||||
)
|
||||
apbMapping += gcd.io.apb -> (0x30000, 1 kB)
|
||||
```
|
||||
|
||||
And thats it!
|
||||
|
||||
The Murax SoC now supports our own GCD peripheral.
|
||||
All thats left now is to use the peripheral in a piece of software.
|
||||
|
||||
## 6. Software Driver Integration
|
||||
|
||||
We start off the software part with the existing `hello_world` example and copy it into a new directory `gcd_world`.
|
||||
|
||||
Since we support a new peripheral in hardware we also need to support it from the software (its supported but we are making it more usable for the developer).
|
||||
We add a new file in the `gcd_world/src` directory called `gcd.h`.
|
||||
|
||||
```c
|
||||
// in gcd.h
|
||||
#ifndef GCD_H_
|
||||
#define GCD_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t A;
|
||||
volatile uint32_t B;
|
||||
volatile uint32_t RES;
|
||||
volatile uint32_t READY;
|
||||
volatile uint32_t VALID;
|
||||
} Gcd_Reg;
|
||||
|
||||
#endif /* GCD_H_ */
|
||||
|
||||
```
|
||||
|
||||
With that we define the available memory mapped registers starting from the base address of the peripheral.
|
||||
|
||||
We then edit the `murax.h` header file in the same directory:
|
||||
|
||||
```c
|
||||
#ifndef __MURAX_H__
|
||||
#define __MURAX_H__
|
||||
|
||||
#include "timer.h"
|
||||
#include "prescaler.h"
|
||||
#include "interrupt.h"
|
||||
#include "gpio.h"
|
||||
#include "uart.h"
|
||||
#include "gcd.h"
|
||||
|
||||
#define GPIO_A ((Gpio_Reg*)(0xF0000000))
|
||||
#define TIMER_PRESCALER ((Prescaler_Reg*)0xF0020000)
|
||||
#define TIMER_INTERRUPT ((InterruptCtrl_Reg*)0xF0020010)
|
||||
#define TIMER_A ((Timer_Reg*)0xF0020040)
|
||||
#define TIMER_B ((Timer_Reg*)0xF0020050)
|
||||
#define UART ((Uart_Reg*)(0xF0010000))
|
||||
#define GCD ((Gcd_Reg*)(0xF0030000))
|
||||
|
||||
|
||||
#endif /* __MURAX_H__ */
|
||||
```
|
||||
|
||||
Our addition is the line `#define GCD ((Gcd_Reg*)(0xF0030000))`.
|
||||
With that we create a way of accessing the memory mapped registers without directly referring to the peripherals address (`0xF0030000`) or having to calculate offsets for the registers.
|
||||
|
||||
Now we can start writing our software!
|
||||
|
||||
In our `main.c` we add a function to make the peripheral handling a bit more convenient:
|
||||
|
||||
```c
|
||||
uint32_t gcd(uint32_t a, uint32_t b){
|
||||
GCD->A = a;
|
||||
GCD->B = b;
|
||||
GCD->VALID = 0x00000001;
|
||||
uint32_t rdyFlag = 0;
|
||||
do{
|
||||
rdyFlag = GCD->READY;
|
||||
}while(!rdyFlag);
|
||||
return GCD->RES;
|
||||
}
|
||||
```
|
||||
|
||||
This function will take the parameters `a` and `b` and applies them to the respective hardware registers `A` and `B` of our peripheral.
|
||||
Then the `VALID` signal is set (our Apb3 wrapper takes care of setting it back to 0).
|
||||
All thats left is waiting for the result, which is done by polling the ready flag until its available and then returning our result value `RES`.
|
||||
|
||||
The software contains a little more code for formatting numbers to print them onto the UART device but reading and understanding that is left as an exercise to the reader.
|
||||
|
||||
So how do we execute our software on the Murax now?
|
||||
|
||||
First we compile the software with the make file. For that call `make` inside `src/main/c/murax/gcd_world`.
|
||||
You should get some minor warnings and a statistics about the memory usage like
|
||||
|
||||
```
|
||||
Memory region Used Size Region Size %age Used
|
||||
RAM: 1752 B 2 KB 85.55%
|
||||
```
|
||||
|
||||
Now we can edit the `Murax.scala` one last time before we execute our simulation.
|
||||
For this scroll down in the `Murax.scala` file until `MuraxWithRamInit`.
|
||||
In order to load the memory with our new software instead of the `hello_world` example we edit this part.
|
||||
|
||||
```scala
|
||||
object MuraxWithRamInit {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(
|
||||
Murax(
|
||||
MuraxConfig.default.copy(
|
||||
onChipRamSize = 4 kB,
|
||||
onChipRamHexFile = "src/main/c/murax/gcd_world/build/gcd_world.hex"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Then in the root directory we open `sbt` and call `runMain vexriscv.demo.MuraxWithRamInit` or we call `sbt "runMain vexriscv.demo.MuraxWithRamInit"` directly.
|
||||
|
||||
This will call SpinalHDL to generate the modified Murax SoC with our small software example.
|
||||
|
||||
The last thing we need to do is call the simulation.
|
||||
For that navigate to `src/test/cpp/murax` and call `make clean run`.
|
||||
|
||||
After some time you should see the following output in the terminal:
|
||||
|
||||
```
|
||||
...
|
||||
BOOT
|
||||
hello gcd world
|
||||
gcd(1,123913):
|
||||
1
|
||||
gcd(461952,116298):
|
||||
18
|
||||
gcd(461952,1162):
|
||||
2
|
||||
gcd(461952,11623):
|
||||
1
|
||||
```
|
||||
|
||||
Keep in mind that we are simulating a SoC. There is no shutdown for our simulation so we have to stop it by ourselves by pressing `CTRL+C`!
|
||||
Otherwise the simulation won't stop.
|
||||
|
||||
|
||||
|
||||
## 7. Conclusion
|
||||
|
||||
In a tutorial we described how to convert pseudocode for the GCD calculation into SpinalHDL based hardware. Furthermore the hardware was integrated into the VexRiscv based Murax SoC.
|
||||
To demonstrate the usage an example C project was set up and the hardware peripheral was used from within the software.
|
||||
|
||||
This tutorial covered the translation from RTL into SpinalHDL, writing a small wrapper for the APB3 bus used in the Murax SoC, integrating the peripheral into the Murax SoC with designated memory mapped space and writing software in C for the Murax SoC that uses the hardware peripheral to calculate the GCD and print it out on the UART of the Murax SoC.
|
||||
|
||||
Now there are a few open challanges to approach as an exercise here are two that would follow up naturally to our existing code:
|
||||
|
||||
* The Murax SoC features interrupts, we could stop polling our ready flag and instead trigger an interrupt from the `Apb3GCDCtrl` instead.
|
||||
* Write the same algorithm in C and compare it with the hardware peripheral. Is it faster, is it smaller (interacting with the peripheral in software still costs instruction in terms of memory)
|
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-controlpath.png
Normal file
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-controlpath.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-datapath.png
Normal file
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-datapath.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-dp+cp.png
Normal file
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd-dp+cp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd.png
Normal file
BIN
doc/gcdPeripheral/img/murax-gcd-diagrams-gcd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
1
doc/gcdPeripheral/img/murax-gcd-diagrams.drawio
Normal file
1
doc/gcdPeripheral/img/murax-gcd-diagrams.drawio
Normal file
File diff suppressed because one or more lines are too long
BIN
doc/gcdPeripheral/img/simulationWave.PNG
Normal file
BIN
doc/gcdPeripheral/img/simulationWave.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
134
doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile
Normal file
134
doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile
Normal file
|
@ -0,0 +1,134 @@
|
|||
PROJ_NAME=gcd_world
|
||||
DEBUG=no
|
||||
BENCH=no
|
||||
MULDIV=no
|
||||
|
||||
SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/*.cpp) \
|
||||
$(wildcard src/*.S)
|
||||
|
||||
OBJDIR = build
|
||||
|
||||
INC =
|
||||
LIBS =
|
||||
LIBSINC = -L$(OBJDIR)
|
||||
LDSCRIPT = ./src/linker.ld
|
||||
|
||||
#include ../../../resources/gcc.mk
|
||||
# Set it to yes if you are using the sifive precompiled GCC pack
|
||||
SIFIVE_GCC_PACK ?= no
|
||||
|
||||
ifeq ($(SIFIVE_GCC_PACK),yes)
|
||||
RISCV_NAME ?= riscv64-unknown-elf
|
||||
RISCV_PATH ?= /home/sallar/tools/riscv-64-newlib-dist/
|
||||
else
|
||||
RISCV_NAME ?= riscv32-unknown-elf
|
||||
ifeq ($(MULDIV),yes)
|
||||
RISCV_PATH ?= /home/sallar/tools/riscv-32-imac-ilp32-newlib-dist/
|
||||
else
|
||||
RISCV_PATH ?= /home/sallar/tools/rv32i-ilp32-dist/
|
||||
endif
|
||||
endif
|
||||
|
||||
MABI=ilp32
|
||||
MARCH := rv32i
|
||||
ifeq ($(MULDIV),yes)
|
||||
MARCH := $(MARCH)m
|
||||
endif
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
MARCH := $(MARCH)ac
|
||||
endif
|
||||
|
||||
CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG
|
||||
LDFLAGS += -march=$(MARCH) -mabi=$(MABI)
|
||||
|
||||
|
||||
|
||||
#include ../../../resources/subproject.mk
|
||||
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CFLAGS += -g3 -O0
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),no)
|
||||
CFLAGS += -g -Os
|
||||
endif
|
||||
|
||||
ifeq ($(BENCH),yes)
|
||||
CFLAGS += -fno-inline
|
||||
endif
|
||||
|
||||
ifeq ($(SIFIVE_GCC_PACK),yes)
|
||||
RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
|
||||
else
|
||||
RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
|
||||
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
|
||||
RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
|
||||
|
||||
CFLAGS += -MD -fstrict-volatile-bitfields -fno-strict-aliasing
|
||||
LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
|
||||
#LDFLAGS += -lgcc -lc -lg -nostdlib -lgcc -msave-restore --strip-debug,
|
||||
|
||||
OBJS := $(SRCS)
|
||||
OBJS := $(OBJS:.c=.o)
|
||||
OBJS := $(OBJS:.cpp=.o)
|
||||
OBJS := $(OBJS:.S=.o)
|
||||
OBJS := $(OBJS:..=miaou)
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
|
||||
|
||||
|
||||
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
|
||||
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBSINC) $(LIBS)
|
||||
|
||||
%.hex: %.elf
|
||||
$(RISCV_OBJCOPY) -O ihex $^ $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(RISCV_OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.v: %.elf
|
||||
$(RISCV_OBJCOPY) -O verilog $^ $@
|
||||
|
||||
%.asm: %.elf
|
||||
$(RISCV_OBJDUMP) -S -d $^ > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
$(RISCV_CC) -S $(CFLAGS) $(INC) -o $@.disasm $^
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.S
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(OBJDIR)/src
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).elf
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).hex
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).map
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).v
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).asm
|
||||
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
|
||||
find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
|
||||
|
||||
clean-all : clean
|
||||
|
||||
.SECONDARY: $(OBJS)
|
|
@ -0,0 +1 @@
|
|||
sbt.version=1.4.9
|
98
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S
Normal file
98
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S
Normal file
|
@ -0,0 +1,98 @@
|
|||
.global crtStart
|
||||
.global main
|
||||
.global irqCallback
|
||||
|
||||
.section .start_jump,"ax",@progbits
|
||||
crtStart:
|
||||
//long jump to allow crtInit to be anywhere
|
||||
//do it always in 12 bytes
|
||||
lui x2, %hi(crtInit)
|
||||
addi x2, x2, %lo(crtInit)
|
||||
jalr x1,x2
|
||||
nop
|
||||
|
||||
.section .text
|
||||
|
||||
.global trap_entry
|
||||
.align 5
|
||||
trap_entry:
|
||||
sw x1, - 1*4(sp)
|
||||
sw x5, - 2*4(sp)
|
||||
sw x6, - 3*4(sp)
|
||||
sw x7, - 4*4(sp)
|
||||
sw x10, - 5*4(sp)
|
||||
sw x11, - 6*4(sp)
|
||||
sw x12, - 7*4(sp)
|
||||
sw x13, - 8*4(sp)
|
||||
sw x14, - 9*4(sp)
|
||||
sw x15, -10*4(sp)
|
||||
sw x16, -11*4(sp)
|
||||
sw x17, -12*4(sp)
|
||||
sw x28, -13*4(sp)
|
||||
sw x29, -14*4(sp)
|
||||
sw x30, -15*4(sp)
|
||||
sw x31, -16*4(sp)
|
||||
addi sp,sp,-16*4
|
||||
call irqCallback
|
||||
lw x1 , 15*4(sp)
|
||||
lw x5, 14*4(sp)
|
||||
lw x6, 13*4(sp)
|
||||
lw x7, 12*4(sp)
|
||||
lw x10, 11*4(sp)
|
||||
lw x11, 10*4(sp)
|
||||
lw x12, 9*4(sp)
|
||||
lw x13, 8*4(sp)
|
||||
lw x14, 7*4(sp)
|
||||
lw x15, 6*4(sp)
|
||||
lw x16, 5*4(sp)
|
||||
lw x17, 4*4(sp)
|
||||
lw x28, 3*4(sp)
|
||||
lw x29, 2*4(sp)
|
||||
lw x30, 1*4(sp)
|
||||
lw x31, 0*4(sp)
|
||||
addi sp,sp,16*4
|
||||
mret
|
||||
.text
|
||||
|
||||
|
||||
crtInit:
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
la sp, _stack_start
|
||||
|
||||
bss_init:
|
||||
la a0, _bss_start
|
||||
la a1, _bss_end
|
||||
bss_loop:
|
||||
beq a0,a1,bss_done
|
||||
sw zero,0(a0)
|
||||
add a0,a0,4
|
||||
j bss_loop
|
||||
bss_done:
|
||||
|
||||
ctors_init:
|
||||
la a0, _ctors_start
|
||||
addi sp,sp,-4
|
||||
ctors_loop:
|
||||
la a1, _ctors_end
|
||||
beq a0,a1,ctors_done
|
||||
lw a3,0(a0)
|
||||
add a0,a0,4
|
||||
sw a0,0(sp)
|
||||
jalr a3
|
||||
lw a0,0(sp)
|
||||
j ctors_loop
|
||||
ctors_done:
|
||||
addi sp,sp,4
|
||||
|
||||
|
||||
li a0, 0x880 //880 enable timer + external interrupts
|
||||
csrw mie,a0
|
||||
li a0, 0x1808 //1808 enable interrupts
|
||||
csrw mstatus,a0
|
||||
|
||||
call main
|
||||
infinitLoop:
|
||||
j infinitLoop
|
13
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h
Normal file
13
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef GCD_H_
|
||||
#define GCD_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t A;
|
||||
volatile uint32_t B;
|
||||
volatile uint32_t RES;
|
||||
volatile uint32_t READY;
|
||||
volatile uint32_t VALID;
|
||||
} Gcd_Reg;
|
||||
|
||||
#endif /* GCD_H_ */
|
15
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h
Normal file
15
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef GPIO_H_
|
||||
#define GPIO_H_
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t INPUT;
|
||||
volatile uint32_t OUTPUT;
|
||||
volatile uint32_t OUTPUT_ENABLE;
|
||||
} Gpio_Reg;
|
||||
|
||||
|
||||
#endif /* GPIO_H_ */
|
||||
|
||||
|
17
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h
Normal file
17
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef INTERRUPTCTRL_H_
|
||||
#define INTERRUPTCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t PENDINGS;
|
||||
volatile uint32_t MASKS;
|
||||
} InterruptCtrl_Reg;
|
||||
|
||||
static void interruptCtrl_init(InterruptCtrl_Reg* reg){
|
||||
reg->MASKS = 0;
|
||||
reg->PENDINGS = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
#endif /* INTERRUPTCTRL_H_ */
|
110
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld
Normal file
110
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(crtStart)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = 0x80000000, LENGTH = 2k
|
||||
}
|
||||
|
||||
_stack_size = DEFINED(_stack_size) ? _stack_size : 256;
|
||||
_heap_size = DEFINED(_heap_size) ? _heap_size : 0;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
._vector ORIGIN(RAM): {
|
||||
*crt.o(.start_jump);
|
||||
*crt.o(.text);
|
||||
} > RAM
|
||||
|
||||
._user_heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
PROVIDE ( _heap_start = .);
|
||||
. = . + _heap_size;
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( _heap_end = .);
|
||||
} > RAM
|
||||
|
||||
._stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_stack_end = .);
|
||||
. = . + _stack_size;
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_stack_start = .);
|
||||
} > RAM
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_bss_start = .;
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_bss_end = .;
|
||||
} > RAM
|
||||
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} > RAM
|
||||
|
||||
.noinit (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.memory : {
|
||||
*(.text);
|
||||
end = .;
|
||||
} > RAM
|
||||
|
||||
.ctors :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_ctors_start = .;
|
||||
KEEP(*(.init_array*))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4);
|
||||
_ctors_end = .;
|
||||
PROVIDE ( END_OF_SW_IMAGE = . );
|
||||
} > RAM
|
||||
|
||||
}
|
62
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c
Normal file
62
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
//#include "stddefs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "murax.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
uint32_t gcd(uint32_t a, uint32_t b){
|
||||
GCD->A = a;
|
||||
GCD->B = b;
|
||||
GCD->VALID = 0x00000001;
|
||||
uint32_t rdyFlag = 0;
|
||||
do{
|
||||
rdyFlag = GCD->READY;
|
||||
}while(!rdyFlag);
|
||||
return GCD->RES;
|
||||
}
|
||||
|
||||
void calcPrintGCD(uint32_t a, uint32_t b){
|
||||
uint32_t myGCD = 0;
|
||||
char buf[5] = { 0x00 };
|
||||
char aBuf[11] = { 0x00 };
|
||||
char bBuf[11] = { 0x00 };
|
||||
itoa(a, aBuf, 10);
|
||||
itoa(b, bBuf, 10);
|
||||
print("gcd(");print(aBuf);print(",");print(bBuf);println("):");
|
||||
myGCD = gcd(a,b);
|
||||
itoa(myGCD, buf, 10);
|
||||
println(buf);
|
||||
}
|
||||
|
||||
void main() {
|
||||
GPIO_A->OUTPUT_ENABLE = 0x0000000F;
|
||||
GPIO_A->OUTPUT = 0x00000001;
|
||||
println("hello gcd world");
|
||||
const int nleds = 4;
|
||||
const int nloops = 2000000;
|
||||
|
||||
GCD->VALID = 0x00000000;
|
||||
while(GCD->READY);
|
||||
|
||||
calcPrintGCD(1, 123913);
|
||||
calcPrintGCD(461952, 116298);
|
||||
calcPrintGCD(461952, 116298);
|
||||
calcPrintGCD(461952, 116298);
|
||||
|
||||
while(1){
|
||||
for(unsigned int i=0;i<nleds-1;i++){
|
||||
GPIO_A->OUTPUT = 1<<i;
|
||||
delay(nloops);
|
||||
}
|
||||
for(unsigned int i=0;i<nleds-1;i++){
|
||||
GPIO_A->OUTPUT = (1<<(nleds-1))>>i;
|
||||
delay(nloops);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void irqCallback(){
|
||||
}
|
78
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h
Normal file
78
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
//----------------------------
|
||||
// integer to ascii (itoa) with util functions
|
||||
//----------------------------
|
||||
|
||||
// function to swap two numbers
|
||||
void swap(char *x, char *y) {
|
||||
char t = *x; *x = *y; *y = t;
|
||||
}
|
||||
|
||||
// function to reverse buffer[i..j]
|
||||
char* reverse(char *buffer, int i, int j) {
|
||||
while (i < j)
|
||||
swap(&buffer[i++], &buffer[j--]);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Iterative function to implement itoa() function in C
|
||||
char* itoa(int value, char* buffer, int base) {
|
||||
// invalid input
|
||||
if (base < 2 || base > 32)
|
||||
return buffer;
|
||||
// consider absolute value of number
|
||||
int n = (value < 0) ? -value : value;
|
||||
int i = 0;
|
||||
while (n) {
|
||||
int r = n % base;
|
||||
if (r >= 10)
|
||||
buffer[i++] = 65 + (r - 10);
|
||||
else
|
||||
buffer[i++] = 48 + r;
|
||||
n = n / base;
|
||||
}
|
||||
|
||||
// if number is 0
|
||||
if (i == 0)
|
||||
buffer[i++] = '0';
|
||||
|
||||
// If base is 10 and value is negative, the resulting string
|
||||
// is preceded with a minus sign (-)
|
||||
// With any other base, value is always considered unsigned
|
||||
if (value < 0 && base == 10)
|
||||
buffer[i++] = '-';
|
||||
|
||||
buffer[i] = '\0'; // null terminate string
|
||||
|
||||
// reverse the string and return it
|
||||
return reverse(buffer, 0, i - 1);
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
// print, println, dbgprint
|
||||
//----------------------------
|
||||
|
||||
void print(const char*str){
|
||||
while(*str){
|
||||
uart_write(UART,*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
void println(const char*str){
|
||||
print(str);
|
||||
uart_write(UART,'\n');
|
||||
}
|
||||
|
||||
void dbgPrintln(const char*str){
|
||||
#if DEBUG == 1
|
||||
println(str);
|
||||
#else
|
||||
void;
|
||||
#endif
|
||||
}
|
||||
|
||||
void delay(uint32_t loops){
|
||||
for(int i=0;i<loops;i++){
|
||||
int tmp = GPIO_A->OUTPUT;
|
||||
}
|
||||
}
|
20
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h
Normal file
20
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef __MURAX_H__
|
||||
#define __MURAX_H__
|
||||
|
||||
#include "timer.h"
|
||||
#include "prescaler.h"
|
||||
#include "interrupt.h"
|
||||
#include "gpio.h"
|
||||
#include "uart.h"
|
||||
#include "gcd.h"
|
||||
|
||||
#define GPIO_A ((Gpio_Reg*)(0xF0000000))
|
||||
#define TIMER_PRESCALER ((Prescaler_Reg*)0xF0020000)
|
||||
#define TIMER_INTERRUPT ((InterruptCtrl_Reg*)0xF0020010)
|
||||
#define TIMER_A ((Timer_Reg*)0xF0020040)
|
||||
#define TIMER_B ((Timer_Reg*)0xF0020050)
|
||||
#define UART ((Uart_Reg*)(0xF0010000))
|
||||
#define GCD ((Gcd_Reg*)(0xF0030000))
|
||||
|
||||
|
||||
#endif /* __MURAX_H__ */
|
16
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h
Normal file
16
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef PRESCALERCTRL_H_
|
||||
#define PRESCALERCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t LIMIT;
|
||||
} Prescaler_Reg;
|
||||
|
||||
static void prescaler_init(Prescaler_Reg* reg){
|
||||
|
||||
}
|
||||
|
||||
#endif /* PRESCALERCTRL_H_ */
|
20
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h
Normal file
20
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef TIMERCTRL_H_
|
||||
#define TIMERCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t CLEARS_TICKS;
|
||||
volatile uint32_t LIMIT;
|
||||
volatile uint32_t VALUE;
|
||||
} Timer_Reg;
|
||||
|
||||
static void timer_init(Timer_Reg *reg){
|
||||
reg->CLEARS_TICKS = 0;
|
||||
reg->VALUE = 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TIMERCTRL_H_ */
|
42
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h
Normal file
42
doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef UART_H_
|
||||
#define UART_H_
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t DATA;
|
||||
volatile uint32_t STATUS;
|
||||
volatile uint32_t CLOCK_DIVIDER;
|
||||
volatile uint32_t FRAME_CONFIG;
|
||||
} Uart_Reg;
|
||||
|
||||
enum UartParity {NONE = 0,EVEN = 1,ODD = 2};
|
||||
enum UartStop {ONE = 0,TWO = 1};
|
||||
|
||||
typedef struct {
|
||||
uint32_t dataLength;
|
||||
enum UartParity parity;
|
||||
enum UartStop stop;
|
||||
uint32_t clockDivider;
|
||||
} Uart_Config;
|
||||
|
||||
static uint32_t uart_writeAvailability(Uart_Reg *reg){
|
||||
return (reg->STATUS >> 16) & 0xFF;
|
||||
}
|
||||
static uint32_t uart_readOccupancy(Uart_Reg *reg){
|
||||
return reg->STATUS >> 24;
|
||||
}
|
||||
|
||||
static void uart_write(Uart_Reg *reg, uint32_t data){
|
||||
while(uart_writeAvailability(reg) == 0);
|
||||
reg->DATA = data;
|
||||
}
|
||||
|
||||
static void uart_applyConfig(Uart_Reg *reg, Uart_Config *config){
|
||||
reg->CLOCK_DIVIDER = config->clockDivider;
|
||||
reg->FRAME_CONFIG = ((config->dataLength-1) << 0) | (config->parity << 8) | (config->stop << 16);
|
||||
}
|
||||
|
||||
#endif /* UART_H_ */
|
||||
|
||||
|
559
doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala
Normal file
559
doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala
Normal file
|
@ -0,0 +1,559 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba3.apb._
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
import spinal.lib.bus.simple.PipelinedMemoryBus
|
||||
import spinal.lib.com.jtag.Jtag
|
||||
import spinal.lib.com.spi.ddr.SpiXdrMaster
|
||||
import spinal.lib.com.uart._
|
||||
import spinal.lib.io.{InOutWrapper, TriStateArray}
|
||||
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
||||
import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||
import spinal.lib.com.spi.ddr._
|
||||
import spinal.lib.bus.simple._
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import vexriscv.periph.gcd._
|
||||
import vexriscv.periph.tasks.gen._
|
||||
import vexriscv.periph.tasks.map._
|
||||
import vexriscv.periph.tasks.sort._
|
||||
import vexriscv.periph.tasks.max._
|
||||
import vexriscv.periph.tasks.sum._
|
||||
import vexriscv.periph.tasks.hash._
|
||||
|
||||
/** Created by PIC32F_USER on 28/07/2017.
|
||||
*
|
||||
* Murax is a very light SoC which could work without any external component.
|
||||
* - ICE40-hx8k + icestorm => 53 MHz, 2142 LC
|
||||
* - 0.37 DMIPS/MHz
|
||||
* - 8 kB of on-chip ram
|
||||
* - JTAG debugger (eclipse/GDB/openocd ready)
|
||||
* - Interrupt support
|
||||
* - APB bus for peripherals
|
||||
* - 32 GPIO pin
|
||||
* - one 16 bits prescaler, two 16 bits timers
|
||||
* - one UART with tx/rx fifo
|
||||
*/
|
||||
|
||||
case class MuraxConfig(
|
||||
coreFrequency: HertzNumber,
|
||||
onChipRamSize: BigInt,
|
||||
onChipRamHexFile: String,
|
||||
pipelineDBus: Boolean,
|
||||
pipelineMainBus: Boolean,
|
||||
pipelineApbBridge: Boolean,
|
||||
gpioWidth: Int,
|
||||
uartCtrlConfig: UartCtrlMemoryMappedConfig,
|
||||
xipConfig: SpiXdrMasterCtrl.MemoryMappingParameters,
|
||||
hardwareBreakpointCount: Int,
|
||||
cpuPlugins: ArrayBuffer[Plugin[VexRiscv]]
|
||||
) {
|
||||
require(
|
||||
pipelineApbBridge || pipelineMainBus,
|
||||
"At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions"
|
||||
)
|
||||
val genXip = xipConfig != null
|
||||
|
||||
}
|
||||
|
||||
object MuraxConfig {
|
||||
def default: MuraxConfig = default(false, false)
|
||||
def default(withXip: Boolean = false, bigEndian: Boolean = false) =
|
||||
MuraxConfig(
|
||||
coreFrequency = 12 MHz,
|
||||
onChipRamSize = 8 kB,
|
||||
onChipRamHexFile = null,
|
||||
pipelineDBus = true,
|
||||
pipelineMainBus = false,
|
||||
pipelineApbBridge = true,
|
||||
gpioWidth = 32,
|
||||
xipConfig = ifGen(withXip)(
|
||||
SpiXdrMasterCtrl.MemoryMappingParameters(
|
||||
SpiXdrMasterCtrl
|
||||
.Parameters(8, 12, SpiXdrParameter(2, 2, 1))
|
||||
.addFullDuplex(0, 1, false),
|
||||
cmdFifoDepth = 32,
|
||||
rspFifoDepth = 32,
|
||||
xip = SpiXdrMasterCtrl
|
||||
.XipBusParameters(addressWidth = 24, lengthWidth = 2)
|
||||
)
|
||||
),
|
||||
hardwareBreakpointCount = if (withXip) 3 else 0,
|
||||
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
||||
new IBusSimplePlugin(
|
||||
resetVector = if (withXip) 0xf001e000L else 0x80000000L,
|
||||
cmdForkOnSecondStage = true,
|
||||
cmdForkPersistence = withXip, //Required by the Xip controller
|
||||
prediction = NONE,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false,
|
||||
bigEndian = bigEndian
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false,
|
||||
earlyInjection = false,
|
||||
bigEndian = bigEndian
|
||||
),
|
||||
new CsrPlugin(
|
||||
CsrPluginConfig.smallest(mtvecInit =
|
||||
if (withXip) 0xe0040020L else 0x80000020L
|
||||
)
|
||||
),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = false
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = false
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false,
|
||||
executeInsertion = false
|
||||
),
|
||||
new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = false,
|
||||
bypassMemory = false,
|
||||
bypassWriteBack = false,
|
||||
bypassWriteBackBuffer = false,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = false
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
),
|
||||
uartCtrlConfig = UartCtrlMemoryMappedConfig(
|
||||
uartCtrlConfig = UartCtrlGenerics(
|
||||
dataWidthMax = 8,
|
||||
clockDividerWidth = 20,
|
||||
preSamplingSize = 1,
|
||||
samplingSize = 3,
|
||||
postSamplingSize = 1
|
||||
),
|
||||
initConfig = UartCtrlInitConfig(
|
||||
baudrate = 115200,
|
||||
dataLength = 7, //7 => 8 bits
|
||||
parity = UartParityType.NONE,
|
||||
stop = UartStopType.ONE
|
||||
),
|
||||
busCanWriteClockDividerConfig = false,
|
||||
busCanWriteFrameConfig = false,
|
||||
txFifoDepth = 16,
|
||||
rxFifoDepth = 16
|
||||
)
|
||||
)
|
||||
|
||||
def fast = {
|
||||
val config = default
|
||||
|
||||
//Replace HazardSimplePlugin to get datapath bypass
|
||||
config.cpuPlugins(
|
||||
config.cpuPlugins.indexWhere(_.isInstanceOf[HazardSimplePlugin])
|
||||
) = new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
bypassMemory = true,
|
||||
bypassWriteBack = true,
|
||||
bypassWriteBackBuffer = true
|
||||
)
|
||||
// config.cpuPlugins(config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin])) = new FullBarrelShifterPlugin()
|
||||
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
case class Murax(config: MuraxConfig) extends Component {
|
||||
import config._
|
||||
|
||||
val io = new Bundle {
|
||||
//Clocks / reset
|
||||
val asyncReset = in Bool ()
|
||||
val mainClk = in Bool ()
|
||||
|
||||
//Main components IO
|
||||
val jtag = slave(Jtag())
|
||||
|
||||
//Peripherals IO
|
||||
val gpioA = master(TriStateArray(gpioWidth bits))
|
||||
val uart = master(Uart())
|
||||
|
||||
val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi)))
|
||||
}
|
||||
|
||||
val resetCtrlClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
config = ClockDomainConfig(
|
||||
resetKind = BOOT
|
||||
)
|
||||
)
|
||||
|
||||
val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
|
||||
val mainClkResetUnbuffered = False
|
||||
|
||||
//Implement an counter to keep the reset axiResetOrder high 64 cycles
|
||||
// Also this counter will automatically do a reset when the system boot.
|
||||
val systemClkResetCounter = Reg(UInt(6 bits)) init (0)
|
||||
when(systemClkResetCounter =/= U(systemClkResetCounter.range -> true)) {
|
||||
systemClkResetCounter := systemClkResetCounter + 1
|
||||
mainClkResetUnbuffered := True
|
||||
}
|
||||
when(BufferCC(io.asyncReset)) {
|
||||
systemClkResetCounter := 0
|
||||
}
|
||||
|
||||
//Create all reset used later in the design
|
||||
val mainClkReset = RegNext(mainClkResetUnbuffered)
|
||||
val systemReset = RegNext(mainClkResetUnbuffered)
|
||||
}
|
||||
|
||||
val systemClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.systemReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val debugClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.mainClkReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val system = new ClockingArea(systemClockDomain) {
|
||||
val pipelinedMemoryBusConfig = PipelinedMemoryBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
val bigEndianDBus = config.cpuPlugins.exists(_ match {
|
||||
case plugin: DBusSimplePlugin => plugin.bigEndian
|
||||
case _ => false
|
||||
})
|
||||
|
||||
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
||||
//Priority to dBus, !! cmd transactions can change on the fly !!
|
||||
val mainBusArbiter =
|
||||
new MuraxMasterArbiter(pipelinedMemoryBusConfig, bigEndianDBus)
|
||||
|
||||
//Instanciate the CPU
|
||||
val cpu = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
plugins = cpuPlugins += new DebugPlugin(
|
||||
debugClockDomain,
|
||||
hardwareBreakpointCount
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
//Checkout plugins used to instanciate the CPU to connect them to the SoC
|
||||
val timerInterrupt = False
|
||||
val externalInterrupt = False
|
||||
for (plugin <- cpu.plugins) plugin match {
|
||||
case plugin: IBusSimplePlugin =>
|
||||
mainBusArbiter.io.iBus.cmd <> plugin.iBus.cmd
|
||||
mainBusArbiter.io.iBus.rsp <> plugin.iBus.rsp
|
||||
case plugin: DBusSimplePlugin => {
|
||||
if (!pipelineDBus)
|
||||
mainBusArbiter.io.dBus <> plugin.dBus
|
||||
else {
|
||||
mainBusArbiter.io.dBus.cmd << plugin.dBus.cmd.halfPipe()
|
||||
mainBusArbiter.io.dBus.rsp <> plugin.dBus.rsp
|
||||
}
|
||||
}
|
||||
case plugin: CsrPlugin => {
|
||||
plugin.externalInterrupt := externalInterrupt
|
||||
plugin.timerInterrupt := timerInterrupt
|
||||
}
|
||||
case plugin: DebugPlugin =>
|
||||
plugin.debugClockDomain {
|
||||
resetCtrl.systemReset setWhen (RegNext(plugin.io.resetOut))
|
||||
io.jtag <> plugin.io.bus.fromJtag()
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
|
||||
//****** MainBus slaves ********
|
||||
val mainBusMapping = ArrayBuffer[(PipelinedMemoryBus, SizeMapping)]()
|
||||
val ram = new MuraxPipelinedMemoryBusRam(
|
||||
onChipRamSize = onChipRamSize,
|
||||
onChipRamHexFile = onChipRamHexFile,
|
||||
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig,
|
||||
bigEndian = bigEndianDBus
|
||||
)
|
||||
mainBusMapping += ram.io.bus -> (0x80000000L, onChipRamSize)
|
||||
|
||||
val apbBridge = new PipelinedMemoryBusToApbBridge(
|
||||
apb3Config = Apb3Config(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
),
|
||||
pipelineBridge = pipelineApbBridge,
|
||||
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig
|
||||
)
|
||||
mainBusMapping += apbBridge.io.pipelinedMemoryBus -> (0xf0000000L, 1 MB)
|
||||
|
||||
//******** APB peripherals *********
|
||||
val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]()
|
||||
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth, withReadSync = true)
|
||||
io.gpioA <> gpioACtrl.io.gpio
|
||||
apbMapping += gpioACtrl.io.apb -> (0x00000, 4 kB)
|
||||
|
||||
val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
|
||||
uartCtrl.io.uart <> io.uart
|
||||
externalInterrupt setWhen (uartCtrl.io.interrupt)
|
||||
apbMapping += uartCtrl.io.apb -> (0x10000, 4 kB)
|
||||
|
||||
val timer = new MuraxApb3Timer()
|
||||
timerInterrupt setWhen (timer.io.interrupt)
|
||||
apbMapping += timer.io.apb -> (0x20000, 4 kB)
|
||||
|
||||
val gcd = new Apb3GCDCtrl(
|
||||
apb3Config = Apb3Config(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
)
|
||||
)
|
||||
apbMapping += gcd.io.apb -> (0x30000, 1 kB)
|
||||
|
||||
val xip = ifGen(genXip)(new Area {
|
||||
val ctrl = Apb3SpiXdrMasterCtrl(xipConfig)
|
||||
ctrl.io.spi <> io.xip
|
||||
externalInterrupt setWhen (ctrl.io.interrupt)
|
||||
apbMapping += ctrl.io.apb -> (0x1f000, 4 kB)
|
||||
|
||||
val accessBus = new PipelinedMemoryBus(PipelinedMemoryBusConfig(24, 32))
|
||||
mainBusMapping += accessBus -> (0xe0000000L, 16 MB)
|
||||
|
||||
ctrl.io.xip.fromPipelinedMemoryBus() << accessBus
|
||||
val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin")
|
||||
apbMapping += bootloader.io.apb -> (0x1e000, 4 kB)
|
||||
})
|
||||
|
||||
//******** Memory mappings *********
|
||||
val apbDecoder = Apb3Decoder(
|
||||
master = apbBridge.io.apb,
|
||||
slaves = apbMapping
|
||||
)
|
||||
|
||||
val mainBusDecoder = new Area {
|
||||
val logic = new MuraxPipelinedMemoryBusDecoder(
|
||||
master = mainBusArbiter.io.masterBus,
|
||||
specification = mainBusMapping,
|
||||
pipelineMaster = pipelineMainBus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Murax {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.default))
|
||||
}
|
||||
}
|
||||
|
||||
object Murax_iCE40_hx8k_breakout_board_xip {
|
||||
|
||||
case class SB_GB() extends BlackBox {
|
||||
val USER_SIGNAL_TO_GLOBAL_BUFFER = in Bool ()
|
||||
val GLOBAL_BUFFER_OUTPUT = out Bool ()
|
||||
}
|
||||
|
||||
case class SB_IO_SCLK() extends BlackBox {
|
||||
addGeneric("PIN_TYPE", B"010000")
|
||||
val PACKAGE_PIN = out Bool ()
|
||||
val OUTPUT_CLK = in Bool ()
|
||||
val CLOCK_ENABLE = in Bool ()
|
||||
val D_OUT_0 = in Bool ()
|
||||
val D_OUT_1 = in Bool ()
|
||||
setDefinitionName("SB_IO")
|
||||
}
|
||||
|
||||
case class SB_IO_DATA() extends BlackBox {
|
||||
addGeneric("PIN_TYPE", B"110000")
|
||||
val PACKAGE_PIN = inout(Analog(Bool))
|
||||
val CLOCK_ENABLE = in Bool ()
|
||||
val INPUT_CLK = in Bool ()
|
||||
val OUTPUT_CLK = in Bool ()
|
||||
val OUTPUT_ENABLE = in Bool ()
|
||||
val D_OUT_0 = in Bool ()
|
||||
val D_OUT_1 = in Bool ()
|
||||
val D_IN_0 = out Bool ()
|
||||
val D_IN_1 = out Bool ()
|
||||
setDefinitionName("SB_IO")
|
||||
}
|
||||
|
||||
case class Murax_iCE40_hx8k_breakout_board_xip() extends Component {
|
||||
val io = new Bundle {
|
||||
val mainClk = in Bool ()
|
||||
val jtag_tck = in Bool ()
|
||||
val jtag_tdi = in Bool ()
|
||||
val jtag_tdo = out Bool ()
|
||||
val jtag_tms = in Bool ()
|
||||
val uart_txd = out Bool ()
|
||||
val uart_rxd = in Bool ()
|
||||
|
||||
val mosi = inout(Analog(Bool))
|
||||
val miso = inout(Analog(Bool))
|
||||
val sclk = out Bool ()
|
||||
val spis = out Bool ()
|
||||
|
||||
val led = out Bits (8 bits)
|
||||
}
|
||||
val murax = Murax(
|
||||
MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB)
|
||||
)
|
||||
murax.io.asyncReset := False
|
||||
|
||||
val mainClkBuffer = SB_GB()
|
||||
mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.mainClk
|
||||
mainClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.mainClk
|
||||
|
||||
val jtagClkBuffer = SB_GB()
|
||||
jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck
|
||||
jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck
|
||||
|
||||
io.led <> murax.io.gpioA.write(7 downto 0)
|
||||
|
||||
murax.io.jtag.tdi <> io.jtag_tdi
|
||||
murax.io.jtag.tdo <> io.jtag_tdo
|
||||
murax.io.jtag.tms <> io.jtag_tms
|
||||
murax.io.gpioA.read <> 0
|
||||
murax.io.uart.txd <> io.uart_txd
|
||||
murax.io.uart.rxd <> io.uart_rxd
|
||||
|
||||
val xip = new ClockingArea(murax.systemClockDomain) {
|
||||
RegNext(murax.io.xip.ss.asBool) <> io.spis
|
||||
|
||||
val sclkIo = SB_IO_SCLK()
|
||||
sclkIo.PACKAGE_PIN <> io.sclk
|
||||
sclkIo.CLOCK_ENABLE := True
|
||||
|
||||
sclkIo.OUTPUT_CLK := ClockDomain.current.readClockWire
|
||||
sclkIo.D_OUT_0 <> murax.io.xip.sclk.write(0)
|
||||
sclkIo.D_OUT_1 <> RegNext(murax.io.xip.sclk.write(1))
|
||||
|
||||
val datas =
|
||||
for ((data, pin) <- (murax.io.xip.data, List(io.mosi, io.miso)).zipped)
|
||||
yield new Area {
|
||||
val dataIo = SB_IO_DATA()
|
||||
dataIo.PACKAGE_PIN := pin
|
||||
dataIo.CLOCK_ENABLE := True
|
||||
|
||||
dataIo.OUTPUT_CLK := ClockDomain.current.readClockWire
|
||||
dataIo.OUTPUT_ENABLE <> data.writeEnable
|
||||
dataIo.D_OUT_0 <> data.write(0)
|
||||
dataIo.D_OUT_1 <> RegNext(data.write(1))
|
||||
|
||||
dataIo.INPUT_CLK := ClockDomain.current.readClockWire
|
||||
data.read(0) := dataIo.D_IN_0
|
||||
data.read(1) := RegNext(dataIo.D_IN_1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip())
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxDhrystoneReady {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.fast.copy(onChipRamSize = 256 kB)))
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxDhrystoneReadyMulDivStatic {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog({
|
||||
val config = MuraxConfig.fast.copy(onChipRamSize = 256 kB)
|
||||
config.cpuPlugins += new MulPlugin
|
||||
config.cpuPlugins += new DivPlugin
|
||||
config.cpuPlugins.remove(
|
||||
config.cpuPlugins.indexWhere(_.isInstanceOf[BranchPlugin])
|
||||
)
|
||||
config.cpuPlugins += new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = false
|
||||
)
|
||||
config.cpuPlugins += new IBusSimplePlugin(
|
||||
resetVector = 0x80000000L,
|
||||
cmdForkOnSecondStage = true,
|
||||
cmdForkPersistence = false,
|
||||
prediction = STATIC,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false
|
||||
)
|
||||
config.cpuPlugins.remove(
|
||||
config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin])
|
||||
)
|
||||
config.cpuPlugins += new FullBarrelShifterPlugin
|
||||
Murax(config)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//Will blink led and echo UART RX to UART TX (in the verilator sim, type some text and press enter to send UART frame to the Murax RX pin)
|
||||
object MuraxWithRamInit {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(
|
||||
Murax(
|
||||
MuraxConfig.default.copy(
|
||||
onChipRamSize = 4 kB,
|
||||
onChipRamHexFile = "src/main/c/murax/gcd_world/build/gcd_world.hex"
|
||||
)
|
||||
)
|
||||
)
|
||||
.printPruned()
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxWithRamInitSynth {
|
||||
def main(args: Array[String]) {
|
||||
val config = SpinalConfig(
|
||||
targetDirectory = "synth",
|
||||
defaultClockDomainFrequency = FixedFrequency(12 MHz)
|
||||
)
|
||||
config
|
||||
.generateVerilog(
|
||||
Murax(
|
||||
MuraxConfig.default.copy(
|
||||
onChipRamSize = 4 kB,
|
||||
onChipRamHexFile = "src/main/c/murax/gcd_world/build/gcd_world.hex"
|
||||
)
|
||||
)
|
||||
)
|
||||
.printPruned()
|
||||
}
|
||||
}
|
||||
|
||||
object Murax_arty {
|
||||
def main(args: Array[String]) {
|
||||
val hex = "src/main/c/murax/hello_world/build/hello_world.hex"
|
||||
SpinalVerilog(
|
||||
Murax(
|
||||
MuraxConfig
|
||||
.default(false)
|
||||
.copy(
|
||||
coreFrequency = 100 MHz,
|
||||
onChipRamSize = 32 kB,
|
||||
onChipRamHexFile = hex
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxAsicBlackBox extends App {
|
||||
println("Warning this soc do not has any rom to boot on.")
|
||||
val config = SpinalConfig()
|
||||
config.addStandardMemBlackboxing(blackboxAll)
|
||||
config.generateVerilog(Murax(MuraxConfig.default()))
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package vexriscv.periph.gcd
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
|
||||
import spinal.lib.eda.altera.QSysify
|
||||
import spinal.lib.slave
|
||||
|
||||
object Apb3GCDCtrl {
|
||||
def getApb3Config = Apb3Config(
|
||||
addressWidth = 5,
|
||||
dataWidth = 32,
|
||||
selWidth = 1,
|
||||
useSlaveError = false
|
||||
)
|
||||
}
|
||||
|
||||
class Apb3GCDCtrl(apb3Config : Apb3Config) extends Component {
|
||||
val io = new Bundle {
|
||||
val apb = slave(Apb3(Apb3GCDCtrl.getApb3Config))
|
||||
// maybe later
|
||||
// val interrupt = out Bool
|
||||
}
|
||||
val gcdCtrl = new GCDTop()
|
||||
val apbCtrl = Apb3SlaveFactory(io.apb)
|
||||
apbCtrl.driveAndRead(gcdCtrl.io.a, address=0)
|
||||
apbCtrl.driveAndRead(gcdCtrl.io.b, address=4)
|
||||
// when result of calculation ready, synchronize it into memory mapped register
|
||||
val resSyncBuf = RegNextWhen(gcdCtrl.io.res, gcdCtrl.io.ready)
|
||||
apbCtrl.read(resSyncBuf, address=8)
|
||||
// if result is read, it will be consumed, set ready to 0
|
||||
apbCtrl.onRead(8)(resSyncBuf := 0)
|
||||
apbCtrl.onRead(8)(rdySyncBuf := False)
|
||||
// synchronize ready signal into memory mapped register
|
||||
val rdySyncBuf = RegNextWhen(gcdCtrl.io.ready, gcdCtrl.io.ready)
|
||||
apbCtrl.read(rdySyncBuf, address=12)
|
||||
// set valid based on memory mapped register but clear/consume it after 1 cycle <s
|
||||
gcdCtrl.io.valid := apbCtrl.setOnSet(RegNext(False) init(False), address=16, 0)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package vexriscv.periph.gcd
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.master
|
||||
import spinal.lib.fsm._
|
||||
|
||||
//Hardware definition
|
||||
class GCDCtrl() extends Component {
|
||||
val io = new Bundle {
|
||||
val valid = in Bool()
|
||||
val ready = out Bool()
|
||||
val dataCtrl = master(GCDDataControl())
|
||||
}
|
||||
val fsm = new StateMachine{
|
||||
io.dataCtrl.loadA := False
|
||||
io.dataCtrl.loadB := False
|
||||
io.dataCtrl.init := False
|
||||
io.dataCtrl.selL := False
|
||||
io.dataCtrl.selR := False
|
||||
io.ready := False
|
||||
val idle : State = new State with EntryPoint{
|
||||
whenIsActive{
|
||||
when(io.valid){
|
||||
io.dataCtrl.init := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
}
|
||||
val calculate : State = new State{
|
||||
whenIsActive{
|
||||
when(io.dataCtrl.cmpAgtB){
|
||||
goto(calcA)
|
||||
}.elsewhen(io.dataCtrl.cmpAltB){
|
||||
goto(calcB)
|
||||
}.elsewhen(!io.dataCtrl.cmpAgtB & !io.dataCtrl.cmpAgtB){
|
||||
goto(calcDone)
|
||||
}
|
||||
}
|
||||
}
|
||||
val calcA : State = new State{
|
||||
whenIsActive{
|
||||
io.dataCtrl.selR := True
|
||||
io.dataCtrl.loadA := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
val calcB : State = new State{
|
||||
whenIsActive{
|
||||
io.dataCtrl.selL := True
|
||||
io.dataCtrl.loadB := True
|
||||
goto(calculate)
|
||||
}
|
||||
}
|
||||
val calcDone : State = new State{
|
||||
whenIsActive{
|
||||
io.ready := True
|
||||
goto(idle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object GCDCtrlVerilog {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(new GCDCtrl)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package vexriscv.periph.gcd
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.slave
|
||||
|
||||
//Hardware definition
|
||||
class GCDData() extends Component {
|
||||
val io = new Bundle {
|
||||
val a = in(UInt(32 bits))
|
||||
val b = in(UInt(32 bits))
|
||||
val res = out(UInt(32 bits))
|
||||
val dataCtrl = slave(GCDDataControl())
|
||||
}
|
||||
/*
|
||||
*
|
||||
* // Pseudocode of the Euclids algorithm for calculating the GCD
|
||||
* inputs: [a, b, start]
|
||||
* outputs: [done, a]
|
||||
* done := False
|
||||
* while(!done):
|
||||
* if(a > b):
|
||||
* a := a - b
|
||||
* else if(b > a):
|
||||
* b := b - a
|
||||
* else:
|
||||
* done := True
|
||||
*/
|
||||
//registers
|
||||
val regA = Reg(UInt(32 bits)) init(0)
|
||||
val regB = Reg(UInt(32 bits)) init(0)
|
||||
// compare
|
||||
val xGTy = regA > regB
|
||||
val xLTy = regA < regB
|
||||
// mux
|
||||
val chX = io.dataCtrl.selL ? regB | regA
|
||||
val chY = io.dataCtrl.selR ? regB | regA
|
||||
// subtract
|
||||
val subXY = chX - chY
|
||||
// load logic
|
||||
when(io.dataCtrl.init){
|
||||
regA := io.a
|
||||
regB := io.b
|
||||
}
|
||||
when(io.dataCtrl.loadA){
|
||||
regA := subXY
|
||||
}
|
||||
when(io.dataCtrl.loadB){
|
||||
regB := subXY
|
||||
}
|
||||
io.dataCtrl.cmpAgtB := xGTy
|
||||
io.dataCtrl.cmpAltB := xLTy
|
||||
io.res := regA
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package vexriscv.periph.gcd
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.IMasterSlave
|
||||
|
||||
case class GCDDataControl() extends Bundle with IMasterSlave{
|
||||
val cmpAgtB = Bool
|
||||
val cmpAltB = Bool
|
||||
val loadA = Bool
|
||||
val loadB = Bool
|
||||
val init = Bool
|
||||
val selL = Bool
|
||||
val selR = Bool
|
||||
// define <> semantic
|
||||
override def asMaster(): Unit = {
|
||||
// as controller: output, input
|
||||
out(loadA, loadB, selL, selR, init)
|
||||
in(cmpAgtB, cmpAltB)
|
||||
}
|
||||
}
|
||||
|
||||
//Hardware definition
|
||||
class GCDTop() extends Component {
|
||||
val io = new Bundle {
|
||||
val valid = in Bool()
|
||||
val ready = out Bool()
|
||||
val a = in(UInt(32 bits))
|
||||
val b = in(UInt(32 bits))
|
||||
val res = out(UInt(32 bits))
|
||||
}
|
||||
val gcdCtr = new GCDCtrl()
|
||||
gcdCtr.io.valid := io.valid
|
||||
io.ready := gcdCtr.io.ready
|
||||
val gcdDat = new GCDData()
|
||||
gcdDat.io.a := io.a
|
||||
gcdDat.io.b := io.b
|
||||
io.res := gcdDat.io.res
|
||||
gcdCtr.io.dataCtrl <> gcdDat.io.dataCtrl
|
||||
}
|
||||
|
||||
object GCDTopVerilog {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(new GCDTop)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package vexriscv.periph.gcd
|
||||
|
||||
import spinal.core._
|
||||
import spinal.sim._
|
||||
import spinal.core.sim._
|
||||
|
||||
//import scala.util.Random
|
||||
import java.util.concurrent.ThreadLocalRandom
|
||||
object GCDTopSim {
|
||||
def main(args: Array[String]) {
|
||||
|
||||
SimConfig.withWave.doSim(new GCDTop()){dut =>
|
||||
// SimConfig.doSim(new GCDTop()){dut =>
|
||||
def gcd(a: Long,b: Long): Long = {
|
||||
if(b==0) a else gcd(b, a%b)
|
||||
}
|
||||
def RndNextUInt32(): Long = {
|
||||
ThreadLocalRandom.current().nextLong(Math.pow(2, 32).toLong - 1)
|
||||
}
|
||||
var a = 0L
|
||||
var b = 0L
|
||||
var model = 0L
|
||||
dut.io.a #= 0
|
||||
dut.io.b #= 0
|
||||
dut.io.valid #= false
|
||||
|
||||
dut.clockDomain.forkStimulus(period = 10)
|
||||
dut.clockDomain.waitRisingEdge()
|
||||
|
||||
for(idx <- 0 to 500){
|
||||
// generate 2 random ints
|
||||
a = RndNextUInt32()
|
||||
b = RndNextUInt32()
|
||||
// calculate the model value (software)
|
||||
model = gcd(a,b)
|
||||
// apply stimulus with random ints
|
||||
dut.io.a #= a
|
||||
dut.io.b #= b
|
||||
dut.io.valid #= true
|
||||
dut.clockDomain.waitRisingEdge()
|
||||
dut.io.valid #= false
|
||||
// wait until calculation of hardware is done
|
||||
waitUntil(dut.io.ready.toBoolean)
|
||||
assert(
|
||||
assertion = (dut.io.res.toBigInt == model),
|
||||
message = "test " + idx + " failed. Expected " + model + ", retrieved: " + dut.io.res.toBigInt
|
||||
)
|
||||
waitUntil(!dut.io.ready.toBoolean)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
140
doc/nativeJtag/README.md
Normal file
140
doc/nativeJtag/README.md
Normal file
|
@ -0,0 +1,140 @@
|
|||
# Implementing VexRiscv Based Murax SoC on Arty A7 Artix-7 PCB from Digilent and Enabling JTAG Connection through Xilinx’s BSCANE2 Debug IP
|
||||
|
||||
**By**<br>
|
||||
**Pradeep Krishnamurthy – Student Research Assistant, OFFIS e.V.**<br>
|
||||
**Frank Poppen – Senior Research Engineer, OFFIS e.V.**<br>
|
||||
|
||||
**www.offis.de**
|
||||
|
||||
Acknowledgement
|
||||
This work was supported in part by the German Federal Ministry of Education and Research (BMBF) within the project
|
||||
SATiSFy under contract no. 16KIS0821K, and within the project Scale4Edge under contract no. 16ME0127.
|
||||
|
||||
## 1. Introduction
|
||||
Up-to-date FPGA evaluation boards, like the Digilent Arty A7 mounting a Xilinx Artix-7 FPGA, come with an integrated
|
||||
FTDI chip which makes programming and debugging quite easy. In our work, we synthesized the VexRiscv based Murax
|
||||
processor to an Artix-7 FPGA and at first lead out the JTAG relevant signals of the Riscv core to the board’s Pmod
|
||||
Header to connect to a dedicated Olimex JTAG Adapter through a second USB cable. As it turns out, this extra effort
|
||||
on hardware can be minimized by use of some Xilinx Debug IP named BSCANE2. Collecting the required information on how
|
||||
to do this was tedious. So we came to the decision to document our path to success with this short report. We expect
|
||||
that the reader is familiar with the README.md to be found at https://github.com/SpinalHDL/VexRiscv and that the
|
||||
reader is capable of generating the Murax SoC as it is described there.
|
||||
|
||||
## 2. SpinalHDL - Generation of Murax SoC with BSCANE2
|
||||
The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary Scan logic controller. This allows
|
||||
for communication between the internally running design and the dedicated JTAG pins of the FPGA.
|
||||
|
||||
Run the following command at the top level of the repository.
|
||||
|
||||
```sh
|
||||
sbt "runMain vexriscv.demo.MuraxWithRamInitWithNativeJtag"
|
||||
```
|
||||
|
||||
The Murax configuration `MuraxWithRamInitWithNativeJtag` activates `WithNativeJtag` flag, which removes toplevel Jtag signals from the default Murax configuration and integrates `BSCANE2` plugin.
|
||||
|
||||
After code generation you will see the Verilog file `Murax.v` next to four `.bin` files at the top level of the repository. These files are the input to the Xilinx FPGA synthesis. Inside the `Murax.v` file, we can see that the BSCANE2 ports are instantiated, confirming that the BSCANE2 has successfully been instantiated within the Murax SoC as a debug bridge to JTAG.
|
||||
|
||||
## 3. Xilinx Vivado - Programming Arty A7 FPGA
|
||||
There are many applications to program a FPGA. In our work we referred to the freely available Xilinx Vivado 2020
|
||||
application to synthesize and program the FPGA. Vivado is readily available at Xilinx website and free of cost to
|
||||
download. This document assumes that the reader is able to setup and execute FPGA synthesis projects. The
|
||||
following is not a step by step tutorial, but gives general guiding information.
|
||||
|
||||
### Programming the FPGA
|
||||
|
||||
* Create a new project and choose the board. In our case it is the Arty A7-35 (`xc7a35ticsg324-1L`).
|
||||
* Copy the mentioned files (.v and .bin) of the previous section from the Vexriscv folder into the Vivado project
|
||||
in e.g. the path: `project_name.srcs\sources_1\imports\Downloads`
|
||||
* Create a toplevel file by instantiating Murax I/O ports in it to blink the LED’s on the Digilent board. (Note: The program to blink the LED’s is already present in the four `.bin` files with the `Murax.v` file). The toplevel file and constraint `arty_a7.xdc` file, if required, can be found and reused from the path: `VexRiscv/scripts/Murax/arty_a7`, but you need to make sure that all the JTAG ports of Murax are commented or deleted in the toplevel file. Remember: we removed them in Section 2 and connected them internally to the BSCANE2 debug bridge.
|
||||
* Be aware that line numbers as given could move with future changes to the file. The lines to remove from toplevel file are:
|
||||
```
|
||||
[43] reg tesic_tck,tesic_tms,tesic_tdi;
|
||||
[44] wire tesic_tdo;
|
||||
[45] reg soc_tck,soc_tms,soc_tdi;
|
||||
[46] wire soc_tdo;
|
||||
[47]
|
||||
[48] always @(*) begin
|
||||
[49] {soc_tck, soc_tms, soc_tdi } = {tck,tms,tdi};
|
||||
[50] tdo = soc_tdo;
|
||||
[51] end
|
||||
…
|
||||
[56] .io_jtag_tck(soc_tck),
|
||||
[57] .io_jtag_tdi(soc_tdi),
|
||||
[58] .io_jtag_tdo(soc_tdo),
|
||||
[59] .io_jtag_tms(soc_tms),
|
||||
```
|
||||
* Also remove any JTAG port to pin assignments from any constraint file.
|
||||
* Next, click Generate Bitstream and program the FPGA with the bit file. You can see the LED’s blink and Murax SoC has been programmed into the FPGA.
|
||||
|
||||
### 4. Debugging - Using OpenOCD and GDB
|
||||
* Clone and setup openocd with the steps as provided by https://github.com/SpinalHDL/openocd_riscv
|
||||
* You basically have to provide two files for OpenOCD to connect successfully through the FPGA into the Murax SoC inside it:
|
||||
1. `usb_connect.cfg` (interface configuration)
|
||||
2. `soc_init.cfg` (take over the control of the CPU)
|
||||
* `usb_connect.cfg`
|
||||
You can take it from ... https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg ... without modifications as we would say. Be aware that it includes the two files `xilinx-xc7.cfg` and `jtagspi.cfg` which are part of the OpenOCD project ... https://github.com/riscv/riscv-openocd/tree/riscv/tcl/cpld , but make sure to check the path for the files. If required, adapt the find and path for the lines:
|
||||
```
|
||||
[29] source [find cpld/xilinx-xc7.cfg]
|
||||
[30] source [find cpld/jtagspi.cfg]
|
||||
```
|
||||
* `soc_init.cfg`
|
||||
https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg
|
||||
You can take it but you need to: `set cpu_count to 1` and remove lines 22 to 35 as shown in the result below:
|
||||
```
|
||||
set cpu_count 1
|
||||
|
||||
for {set i 0} {$i < $cpu_count} {incr i} {
|
||||
target create saxon.cpu$i vexriscv -endian little -chain-position $TAP_NAME -coreid $i -dbgbase [expr $i*0x1000+0x10B80000]
|
||||
vexriscv readWaitCycles 40
|
||||
vexriscv cpuConfigFile $CPU0_YAML
|
||||
if {$SPINAL_SIM != "yes"} {
|
||||
vexriscv jtagMapping 3 3 0 1 2 2
|
||||
}
|
||||
}
|
||||
|
||||
for {set i 0} {$i < $cpu_count} {incr i} {
|
||||
targets saxon.cpu$i
|
||||
poll_period 50
|
||||
init
|
||||
soft_reset_halt
|
||||
}
|
||||
|
||||
puts " done"
|
||||
```
|
||||
* Run openocd:
|
||||
```
|
||||
openocd -c "set CPU0_YAML ../VexRiscv/cpu0.yaml" \
|
||||
-f tcl/interface/usb_connect.cfg \
|
||||
-f tcl/interface/soc_init.cfg
|
||||
```
|
||||
On success you should be able to see something like
|
||||
```
|
||||
Open On-Chip Debugger 0.10.0+dev-01231-gf8c1c8ad-dirty (2021-05-03-10:57)
|
||||
Licensed under GNU GPL v2
|
||||
For bug reports, read
|
||||
http://openocd.org/doc/doxygen/bugs.html
|
||||
../../cpu0.yaml
|
||||
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
|
||||
xc7.tap
|
||||
Info : set servers polling period to 50ms
|
||||
Info : clock speed 5000 kHz
|
||||
Info : JTAG tap: xc7.tap tap/device found: 0x0362d093 (mfg: 0x049 (Xilinx), part: 0x362d, ver: 0x0)
|
||||
Info : starting gdb server for saxon.cpu0 on 3333
|
||||
Info : Listening on port 3333 for gdb connections
|
||||
requesting target halt and executing a soft reset
|
||||
done
|
||||
Info : Listening on port 6666 for tcl connections
|
||||
Info : Listening on port 4444 for telnet connections
|
||||
```
|
||||
* Information on setting up a riscv compiler and debugger toolchain are to be found at:
|
||||
https://github.com/riscv/riscv-gnu-toolchain
|
||||
* With openocd running you can now connect a debugger to `port 3333`.
|
||||
* A demonstration software to compile and debug with the Murax SoC can be found at https://github.com/SpinalHDL/VexRiscvSocSoftware in the path `VexRiscvSocSoftware/projects/murax/demo`. With a `make` you create the `.elf` in the `build` directory from which you then give the command:
|
||||
```
|
||||
riscv64-unknown-elf-gdb demo.elf
|
||||
```
|
||||
* The riscv debugger is started with the `demo.elf` program and is ready to be connected to the CPU. Do so by issuing the following command in its window:
|
||||
* `target remote localhost:3333` This command will connect the GDB server to OpenOCD
|
||||
* `load` This command will load the program into the FPGA. Whenever you decide to make changes to the demo software and recompiled it, you need to upload the resulting new executable to the CPU in this way.
|
||||
* `monitor reset halt` This command resets the Murax CPU and halts it to receive further commands.
|
||||
* `continue` From here on you should be able to execute a regular debug session with your VexRiscv based Murax SoC on the FPGA.
|
26
doc/nativeJtag/soc_init.cfg
Normal file
26
doc/nativeJtag/soc_init.cfg
Normal file
|
@ -0,0 +1,26 @@
|
|||
if [info exists env(SPINAL_SIM)] {
|
||||
set SPINAL_SIM $::env(SPINAL_SIM)
|
||||
} else {
|
||||
set SPINAL_SIM no
|
||||
}
|
||||
|
||||
set cpu_count 1
|
||||
|
||||
|
||||
for {set i 0} {$i < $cpu_count} {incr i} {
|
||||
target create saxon.cpu$i vexriscv -endian little -chain-position $TAP_NAME -coreid $i -dbgbase [expr $i*0x1000+0x10B80000]
|
||||
vexriscv readWaitCycles 40
|
||||
vexriscv cpuConfigFile $CPU0_YAML
|
||||
if {$SPINAL_SIM != "yes"} {
|
||||
vexriscv jtagMapping 3 3 0 1 2 2
|
||||
}
|
||||
}
|
||||
|
||||
for {set i 0} {$i < $cpu_count} {incr i} {
|
||||
targets saxon.cpu$i
|
||||
poll_period 50
|
||||
init
|
||||
soft_reset_halt
|
||||
}
|
||||
|
||||
puts " done"
|
14
doc/nativeJtag/usb_connect.cfg
Normal file
14
doc/nativeJtag/usb_connect.cfg
Normal file
|
@ -0,0 +1,14 @@
|
|||
adapter driver ftdi
|
||||
ftdi_device_desc "Digilent USB Device"
|
||||
ftdi_vid_pid 0x0403 0x6010
|
||||
ftdi_channel 0
|
||||
ftdi_layout_init 0x00e8 0x60eb
|
||||
ftdi_tdo_sample_edge falling
|
||||
|
||||
reset_config none
|
||||
adapter speed 5000
|
||||
|
||||
source [find cpld/xilinx-xc7.cfg]
|
||||
source [find cpld/jtagspi.cfg]
|
||||
|
||||
set TAP_NAME xc7.tap
|
216
doc/smp/smp.md
Normal file
216
doc/smp/smp.md
Normal file
|
@ -0,0 +1,216 @@
|
|||
# Coherent interface specification
|
||||
|
||||
Features :
|
||||
- 3 interface (write, read, probe) composed of 7 streams
|
||||
- Two data paths (read + write), but allow dirty/clean sharing by reusing the write data path
|
||||
- Allow multi level coherent interconnect
|
||||
- No ordering, but provide barrier
|
||||
- Allow cache-full and cache-less agents
|
||||
|
||||
## A few hint to help reading the spec
|
||||
|
||||
In order to make the spec more readable, there is some definitions :
|
||||
|
||||
### Stream
|
||||
|
||||
A stream is a primitive interface which carry transactions using a valid/ready handshake.
|
||||
|
||||
### Memory copy
|
||||
|
||||
To talk in a non abstract way, in a system with multiple caches, a given memory address can potentialy be loaded in multiple caches at the same time. So let's define that :
|
||||
|
||||
- The DDR memory is named `main memory`
|
||||
- Each cache line can be loaded with a part of the main memory, let's name that a `memory copy`
|
||||
|
||||
### Master / Interconnect / Slave
|
||||
|
||||
A master could be for instance a CPU cache, the side of the interconnect toward the main memory or toward a more general interconnect.
|
||||
|
||||
A slave could be main memory, the side of the interconnect toward a CPU cache or toward a less general interconnect.
|
||||
|
||||
The spec will try to stay abstract and define the coherent interface as something which can be used between two agents (cpu, interconnect, main memory)
|
||||
|
||||
## Memory copy status
|
||||
|
||||
Memory copy, in other words, cache line, have more states than non coherent systems :
|
||||
|
||||
| Name | Description |
|
||||
|---------------|-------------|
|
||||
| Valid/Invalid | Line loaded or not |
|
||||
| Shared/Unique | shared => multiple copy of the cache line in different caches, unique => no other caches has a copy of the line |
|
||||
| Owner/Lodger | lodger => copy of the line, but no other responsibility, owner => the given cache is responsible to write back dirty data and answer probes with the data |
|
||||
| Clean/Dirty | clean => match main memory, dirty => main memory need updates |
|
||||
|
||||
All combination of those cache flag are valid. But if a cache line is invalid, the other status have no meaning.
|
||||
|
||||
Later in the spec, memory copy state can be described for example as :
|
||||
|
||||
- VSOC for (Valid, Shared, Owner, Clean)
|
||||
- V-OC for (Valid, Shared or Unique, Owner, Clean)
|
||||
- !V-OC for NOT (Valid, Shared or Unique, Owner, Clean)
|
||||
- ...
|
||||
|
||||
## Coherent interface
|
||||
|
||||
One full coherent interface is composed of 3 inner interfaces, them-self composed of 7 stream described bellow as `interfaceName (Side -> StreamName -> Side -> StreamName -> ...)`
|
||||
- write (M -> writeCmd -> S -> writeRsp -> M)
|
||||
- read (M -> readCmd- > S -> readRsp -> M -> readAck -> S)
|
||||
- probe (S -> probeCmd -> M -> probeRsp -> S)
|
||||
|
||||
The following streams could physically be merges in order to reduce the number of arbitration :
|
||||
|
||||
- writeCmd, probeRsp, readAck
|
||||
- writeRsp, readRsp
|
||||
|
||||
### Read interface
|
||||
|
||||
Used by masters to obtain new memory copies and make copies unique (used to write them).
|
||||
|
||||
Composed of 3 stream :
|
||||
|
||||
| Name | Direction | Description |
|
||||
|---------|-----------|----------|
|
||||
| readCmd | M -> S | Emit memory read and cache management commands |
|
||||
| readRsp | M <- S | Return some data and/or a status from readCmd |
|
||||
| readAck | M -> S | Return ACK from readRsp to synchronize the interconnect status |
|
||||
|
||||
### Write interface
|
||||
|
||||
Used by masters to write data back to the memory and notify the interconnect of memory copies eviction (used to keep potential directories updated).
|
||||
|
||||
Composed of 2 stream :
|
||||
|
||||
| Name | Direction | Description |
|
||||
|---------|-----------|----------|
|
||||
| writeCmd | M -> S | Emit memory writes and cache management commands |
|
||||
| writeRsp | M <- S | Return a status from writeCmd |
|
||||
|
||||
### Probe interface
|
||||
|
||||
Used by the interconnect to order master to change their memory copies status and get memory copies owners data.
|
||||
|
||||
Composed of 2 stream :
|
||||
|
||||
| Name | Direction | Description |
|
||||
|----------|-----------|----------|
|
||||
| probeCmd | M <- S | Used for cache management |
|
||||
| probeRsp | M -> S | Acknowledgment |
|
||||
|
||||
## Transactions
|
||||
|
||||
This chapter define transactions moving over the 3 previously defined interface (read/write/probe).
|
||||
|
||||
### Read commands
|
||||
|
||||
Emitted on the readCmd channel (master -> slave)
|
||||
|
||||
| Command | Initial state | Description | Usage example |
|
||||
|-------------|---------------|----------|------|
|
||||
| readShared | I--- | Get a memory copy as V--- | Want to read a uncached address |
|
||||
| readUnique | I--- | Get a memory copy as VUO- | Want to write a uncached address |
|
||||
| readOnce | I--- | Get a memory copy without coherency tracking | Instruction cache read |
|
||||
| makeUnique | VS-- | Make other memory copy as I--- and make yourself VUO- | Want to write into a shared line |
|
||||
| readBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence |
|
||||
|
||||
makeUnique should be designed with care. There is a few corner cases :
|
||||
- While a master has a inflight makeUnique, a probe can change its state, in such case, the makeUnique become weak and invalidation is canceled. This is usefull for multi level coherent interconnects.
|
||||
- Multi level coherent interconnect should be careful to properly move the ownership and not lose dirty data
|
||||
|
||||
I'm not sure yet if we should add some barrier transactions to enforce
|
||||
|
||||
### Read responses
|
||||
|
||||
Emitted on the readRsp channel (master <- slave)
|
||||
|
||||
readSuccess, readError, data shared/unique clean/dirty owner/notOwner
|
||||
|
||||
| Responses | From command | Description |
|
||||
|-------------|---------------|----------|
|
||||
| readSuccess | makeUnique, readBarrier | - |
|
||||
| readError | readShared, readUnique, readOnce | Bad address |
|
||||
| readData | readShared, readUnique, readOnce | Data + coherency status (V---) |
|
||||
|
||||
### Read ack
|
||||
|
||||
Emitted on the readAck channel (master -> slave), it carry no information, just a notification that the master received the read response
|
||||
|
||||
| Name | From command | Description |
|
||||
|--------------|---------------|----------|
|
||||
| readSuccess | * | - |
|
||||
|
||||
### Write commands
|
||||
|
||||
Write commands can be emitted on the writeCmd channel (master -> slave)
|
||||
|
||||
| Name | Initial state | Description | Usage example |
|
||||
|--------------|---------------|----------|----------|
|
||||
| writeInvalid | V-O- | Write the memory copy and update it status to I--- | Need to free the dirty cache line |
|
||||
| writeShare | V-O- | Write the memory copy but keep it as VSO- | A probe makeShared asked it |
|
||||
| writeUnique | VUO- | Write the memory copy but keep it as VUO- | A probe probeOnce need to read the data |
|
||||
| evict | V---, !V-OD | Notify the interconnect that the cache line is now I--- | Need to free a clean cache line |
|
||||
| writeBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence |
|
||||
|
||||
### Write responses
|
||||
|
||||
Emitted on the writeRsp channel (master <- slave), it carry no information, just a notification that the corresponding command is done.
|
||||
|
||||
| Name | From command | Description |
|
||||
|--------------|---------------|----------|
|
||||
| writeSuccess | * | - |
|
||||
|
||||
### Probe commands
|
||||
|
||||
Probe commands can be emitted on the probeCmd channel (slave -> master)
|
||||
|
||||
| Name | Description | Usage example |
|
||||
|-------------|-------------|---------------|
|
||||
| makeInvalid | Make the memory copy I--- | Another cache want to make his shared copy unique to write it |
|
||||
| makeShared | Make the memory copy VS-- | Another cache want to read a memory block, so unique copy need to be shared |
|
||||
| probeOnce | Read the V-O- memory copy | A non coherent agent did a readOnce |
|
||||
|
||||
makeInvalid and makeShared could result into one of the following probeSuccess, writeInvalid, writeShare
|
||||
|
||||
probeOnce can result into one of the following probeSuccess, writeShare, writeUnique
|
||||
|
||||
To help the slave matching the writeInvalid and writeShare generated from a probe, those request are tagged with a matching ID.
|
||||
|
||||
### Probe responses
|
||||
|
||||
Emitted on the probeRsp channel (master -> slave), it carry no information, just a notification that the corresponding command is done.
|
||||
|
||||
| Name | From command | Description |
|
||||
|--------------|---------------|----------|
|
||||
| probeSuccess | * | - |
|
||||
|
||||
|
||||
## Channel interlocking
|
||||
|
||||
This is a delicate subject as if everything was permited, it would be easy to end up with deadlocks.
|
||||
|
||||
There is the streams priority (top => high priority, bottom => low priority) A lower priority stream should not block a higher priority stream in order to avoid deadlocks.
|
||||
- writeCmd, writeRsp, readRsp, readAck, probeRsp. Nothing should realy block them excepted bandwidth
|
||||
- probeCmd. Can be blocked by inflight/generated writes
|
||||
- readCmd. Can be blocked by inflight/generated probes
|
||||
|
||||
In other words :
|
||||
|
||||
Masters can emit writeCmd and wait their writeRsp completion before answering probes commands.
|
||||
Slaves can emit probeCmd and wait their proveRsp completion before answering reads.
|
||||
Slaves can emit readRsp and wait on their readAck completion before doing anything else
|
||||
|
||||
## Interface subsets
|
||||
|
||||
There is a few cases where you could need a specific subset of the coherent interface :
|
||||
- Instruction caches do not necessarily need to maintain the coherency with the memory system.
|
||||
- DMA need to read and write the memory system, but are cache-less (no probe)
|
||||
|
||||
### ReadOnly interface without maintained coherency
|
||||
|
||||
Such interface is only composed of the read bus on which the readCmd stream can only use readOnce requests
|
||||
|
||||
|
||||
### WriteOnly interface
|
||||
|
||||
In such interface, there is no read/probe buses, but only a writeCmd and a writeRsp stream. The writeCmd will invalidate other memory copies, then write into the memory while the writeRsp will return a writeSuccess/writeError status.
|
||||
|
||||
|
106
doc/vjtag/README.md
Normal file
106
doc/vjtag/README.md
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Intel VJTAG
|
||||
*By Levi Walker (@LYWalker)*
|
||||
|
||||
Intel VJTAG allows JTAG communication with the FPGA fabric of Altera devices through the standard USB cable using the onboard USB-Blaster. This avoids the needs to breakout the JTAG signals to the GPIO and use a dedicated external debugger.
|
||||
|
||||
## How to use VJTAG with Briey
|
||||
In Briey.scala remove the following lines (note: line numbers may differ, depending on edits):
|
||||
|
||||
```
|
||||
[185] val jtag = slave(Jtag())
|
||||
...
|
||||
[466] val tcpJtag = JtagTcp(
|
||||
[467] jtag = dut.io.jtag,
|
||||
[468] jtagClkPeriod = jtagClkPeriod
|
||||
[469] )
|
||||
```
|
||||
|
||||
Then VJAG can be added in two ways.
|
||||
|
||||
### Method 1
|
||||
Replace the following line in Briey.scala:
|
||||
|
||||
```
|
||||
[311] io.jtag <> plugin.io.bus.fromJtag()
|
||||
```
|
||||
with
|
||||
```
|
||||
[311] plugin.io.bus.fromVJtag()
|
||||
```
|
||||
|
||||
### Method 2
|
||||
Replace the following line in Briey.scala:
|
||||
|
||||
```
|
||||
[311] io.jtag <> plugin.io.bus.fromJtag()
|
||||
```
|
||||
with
|
||||
```
|
||||
[311] val tap = new sld_virtual_jtag(2)
|
||||
[312] val jtagCtrl = tap.toJtagTapInstructionCtrl()
|
||||
[313] jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.io.tck),0)
|
||||
```
|
||||
And add
|
||||
```
|
||||
import spinal.lib.blackbox.altera.sld_virtual_jtag
|
||||
```
|
||||
to the imports at the top of the file.
|
||||
|
||||
This uses the existing JtagInstructionCtrl architecture and communicates using DR headers.
|
||||
|
||||
## Using OpenOCD
|
||||
|
||||
First, clone and setup openocd with the steps as provided by https://github.com/SpinalHDL/openocd_riscv
|
||||
|
||||
Then in tcl/target/Briey.cfg set `_USE_VJTAG` to 1:
|
||||
```
|
||||
[3] set _USE_VJTAG 1
|
||||
```
|
||||
|
||||
Then if you used Method 1 above uncomment line 25:
|
||||
```
|
||||
[25] vexriscv jtagMapping 0 1 0 0 0 0
|
||||
```
|
||||
If you used Method 2 uncomment line 27:
|
||||
```
|
||||
[27] vexriscv jtagMapping 0 0 0 1 2 2
|
||||
```
|
||||
|
||||
If the board uses USB-Blaster2 then run OpenOCD in shell using:
|
||||
```
|
||||
openocd -c "set CPU0_YAML ../VexRiscv/cpu0.yaml" \
|
||||
-f tcl/interface/altera-usb-blaster2.cfg \
|
||||
-f tcl/interface/soc_init.cfg
|
||||
```
|
||||
Note: you may need to edit `tcl/interface/altera-usb-blaster2.cfg` with your quartus path.
|
||||
|
||||
If using an older board using USB-Blaster run using:
|
||||
```
|
||||
openocd -c "set CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/interface/altera-usb-blaster.cfg -f tcl/interface/Briey.cfg
|
||||
```
|
||||
|
||||
On success it should look something like:
|
||||
```
|
||||
Open On-Chip Debugger 0.11.0+dev-02588-gb10abb4b1 (2022-11-07-13:38)
|
||||
Licensed under GNU GPL v2
|
||||
For bug reports, read
|
||||
http://openocd.org/doc/doxygen/bugs.html
|
||||
../../Verilog/cpu0.yaml
|
||||
Info : only one transport option; autoselect 'jtag'
|
||||
DEPRECATED! use 'adapter speed' not 'adapter_khz'
|
||||
DEPRECATED! use 'adapter srst delay' not 'adapter_nsrst_delay'
|
||||
Info : set servers polling period to 50ms
|
||||
Info : usb blaster interface using libftdi
|
||||
Info : This adapter doesn't support configurable speed
|
||||
Info : JTAG tap: fpgasoc.fpga.tap tap/device found: 0x020f20dd (mfg: 0x06e (Altera), part: 0x20f2, ver: 0x0)
|
||||
[fpga_spinal.cpu0] Target successfully examined.
|
||||
Info : starting gdb server for fpga_spinal.cpu0 on 3333
|
||||
Info : Listening on port 3333 for gdb connections
|
||||
requesting target halt and executing a soft reset
|
||||
Info : Listening on port 6666 for tcl connections
|
||||
Info : Listening on port 4444 for telnet connections
|
||||
```
|
||||
|
||||
From this point on attach a gdb connection and debug the board as usual.
|
||||
|
||||
*NOTE: You may need to add your boards FPGA ID to line [21] of Briey.cfg, simply append it to the other expected ids using: `-expected-id <your id>`. The IDs for the DE1-SoC and DE0 have already been added.*
|
|
@ -1 +1 @@
|
|||
sbt.version=0.13.16
|
||||
sbt.version=1.6.0
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.1")
|
||||
|
129
scripts/Murax/arty_a7/README.md
Normal file
129
scripts/Murax/arty_a7/README.md
Normal file
|
@ -0,0 +1,129 @@
|
|||
This example is for the Digilent ARTY A7 35T board.
|
||||
|
||||
# Using the example
|
||||
|
||||
## Before Starting
|
||||
|
||||
You should make sure you have the following tools installed:
|
||||
* vivado 2018.1 or later
|
||||
* riscv toolchain (riscv64-unknown-elf)
|
||||
* sbt
|
||||
|
||||
## Board setup
|
||||
Make sure you have a rev E board. If you have a later version check that the
|
||||
flash part is S25FL128SAGMF100.
|
||||
|
||||
Jumper settings for board rev E:
|
||||
* Disconnect anything from the connectors (Pmod, Arduino)
|
||||
* Jumpers: JP1 and JP2 on, others off.
|
||||
|
||||
## Building
|
||||
|
||||
You should be able to just type `make` and get output similar to this;
|
||||
```
|
||||
...
|
||||
Memory region Used Size Region Size %age Used
|
||||
RAM: 896 B 2 KB 43.75%
|
||||
...
|
||||
---------------------------------------------------------------------------------
|
||||
Finished RTL Elaboration : Time (s): cpu = 00:00:08 ; elapsed = 00:00:09 . Memory (MB): peak = 1457.785 ; gain = 243.430 ; free physical = 17940 ; free virtual = 57159
|
||||
---------------------------------------------------------------------------------
|
||||
...
|
||||
---------------------------------------------------------------------------------
|
||||
Finished Technology Mapping : Time (s): cpu = 00:02:42 ; elapsed = 00:02:58 . Memory (MB): peak = 1986.879 ; gain = 772.523 ; free physical = 17454 ; free virtual = 56670
|
||||
---------------------------------------------------------------------------------
|
||||
...
|
||||
---------------------------------------------------------------------------------
|
||||
Finished Writing Synthesis Report : Time (s): cpu = 00:02:45 ; elapsed = 00:03:01 . Memory (MB): peak = 1986.879 ; gain = 772.523 ; free physical = 17457 ; free virtual = 56673
|
||||
---------------------------------------------------------------------------------
|
||||
...
|
||||
Writing bitstream ./toplevel.bit...
|
||||
...
|
||||
mmi files generated
|
||||
...
|
||||
********************************************
|
||||
./soc_latest_sw.bit correctly generated
|
||||
********************************************
|
||||
...
|
||||
********************************************
|
||||
./soc_latest_sw.mcs correctly generated
|
||||
********************************************
|
||||
|
||||
INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:00:50 2019...
|
||||
```
|
||||
|
||||
The process should take around 8 minutes on a reasonably fast computer.
|
||||
|
||||
## Programming
|
||||
|
||||
### Direct FPGA RAM programming
|
||||
|
||||
Run `make prog` to program the bit file directly to FPGA RAM.
|
||||
|
||||
You should get output like the following;
|
||||
```
|
||||
...
|
||||
****** Xilinx hw_server v2018.1
|
||||
**** Build date : Apr 4 2018-18:56:09
|
||||
** Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.
|
||||
|
||||
INFO: [Labtoolstcl 44-466] Opening hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA
|
||||
INFO: [Labtools 27-1434] Device xc7a35t (JTAG device index = 0) is programmed with a design that has no supported debug core(s) in it.
|
||||
WARNING: [Labtools 27-3361] The debug hub core was not detected.
|
||||
Resolution:
|
||||
1. Make sure the clock connected to the debug hub (dbg_hub) core is a free running clock and is active.
|
||||
2. Make sure the BSCAN_SWITCH_USER_MASK device property in Vivado Hardware Manager reflects the user scan chain setting in the design and refresh the device. To determine the user scan chain setting in the design, open the implemented design and use 'get_property C_USER_SCAN_CHAIN [get_debug_cores dbg_hub]'.
|
||||
For more details on setting the scan chain property, consult the Vivado Debug and Programming User Guide (UG908).
|
||||
INFO: [Labtools 27-3164] End of startup status: HIGH
|
||||
INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:01:36 2019...
|
||||
```
|
||||
|
||||
After programming the LED4~LED7 shall show some activity.
|
||||
|
||||
### QSPI flash programming
|
||||
|
||||
Run `make flash` to program the bit file to the QSPI flash.
|
||||
|
||||
You should get output like the following;
|
||||
```
|
||||
...
|
||||
****** Xilinx hw_server v2018.1
|
||||
**** Build date : Apr 4 2018-18:56:09
|
||||
** Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.
|
||||
|
||||
|
||||
INFO: [Labtoolstcl 44-466] Opening hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA
|
||||
INFO: [Labtools 27-1434] Device xc7a35t (JTAG device index = 0) is programmed with a design that has no supported debug core(s) in it.
|
||||
...
|
||||
INFO: [Labtools 27-3164] End of startup status: HIGH
|
||||
Mfg ID : 1 Memory Type : 20 Memory Capacity : 18 Device ID 1 : 0 Device ID 2 : 0
|
||||
Performing Erase Operation...
|
||||
Erase Operation successful.
|
||||
Performing Program and Verify Operations...
|
||||
Program/Verify Operation successful.
|
||||
INFO: [Labtoolstcl 44-377] Flash programming completed successfully
|
||||
program_hw_cfgmem: Time (s): cpu = 00:00:00.11 ; elapsed = 00:00:52 . Memory (MB): peak = 1792.711 ; gain = 8.000 ; free physical = 17712 ; free virtual = 56943
|
||||
INFO: [Labtoolstcl 44-464] Closing hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA
|
||||
...
|
||||
INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:06:28 2019...
|
||||
```
|
||||
|
||||
After programming the flash you need to press the "PROG" button on the board. Then after a second or so the "DONE" LED shall be ON and LED4~LED7 shall show some activity.
|
||||
|
||||
|
||||
## Connect
|
||||
|
||||
After programming you should be able to connect to the serial port and have some output.
|
||||
|
||||
On Linux you can do this using a command like `screen /dev/ttyUSB1`. Other good alternatives:
|
||||
|
||||
* moserial (GUI)
|
||||
* picocom (can be launched via the file "picocom_arty")
|
||||
|
||||
Parameters:
|
||||
* port is : /dev/ttyUSB1
|
||||
* flowcontrol : none
|
||||
* baudrate is : 115200
|
||||
* parity is : none
|
||||
* databits are : 8
|
||||
* stopbits are : 1
|
366
scripts/Murax/arty_a7/arty_a7.xdc
Normal file
366
scripts/Murax/arty_a7/arty_a7.xdc
Normal file
|
@ -0,0 +1,366 @@
|
|||
set_property PACKAGE_PIN F4 [get_ports tck]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports tck]
|
||||
|
||||
set_property PACKAGE_PIN D2 [get_ports tms]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports tms]
|
||||
|
||||
set_property PACKAGE_PIN D4 [get_ports tdo]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports tdo]
|
||||
set_property PULLUP true [get_ports tdo]
|
||||
|
||||
set_property PACKAGE_PIN E2 [get_ports tdi]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports tdi]
|
||||
|
||||
set_property PACKAGE_PIN D3 [get_ports trst]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports trst]
|
||||
set_property PULLUP true [get_ports trst]
|
||||
|
||||
|
||||
## serial:0.tx
|
||||
set_property PACKAGE_PIN D10 [get_ports serial_tx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports serial_tx]
|
||||
## serial:0.rx
|
||||
set_property PACKAGE_PIN A9 [get_ports serial_rx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports serial_rx]
|
||||
## clk100:0
|
||||
set_property PACKAGE_PIN E3 [get_ports clk100]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports clk100]
|
||||
## cpu_reset:0
|
||||
set_property PACKAGE_PIN C2 [get_ports cpu_reset]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports cpu_reset]
|
||||
## eth_ref_clk:0
|
||||
#set_property LOC G18 [get_ports eth_ref_clk]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_ref_clk]
|
||||
## user_led:0
|
||||
set_property PACKAGE_PIN H5 [get_ports user_led0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led0]
|
||||
## user_led:1
|
||||
set_property PACKAGE_PIN J5 [get_ports user_led1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led1]
|
||||
## user_led:2
|
||||
set_property PACKAGE_PIN T9 [get_ports user_led2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led2]
|
||||
## user_led:3
|
||||
set_property PACKAGE_PIN T10 [get_ports user_led3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led3]
|
||||
## user_sw:0
|
||||
set_property PACKAGE_PIN A8 [get_ports user_sw0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw0]
|
||||
## user_sw:1
|
||||
set_property PACKAGE_PIN C11 [get_ports user_sw1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw1]
|
||||
## user_sw:2
|
||||
set_property PACKAGE_PIN C10 [get_ports user_sw2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw2]
|
||||
## user_sw:3
|
||||
set_property PACKAGE_PIN A10 [get_ports user_sw3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw3]
|
||||
## user_btn:0
|
||||
set_property PACKAGE_PIN D9 [get_ports user_btn0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn0]
|
||||
## user_btn:1
|
||||
set_property PACKAGE_PIN C9 [get_ports user_btn1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn1]
|
||||
## user_btn:2
|
||||
set_property PACKAGE_PIN B9 [get_ports user_btn2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn2]
|
||||
## user_btn:3
|
||||
set_property PACKAGE_PIN B8 [get_ports user_btn3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn3]
|
||||
## spiflash_1x:0.cs_n
|
||||
#set_property LOC L13 [get_ports spiflash_1x_cs_n]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_cs_n]
|
||||
# ## spiflash_1x:0.mosi
|
||||
#set_property LOC K17 [get_ports spiflash_1x_mosi]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_mosi]
|
||||
# ## spiflash_1x:0.miso
|
||||
#set_property LOC K18 [get_ports spiflash_1x_miso]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_miso]
|
||||
# ## spiflash_1x:0.wp
|
||||
#set_property LOC L14 [get_ports spiflash_1x_wp]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_wp]
|
||||
# ## spiflash_1x:0.hold
|
||||
#set_property LOC M14 [get_ports spiflash_1x_hold]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_hold]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R2 [get_ports ddram_a[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[0]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC M6 [get_ports ddram_a[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[1]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC N4 [get_ports ddram_a[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[2]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T1 [get_ports ddram_a[3]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[3]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[3]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC N6 [get_ports ddram_a[4]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[4]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[4]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R7 [get_ports ddram_a[5]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[5]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[5]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC V6 [get_ports ddram_a[6]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[6]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[6]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC U7 [get_ports ddram_a[7]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[7]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[7]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R8 [get_ports ddram_a[8]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[8]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[8]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC V7 [get_ports ddram_a[9]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[9]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[9]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R6 [get_ports ddram_a[10]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[10]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[10]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC U6 [get_ports ddram_a[11]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[11]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[11]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T6 [get_ports ddram_a[12]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[12]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[12]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T8 [get_ports ddram_a[13]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[13]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[13]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC R1 [get_ports ddram_ba[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[0]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC P4 [get_ports ddram_ba[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[1]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC P2 [get_ports ddram_ba[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[2]]
|
||||
# ## ddram:0.ras_n
|
||||
#set_property LOC P3 [get_ports ddram_ras_n]
|
||||
#set_property SLEW FAST [get_ports ddram_ras_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ras_n]
|
||||
# ## ddram:0.cas_n
|
||||
#set_property LOC M4 [get_ports ddram_cas_n]
|
||||
#set_property SLEW FAST [get_ports ddram_cas_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cas_n]
|
||||
# ## ddram:0.we_n
|
||||
#set_property LOC P5 [get_ports ddram_we_n]
|
||||
#set_property SLEW FAST [get_ports ddram_we_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_we_n]
|
||||
# ## ddram:0.cs_n
|
||||
#set_property LOC U8 [get_ports ddram_cs_n]
|
||||
#set_property SLEW FAST [get_ports ddram_cs_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cs_n]
|
||||
# ## ddram:0.dm
|
||||
#set_property LOC L1 [get_ports ddram_dm[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dm[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[0]]
|
||||
# ## ddram:0.dm
|
||||
#set_property LOC U1 [get_ports ddram_dm[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dm[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[1]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC K5 [get_ports ddram_dq[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[0]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[0]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L3 [get_ports ddram_dq[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[1]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[1]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC K3 [get_ports ddram_dq[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[2]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[2]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L6 [get_ports ddram_dq[3]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[3]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[3]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[3]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M3 [get_ports ddram_dq[4]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[4]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[4]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[4]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M1 [get_ports ddram_dq[5]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[5]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[5]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[5]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L4 [get_ports ddram_dq[6]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[6]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[6]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[6]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M2 [get_ports ddram_dq[7]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[7]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[7]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[7]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V4 [get_ports ddram_dq[8]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[8]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[8]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[8]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC T5 [get_ports ddram_dq[9]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[9]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[9]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[9]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC U4 [get_ports ddram_dq[10]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[10]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[10]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[10]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V5 [get_ports ddram_dq[11]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[11]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[11]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[11]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V1 [get_ports ddram_dq[12]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[12]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[12]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[12]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC T3 [get_ports ddram_dq[13]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[13]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[13]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[13]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC U3 [get_ports ddram_dq[14]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[14]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[14]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[14]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC R3 [get_ports ddram_dq[15]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[15]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[15]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[15]]
|
||||
# ## ddram:0.dqs_p
|
||||
#set_property LOC N2 [get_ports ddram_dqs_p[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_p[0]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[0]]
|
||||
# ## ddram:0.dqs_p
|
||||
#set_property LOC U2 [get_ports ddram_dqs_p[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_p[1]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[1]]
|
||||
# ## ddram:0.dqs_n
|
||||
#set_property LOC N1 [get_ports ddram_dqs_n[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_n[0]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[0]]
|
||||
# ## ddram:0.dqs_n
|
||||
#set_property LOC V2 [get_ports ddram_dqs_n[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_n[1]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[1]]
|
||||
# ## ddram:0.clk_p
|
||||
#set_property LOC U9 [get_ports ddram_clk_p]
|
||||
#set_property SLEW FAST [get_ports ddram_clk_p]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_p]
|
||||
# ## ddram:0.clk_n
|
||||
#set_property LOC V9 [get_ports ddram_clk_n]
|
||||
#set_property SLEW FAST [get_ports ddram_clk_n]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_n]
|
||||
# ## ddram:0.cke
|
||||
#set_property LOC N5 [get_ports ddram_cke]
|
||||
#set_property SLEW FAST [get_ports ddram_cke]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cke]
|
||||
# ## ddram:0.odt
|
||||
#set_property LOC R5 [get_ports ddram_odt]
|
||||
#set_property SLEW FAST [get_ports ddram_odt]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_odt]
|
||||
# ## ddram:0.reset_n
|
||||
#set_property LOC K6 [get_ports ddram_reset_n]
|
||||
#set_property SLEW FAST [get_ports ddram_reset_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_reset_n]
|
||||
# ## eth_clocks:0.tx
|
||||
#set_property LOC H16 [get_ports eth_clocks_tx]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_tx]
|
||||
# ## eth_clocks:0.rx
|
||||
#set_property LOC F15 [get_ports eth_clocks_rx]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_rx]
|
||||
# ## eth:0.rst_n
|
||||
#set_property LOC C16 [get_ports eth_rst_n]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rst_n]
|
||||
# ## eth:0.mdio
|
||||
#set_property LOC K13 [get_ports eth_mdio]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdio]
|
||||
# ## eth:0.mdc
|
||||
#set_property LOC F16 [get_ports eth_mdc]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdc]
|
||||
# ## eth:0.rx_dv
|
||||
#set_property LOC G16 [get_ports eth_rx_dv]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_dv]
|
||||
# ## eth:0.rx_er
|
||||
#set_property LOC C17 [get_ports eth_rx_er]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_er]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC D18 [get_ports eth_rx_data[0]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[0]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC E17 [get_ports eth_rx_data[1]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[1]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC E18 [get_ports eth_rx_data[2]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[2]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC G17 [get_ports eth_rx_data[3]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[3]]
|
||||
# ## eth:0.tx_en
|
||||
#set_property LOC H15 [get_ports eth_tx_en]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_en]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC H14 [get_ports eth_tx_data[0]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[0]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC J14 [get_ports eth_tx_data[1]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[1]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC J13 [get_ports eth_tx_data[2]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[2]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC H17 [get_ports eth_tx_data[3]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[3]]
|
||||
# ## eth:0.col
|
||||
#set_property LOC D17 [get_ports eth_col]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_col]
|
||||
# ## eth:0.crs
|
||||
#set_property LOC G14 [get_ports eth_crs]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_crs]
|
||||
|
||||
set_property INTERNAL_VREF 0.75 [get_iobanks 34]
|
||||
|
||||
|
||||
create_clock -period 10.000 -name clk100 [get_nets clk100]
|
||||
|
||||
#create_clock -name eth_rx_clk -period 40.0 [get_nets eth_rx_clk]
|
||||
|
||||
#create_clock -name eth_tx_clk -period 40.0 [get_nets eth_tx_clk]
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -asynchronous
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous
|
||||
|
||||
|
||||
|
||||
|
||||
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
|
350
scripts/Murax/arty_a7/arty_a7_org.xdc
Normal file
350
scripts/Murax/arty_a7/arty_a7_org.xdc
Normal file
|
@ -0,0 +1,350 @@
|
|||
## serial:0.tx
|
||||
set_property LOC D10 [get_ports serial_tx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports serial_tx]
|
||||
## serial:0.rx
|
||||
set_property LOC A9 [get_ports serial_rx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports serial_rx]
|
||||
## clk100:0
|
||||
set_property LOC E3 [get_ports clk100]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports clk100]
|
||||
## cpu_reset:0
|
||||
set_property LOC C2 [get_ports cpu_reset]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports cpu_reset]
|
||||
## eth_ref_clk:0
|
||||
#set_property LOC G18 [get_ports eth_ref_clk]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_ref_clk]
|
||||
## user_led:0
|
||||
set_property LOC H5 [get_ports user_led0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led0]
|
||||
## user_led:1
|
||||
set_property LOC J5 [get_ports user_led1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led1]
|
||||
## user_led:2
|
||||
set_property LOC T9 [get_ports user_led2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led2]
|
||||
## user_led:3
|
||||
set_property LOC T10 [get_ports user_led3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_led3]
|
||||
## user_sw:0
|
||||
set_property LOC A8 [get_ports user_sw0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw0]
|
||||
## user_sw:1
|
||||
set_property LOC C11 [get_ports user_sw1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw1]
|
||||
## user_sw:2
|
||||
set_property LOC C10 [get_ports user_sw2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw2]
|
||||
## user_sw:3
|
||||
set_property LOC A10 [get_ports user_sw3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_sw3]
|
||||
## user_btn:0
|
||||
set_property LOC D9 [get_ports user_btn0]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn0]
|
||||
## user_btn:1
|
||||
set_property LOC C9 [get_ports user_btn1]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn1]
|
||||
## user_btn:2
|
||||
set_property LOC B9 [get_ports user_btn2]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn2]
|
||||
## user_btn:3
|
||||
set_property LOC B8 [get_ports user_btn3]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports user_btn3]
|
||||
## spiflash_1x:0.cs_n
|
||||
#set_property LOC L13 [get_ports spiflash_1x_cs_n]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_cs_n]
|
||||
# ## spiflash_1x:0.mosi
|
||||
#set_property LOC K17 [get_ports spiflash_1x_mosi]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_mosi]
|
||||
# ## spiflash_1x:0.miso
|
||||
#set_property LOC K18 [get_ports spiflash_1x_miso]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_miso]
|
||||
# ## spiflash_1x:0.wp
|
||||
#set_property LOC L14 [get_ports spiflash_1x_wp]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_wp]
|
||||
# ## spiflash_1x:0.hold
|
||||
#set_property LOC M14 [get_ports spiflash_1x_hold]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_hold]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R2 [get_ports ddram_a[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[0]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC M6 [get_ports ddram_a[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[1]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC N4 [get_ports ddram_a[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[2]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T1 [get_ports ddram_a[3]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[3]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[3]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC N6 [get_ports ddram_a[4]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[4]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[4]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R7 [get_ports ddram_a[5]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[5]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[5]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC V6 [get_ports ddram_a[6]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[6]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[6]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC U7 [get_ports ddram_a[7]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[7]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[7]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R8 [get_ports ddram_a[8]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[8]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[8]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC V7 [get_ports ddram_a[9]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[9]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[9]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC R6 [get_ports ddram_a[10]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[10]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[10]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC U6 [get_ports ddram_a[11]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[11]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[11]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T6 [get_ports ddram_a[12]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[12]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[12]]
|
||||
# ## ddram:0.a
|
||||
#set_property LOC T8 [get_ports ddram_a[13]]
|
||||
#set_property SLEW FAST [get_ports ddram_a[13]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_a[13]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC R1 [get_ports ddram_ba[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[0]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC P4 [get_ports ddram_ba[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[1]]
|
||||
# ## ddram:0.ba
|
||||
#set_property LOC P2 [get_ports ddram_ba[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_ba[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[2]]
|
||||
# ## ddram:0.ras_n
|
||||
#set_property LOC P3 [get_ports ddram_ras_n]
|
||||
#set_property SLEW FAST [get_ports ddram_ras_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_ras_n]
|
||||
# ## ddram:0.cas_n
|
||||
#set_property LOC M4 [get_ports ddram_cas_n]
|
||||
#set_property SLEW FAST [get_ports ddram_cas_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cas_n]
|
||||
# ## ddram:0.we_n
|
||||
#set_property LOC P5 [get_ports ddram_we_n]
|
||||
#set_property SLEW FAST [get_ports ddram_we_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_we_n]
|
||||
# ## ddram:0.cs_n
|
||||
#set_property LOC U8 [get_ports ddram_cs_n]
|
||||
#set_property SLEW FAST [get_ports ddram_cs_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cs_n]
|
||||
# ## ddram:0.dm
|
||||
#set_property LOC L1 [get_ports ddram_dm[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dm[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[0]]
|
||||
# ## ddram:0.dm
|
||||
#set_property LOC U1 [get_ports ddram_dm[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dm[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[1]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC K5 [get_ports ddram_dq[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[0]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[0]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[0]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L3 [get_ports ddram_dq[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[1]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[1]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[1]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC K3 [get_ports ddram_dq[2]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[2]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[2]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[2]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L6 [get_ports ddram_dq[3]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[3]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[3]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[3]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M3 [get_ports ddram_dq[4]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[4]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[4]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[4]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M1 [get_ports ddram_dq[5]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[5]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[5]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[5]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC L4 [get_ports ddram_dq[6]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[6]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[6]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[6]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC M2 [get_ports ddram_dq[7]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[7]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[7]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[7]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V4 [get_ports ddram_dq[8]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[8]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[8]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[8]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC T5 [get_ports ddram_dq[9]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[9]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[9]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[9]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC U4 [get_ports ddram_dq[10]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[10]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[10]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[10]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V5 [get_ports ddram_dq[11]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[11]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[11]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[11]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC V1 [get_ports ddram_dq[12]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[12]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[12]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[12]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC T3 [get_ports ddram_dq[13]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[13]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[13]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[13]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC U3 [get_ports ddram_dq[14]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[14]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[14]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[14]]
|
||||
# ## ddram:0.dq
|
||||
#set_property LOC R3 [get_ports ddram_dq[15]]
|
||||
#set_property SLEW FAST [get_ports ddram_dq[15]]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[15]]
|
||||
#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[15]]
|
||||
# ## ddram:0.dqs_p
|
||||
#set_property LOC N2 [get_ports ddram_dqs_p[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_p[0]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[0]]
|
||||
# ## ddram:0.dqs_p
|
||||
#set_property LOC U2 [get_ports ddram_dqs_p[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_p[1]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[1]]
|
||||
# ## ddram:0.dqs_n
|
||||
#set_property LOC N1 [get_ports ddram_dqs_n[0]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_n[0]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[0]]
|
||||
# ## ddram:0.dqs_n
|
||||
#set_property LOC V2 [get_ports ddram_dqs_n[1]]
|
||||
#set_property SLEW FAST [get_ports ddram_dqs_n[1]]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[1]]
|
||||
# ## ddram:0.clk_p
|
||||
#set_property LOC U9 [get_ports ddram_clk_p]
|
||||
#set_property SLEW FAST [get_ports ddram_clk_p]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_p]
|
||||
# ## ddram:0.clk_n
|
||||
#set_property LOC V9 [get_ports ddram_clk_n]
|
||||
#set_property SLEW FAST [get_ports ddram_clk_n]
|
||||
#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_n]
|
||||
# ## ddram:0.cke
|
||||
#set_property LOC N5 [get_ports ddram_cke]
|
||||
#set_property SLEW FAST [get_ports ddram_cke]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_cke]
|
||||
# ## ddram:0.odt
|
||||
#set_property LOC R5 [get_ports ddram_odt]
|
||||
#set_property SLEW FAST [get_ports ddram_odt]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_odt]
|
||||
# ## ddram:0.reset_n
|
||||
#set_property LOC K6 [get_ports ddram_reset_n]
|
||||
#set_property SLEW FAST [get_ports ddram_reset_n]
|
||||
#set_property IOSTANDARD SSTL15 [get_ports ddram_reset_n]
|
||||
# ## eth_clocks:0.tx
|
||||
#set_property LOC H16 [get_ports eth_clocks_tx]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_tx]
|
||||
# ## eth_clocks:0.rx
|
||||
#set_property LOC F15 [get_ports eth_clocks_rx]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_rx]
|
||||
# ## eth:0.rst_n
|
||||
#set_property LOC C16 [get_ports eth_rst_n]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rst_n]
|
||||
# ## eth:0.mdio
|
||||
#set_property LOC K13 [get_ports eth_mdio]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdio]
|
||||
# ## eth:0.mdc
|
||||
#set_property LOC F16 [get_ports eth_mdc]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdc]
|
||||
# ## eth:0.rx_dv
|
||||
#set_property LOC G16 [get_ports eth_rx_dv]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_dv]
|
||||
# ## eth:0.rx_er
|
||||
#set_property LOC C17 [get_ports eth_rx_er]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_er]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC D18 [get_ports eth_rx_data[0]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[0]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC E17 [get_ports eth_rx_data[1]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[1]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC E18 [get_ports eth_rx_data[2]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[2]]
|
||||
# ## eth:0.rx_data
|
||||
#set_property LOC G17 [get_ports eth_rx_data[3]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[3]]
|
||||
# ## eth:0.tx_en
|
||||
#set_property LOC H15 [get_ports eth_tx_en]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_en]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC H14 [get_ports eth_tx_data[0]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[0]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC J14 [get_ports eth_tx_data[1]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[1]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC J13 [get_ports eth_tx_data[2]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[2]]
|
||||
# ## eth:0.tx_data
|
||||
#set_property LOC H17 [get_ports eth_tx_data[3]]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[3]]
|
||||
# ## eth:0.col
|
||||
#set_property LOC D17 [get_ports eth_col]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_col]
|
||||
# ## eth:0.crs
|
||||
#set_property LOC G14 [get_ports eth_crs]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports eth_crs]
|
||||
|
||||
set_property INTERNAL_VREF 0.750 [get_iobanks 34]
|
||||
|
||||
create_clock -name sys_clk -period 10.0 [get_nets sys_clk]
|
||||
|
||||
create_clock -name clk100 -period 10.0 [get_nets clk100]
|
||||
|
||||
#create_clock -name eth_rx_clk -period 40.0 [get_nets eth_rx_clk]
|
||||
|
||||
#create_clock -name eth_tx_clk -period 40.0 [get_nets eth_tx_clk]
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -asynchronous
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous
|
||||
|
||||
#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous
|
||||
|
||||
set_false_path -quiet -to [get_nets -quiet -filter {mr_ff == TRUE}]
|
||||
|
||||
set_false_path -quiet -to [get_pins -quiet -filter {REF_PIN_NAME == PRE} -of [get_cells -quiet -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]]
|
||||
|
||||
set_max_delay 2 -quiet -from [get_pins -quiet -filter {REF_PIN_NAME == Q} -of [get_cells -quiet -filter {ars_ff1 == TRUE}]] -to [get_pins -quiet -filter {REF_PIN_NAME == D} -of [get_cells -quiet -filter {ars_ff2 == TRUE}]]
|
50
scripts/Murax/arty_a7/make_bit_file.tcl
Normal file
50
scripts/Murax/arty_a7/make_bit_file.tcl
Normal file
|
@ -0,0 +1,50 @@
|
|||
|
||||
# Input files
|
||||
set mmi_file "./soc.mmi"
|
||||
set elf_file "./soc.elf"
|
||||
set source_bit_file "./soc.bit"
|
||||
|
||||
# Output files
|
||||
set output_bit_file "./soc_latest_sw.bit"
|
||||
|
||||
# Enable to turn on debug
|
||||
set updatemem_debug 0
|
||||
|
||||
# Assemble bit file that can be downloaded to device directly
|
||||
# Combine the original bit file, mmi file, and software elf to create the full bitstream
|
||||
|
||||
# Delete target file
|
||||
file delete -force $output_bit_file
|
||||
|
||||
# Determine if the user has built the project and has the target source file
|
||||
# If not, then use the reference bit file shipped with the project
|
||||
if { ![file exists $source_bit_file] } {
|
||||
puts "\n********************************************"
|
||||
puts "INFO - File $source_bit_file doesn't exist as project has not been built"
|
||||
puts " Using $reference_bit_file instead\n"
|
||||
puts "********************************************/n"
|
||||
set source_bit_file $reference_bit_file
|
||||
}
|
||||
|
||||
# Banner message to console as there is no output for a few seconds
|
||||
puts " Running updatemem ..."
|
||||
|
||||
if { $updatemem_debug } {
|
||||
set error [catch {exec updatemem --debug --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result]
|
||||
} else {
|
||||
set error [catch {exec updatemem --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result]
|
||||
}
|
||||
|
||||
# Print the stdout from updatemem
|
||||
puts $result
|
||||
|
||||
# Updatemem returns 0 even when there is an error, so cannot trap on error. Having deleted output file to start, then
|
||||
# detect if it now exists, else exit.
|
||||
if { ![file exists $output_bit_file] } {
|
||||
puts "ERROR - $output_bit_file not made"
|
||||
return -1
|
||||
} else {
|
||||
puts "\n********************************************"
|
||||
puts " $output_bit_file correctly generated"
|
||||
puts "********************************************\n"
|
||||
}
|
6
scripts/Murax/arty_a7/make_mcs_file
Executable file
6
scripts/Murax/arty_a7/make_mcs_file
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
#Create mcs file for QSPI flash
|
||||
|
||||
cd ./build
|
||||
|
||||
vivado -mode batch -source ../make_mcs_file.tcl -notrace
|
31
scripts/Murax/arty_a7/make_mcs_file.tcl
Normal file
31
scripts/Murax/arty_a7/make_mcs_file.tcl
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
# Input file
|
||||
set source_bit_file "./latest.bit"
|
||||
|
||||
# Output file
|
||||
set output_mcs_file "./latest.mcs"
|
||||
|
||||
# Delete target file
|
||||
file delete -force $output_mcs_file
|
||||
|
||||
# Determine if the user has built the project and has the target source file
|
||||
# If not, then use the reference bit file shipped with the project
|
||||
if { ![file exists $source_bit_file] } {
|
||||
puts "\n********************************************"
|
||||
puts "INFO - File $source_bit_file doesn't exist as project has not been built\n"
|
||||
puts "********************************************/n"
|
||||
error
|
||||
}
|
||||
|
||||
# Create MCS file for base board QSPI flash memory
|
||||
write_cfgmem -force -format MCS -size 16 -interface SPIx4 -loadbit " up 0 $source_bit_file" $output_mcs_file
|
||||
|
||||
# Check MCS was correctly made
|
||||
if { ![file exists $output_mcs_file] } {
|
||||
puts "ERROR - $output_bit_file not made"
|
||||
return -1
|
||||
} else {
|
||||
puts "\n********************************************"
|
||||
puts " $output_mcs_file correctly generated"
|
||||
puts "********************************************\n"
|
||||
}
|
4
scripts/Murax/arty_a7/make_mmi_files
Executable file
4
scripts/Murax/arty_a7/make_mmi_files
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd ./build
|
||||
vivado -mode batch -source ../make_mmi_files.tcl -notrace
|
6
scripts/Murax/arty_a7/make_mmi_files.tcl
Normal file
6
scripts/Murax/arty_a7/make_mmi_files.tcl
Normal file
|
@ -0,0 +1,6 @@
|
|||
source [file join [file dirname [file normalize [info script]]] vivado_params.tcl]
|
||||
|
||||
open_project -read_only $outputdir/$projectName
|
||||
open_run impl_1
|
||||
source $base/soc_mmi.tcl
|
||||
puts "mmi files generated"
|
9
scripts/Murax/arty_a7/make_vivado_project
Executable file
9
scripts/Murax/arty_a7/make_vivado_project
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
#cannot rm build because it erase software images that the make file copy there
|
||||
#rm -rf ./build
|
||||
|
||||
mkdir -p ./build
|
||||
|
||||
cd ./build
|
||||
vivado -mode batch -source ../make_vivado_project.tcl -notrace
|
46
scripts/Murax/arty_a7/make_vivado_project.tcl
Normal file
46
scripts/Murax/arty_a7/make_vivado_project.tcl
Normal file
|
@ -0,0 +1,46 @@
|
|||
#Create output directory and clear contents
|
||||
source [file join [file dirname [file normalize [info script]]] vivado_params.tcl]
|
||||
|
||||
file mkdir $outputdir
|
||||
set files [glob -nocomplain "$outputdir/*"]
|
||||
if {[llength $files] != 0} {
|
||||
puts "deleting contents of $outputdir"
|
||||
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents
|
||||
} else {
|
||||
puts "$outputdir is empty"
|
||||
}
|
||||
|
||||
#Create project
|
||||
create_project -part $part $projectName $outputdir
|
||||
|
||||
#add source files to Vivado project
|
||||
#add_files -fileset sim_1 ./path/to/testbench.vhd
|
||||
#add_files [glob ./path/to/sources/*.vhd]
|
||||
#add_files -fileset constrs_1 ./path/to/constraint/constraint.xdc
|
||||
#add_files [glob ./path/to/library/sources/*.vhd]
|
||||
#set_property -library userDefined [glob ./path/to/library/sources/*.vhd]
|
||||
add_files [glob $base/*.v]
|
||||
add_files [glob $topv]
|
||||
add_files -fileset constrs_1 $base/arty_a7.xdc
|
||||
|
||||
#set top level module and update compile order
|
||||
set_property top toplevel [current_fileset]
|
||||
update_compile_order -fileset sources_1
|
||||
#update_compile_order -fileset sim_1
|
||||
|
||||
#launch synthesis
|
||||
launch_runs synth_1
|
||||
wait_on_run synth_1
|
||||
|
||||
#Run implementation and generate bitstream
|
||||
set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
|
||||
launch_runs impl_1 -to_step write_bitstream
|
||||
wait_on_run impl_1
|
||||
puts "Implementation done!"
|
||||
|
||||
#reports generated by default
|
||||
#open_run impl_1
|
||||
#report_timing_summary -check_timing_verbose -report_unconstrained -file report_timing_summary.rpt
|
||||
#report_utilization -hierarchical -file report_utilization.rpt
|
||||
|
||||
#TODO: add checks about timing, DRC, CDC such that the script give clear indication if design is OK or not
|
62
scripts/Murax/arty_a7/makefile
Normal file
62
scripts/Murax/arty_a7/makefile
Normal file
|
@ -0,0 +1,62 @@
|
|||
ROOT=../../..
|
||||
SWBASE=$(ROOT)/src/main/c/murax
|
||||
SOCSW=hello_world
|
||||
SOCMEMSRC=$(SWBASE)/$(SOCSW)/build/$(SOCSW).v
|
||||
SOCMEM=build/soc.mem
|
||||
|
||||
TOP=Murax
|
||||
|
||||
all : build/latest.bit
|
||||
|
||||
../../../$(TOP).v : toplevel.v
|
||||
(cd ../../..; sbt "runMain vexriscv.demo.Murax_arty")
|
||||
|
||||
.PHONY: $(SOCMEMSRC)
|
||||
$(SOCMEMSRC):
|
||||
mkdir -p build
|
||||
make -C $(SWBASE)/$(SOCSW)
|
||||
|
||||
$(SOCMEM) : $(SOCMEMSRC)
|
||||
cp -u $(SOCMEMSRC) $(SOCMEM)
|
||||
|
||||
build/vivado_project/fpga.runs/impl_1/toplevel.bit : toplevel.v arty_a7.xdc ../../../$(TOP).v
|
||||
mkdir -p build
|
||||
./make_vivado_project
|
||||
cp build/vivado_project/fpga.runs/impl_1/toplevel.bit build/latest.bit
|
||||
|
||||
build/soc.mmi: build/vivado_project/fpga.runs/impl_1/toplevel.bit
|
||||
./make_mmi_files
|
||||
|
||||
build/latest_soc_sw.bit : $(SOCMEM) build/soc.mmi
|
||||
rm -f updatemem.jou updatemem.log
|
||||
updatemem -force --meminfo build/soc.mmi --data $(SOCMEM) --bit build/latest.bit --proc dummy --out build/latest_soc_sw.bit
|
||||
cp build/latest_soc_sw.bit build/latest.bit
|
||||
|
||||
build/latest.bit : build/latest_soc_sw.bit
|
||||
|
||||
build/latest.mcs : build/latest.bit
|
||||
./make_mcs_file
|
||||
|
||||
prog : build/latest.bit
|
||||
./write_fpga
|
||||
|
||||
flash : build/latest.mcs
|
||||
./write_flash
|
||||
|
||||
clean-soc-sw:
|
||||
make -C $(SWBASE)/$(SOCSW) clean-all
|
||||
|
||||
soc-sw: clean-soc-sw $(SOCMEM)
|
||||
|
||||
.PHONY: clean
|
||||
clean :
|
||||
rm -rf build
|
||||
mkdir build
|
||||
rm -f updatemem.jou
|
||||
rm -f updatemem.log
|
||||
|
||||
clean-sw: clean-soc-sw
|
||||
|
||||
clean-all : clean clean-sw
|
||||
rm -f ../../../$(TOP).v
|
||||
rm -f ../../../$(TOP).v_*
|
4
scripts/Murax/arty_a7/open_vivado_project
Executable file
4
scripts/Murax/arty_a7/open_vivado_project
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd ./build
|
||||
vivado -mode batch -source ../open_vivado_project.tcl -notrace
|
4
scripts/Murax/arty_a7/open_vivado_project.tcl
Normal file
4
scripts/Murax/arty_a7/open_vivado_project.tcl
Normal file
|
@ -0,0 +1,4 @@
|
|||
source [file join [file dirname [file normalize [info script]]] vivado_params.tcl]
|
||||
|
||||
open_project -read_only $outputdir/$projectName
|
||||
start_gui
|
1
scripts/Murax/arty_a7/picocom_arty
Normal file
1
scripts/Murax/arty_a7/picocom_arty
Normal file
|
@ -0,0 +1 @@
|
|||
picocom --baud 115200 --imap lfcrlf /dev/ttyUSB1
|
151
scripts/Murax/arty_a7/soc_mmi.tcl
Normal file
151
scripts/Murax/arty_a7/soc_mmi.tcl
Normal file
|
@ -0,0 +1,151 @@
|
|||
#script to update the init values of RAM without re-synthesis
|
||||
|
||||
if {![info exists mmi_file]} {
|
||||
# Set MMI output file name
|
||||
set mmi_file "soc.mmi"
|
||||
}
|
||||
if {![info exists part]} {
|
||||
set part "xc7a35ticsg324-1L"
|
||||
}
|
||||
|
||||
# Function to swap bits
|
||||
proc swap_bits { bit } {
|
||||
|
||||
if { $bit > 23 } {return [expr {24 + (31 - $bit)}]}
|
||||
if { $bit > 15 } {return [expr {16 + (23 - $bit)}]}
|
||||
if { $bit > 7 } {return [expr {8 + (15 - $bit)}]}
|
||||
return [expr {7 - $bit}]
|
||||
}
|
||||
|
||||
# If run from batch file, will need to open project, then open the run
|
||||
# open_run impl_1
|
||||
|
||||
# Find all the RAMs, place in a list
|
||||
set rams [get_cells -hier -regexp {.*core/system_ram/.*} -filter {REF_NAME == RAMB36E1 || REF_NAME == RAMB18E1}]
|
||||
|
||||
puts "[llength $rams] RAMs in total"
|
||||
foreach m $rams {puts $m}
|
||||
|
||||
set mems [dict create]
|
||||
foreach m $rams {
|
||||
set numbers [regexp -all -inline -- {[0-9]+} $m]
|
||||
dict set mems $numbers $m
|
||||
}
|
||||
set keys [dict keys $mems]
|
||||
#set keys [lsort -integer $keys]
|
||||
set rams []
|
||||
foreach key $keys {
|
||||
set m [dict get $mems $key]
|
||||
puts "$key -> $m"
|
||||
lappend rams $m
|
||||
}
|
||||
|
||||
puts "after sort:"
|
||||
foreach m $rams {puts $m}
|
||||
puts $rams
|
||||
|
||||
if { [llength $rams] == 0 } {
|
||||
puts "Error - no memories found"
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [expr {[llength $rams] % 4}] != 0 } {
|
||||
puts "Error - Number of memories not divisible by 4"
|
||||
return -1
|
||||
}
|
||||
|
||||
set size_bytes [expr {4096*[llength $rams]}]
|
||||
puts "Instruction memory size $size_bytes"
|
||||
|
||||
# Currently only support memory sizes between 16kB, (one byte per mem), and 128kB, (one bit per mem)
|
||||
if { ($size_bytes < (4*4096)) || ($size_bytes > (32*4096)) } {
|
||||
puts "Error - Memory size of $size_bytes out of range"
|
||||
puts " Script only supports memory sizes between 16kB and 128kB"
|
||||
return -1
|
||||
}
|
||||
|
||||
# Create and open target mmi file
|
||||
set fp [open $mmi_file {WRONLY CREAT TRUNC}]
|
||||
if { $fp == 0 } {
|
||||
puts "Error - Unable to open $mmi_file for writing"
|
||||
return -1
|
||||
}
|
||||
|
||||
# Write the file header
|
||||
puts $fp "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
puts $fp "<MemInfo Version=\"1\" Minor=\"15\">"
|
||||
puts $fp " <Processor Endianness=\"ignored\" InstPath=\"dummy\">"
|
||||
puts $fp " <AddressSpace Name=\"soc_side\" Begin=\"[expr {0x80000000}]\" End=\"[expr {0x80000000 + $size_bytes-1}]\">"
|
||||
puts $fp " <BusBlock>"
|
||||
|
||||
# Calculate the expected number of bits per memory
|
||||
set mem_bits [expr {32/[llength $rams]}]
|
||||
|
||||
puts "mem_bits = $mem_bits"
|
||||
|
||||
set mem_info [dict create]
|
||||
|
||||
set i 0
|
||||
foreach ram $rams {
|
||||
# Get the RAM location
|
||||
set loc_val [get_property LOC [get_cells $ram]]
|
||||
regexp {(RAMB.+_)([0-9XY]+)} $loc_val full ram_name loc_xy
|
||||
|
||||
set memi [dict create ram $ram loc $loc_xy]
|
||||
|
||||
set numbers [regexp -all -inline -- {[0-9]+} $ram]
|
||||
if { [llength $numbers] == 2 } {
|
||||
dict lappend mem_info [lindex $numbers 0] $memi
|
||||
} else {
|
||||
dict lappend mem_info [expr $i/4] $memi
|
||||
}
|
||||
incr i
|
||||
}
|
||||
|
||||
set sorted_mem_info [dict create]
|
||||
foreach {idx mems} $mem_info {
|
||||
foreach mem [lreverse $mems] {
|
||||
dict lappend sorted_mem_info $idx $mem
|
||||
}
|
||||
}
|
||||
foreach mems $sorted_mem_info {
|
||||
foreach mem $mems {
|
||||
puts $mem
|
||||
}
|
||||
}
|
||||
|
||||
set lsb 0
|
||||
set memlen [ expr 4096*8 / $mem_bits ]
|
||||
foreach {idx mems} $sorted_mem_info {
|
||||
puts "idx=$idx"
|
||||
foreach mem $mems {
|
||||
puts "mem=$mem"
|
||||
set ram [dict get $mem ram]
|
||||
set loc [dict get $mem loc]
|
||||
set msb [expr $lsb+$mem_bits-1]
|
||||
set addr_start 0
|
||||
set addr_end [expr $memlen-1]
|
||||
puts "ram=$ram loc=$loc lsb=$lsb msb=$msb addr_start=$addr_start addr_end=$addr_end"
|
||||
puts $fp " <!-- $ram -->"
|
||||
puts $fp " <BitLane MemType=\"RAMB36\" Placement=\"$loc\">"
|
||||
puts $fp " <DataWidth MSB=\"$msb\" LSB=\"$lsb\"/>"
|
||||
puts $fp " <!--not used!--><AddressRange Begin=\"$addr_start\" End=\"$addr_end\"/>"
|
||||
puts $fp " <Parity ON=\"false\" NumBits=\"0\"/>"
|
||||
puts $fp " </BitLane>"
|
||||
|
||||
set lsb [expr ($msb+1)%32]
|
||||
}
|
||||
}
|
||||
|
||||
puts $fp " </BusBlock>"
|
||||
puts $fp " </AddressSpace>"
|
||||
puts $fp " </Processor>"
|
||||
puts $fp " <Config>"
|
||||
puts $fp " <Option Name=\"Part\" Val=\"$part\"/>"
|
||||
puts $fp " </Config>"
|
||||
puts $fp " <DRC>"
|
||||
puts $fp " <Rule Name=\"RDADDRCHANGE\" Val=\"false\"/>"
|
||||
puts $fp " </DRC>"
|
||||
puts $fp "</MemInfo>"
|
||||
|
||||
close $fp
|
66
scripts/Murax/arty_a7/toplevel.v
Normal file
66
scripts/Murax/arty_a7/toplevel.v
Normal file
|
@ -0,0 +1,66 @@
|
|||
`timescale 1ns / 1ps
|
||||
|
||||
module toplevel(
|
||||
input wire clk100,
|
||||
input wire cpu_reset,//active low
|
||||
|
||||
input wire tck,
|
||||
input wire tms,
|
||||
input wire tdi,
|
||||
input wire trst,//ignored
|
||||
output reg tdo,
|
||||
|
||||
input wire serial_rx,
|
||||
output wire serial_tx,
|
||||
|
||||
input wire user_sw0,
|
||||
input wire user_sw1,
|
||||
input wire user_sw2,
|
||||
input wire user_sw3,
|
||||
|
||||
input wire user_btn0,
|
||||
input wire user_btn1,
|
||||
input wire user_btn2,
|
||||
input wire user_btn3,
|
||||
|
||||
output wire user_led0,
|
||||
output wire user_led1,
|
||||
output wire user_led2,
|
||||
output wire user_led3
|
||||
);
|
||||
|
||||
wire [31:0] io_gpioA_read;
|
||||
wire [31:0] io_gpioA_write;
|
||||
wire [31:0] io_gpioA_writeEnable;
|
||||
|
||||
wire io_asyncReset = ~cpu_reset;
|
||||
|
||||
assign {user_led3,user_led2,user_led1,user_led0} = io_gpioA_write[3 : 0];
|
||||
assign io_gpioA_read[3:0] = {user_sw3,user_sw2,user_sw1,user_sw0};
|
||||
assign io_gpioA_read[7:4] = {user_btn3,user_btn2,user_btn1,user_btn0};
|
||||
assign io_gpioA_read[11:8] = {tck,tms,tdi,trst};
|
||||
|
||||
reg tesic_tck,tesic_tms,tesic_tdi;
|
||||
wire tesic_tdo;
|
||||
reg soc_tck,soc_tms,soc_tdi;
|
||||
wire soc_tdo;
|
||||
|
||||
always @(*) begin
|
||||
{soc_tck, soc_tms, soc_tdi } = {tck,tms,tdi};
|
||||
tdo = soc_tdo;
|
||||
end
|
||||
|
||||
Murax core (
|
||||
.io_asyncReset(io_asyncReset),
|
||||
.io_mainClk (clk100 ),
|
||||
.io_jtag_tck(soc_tck),
|
||||
.io_jtag_tdi(soc_tdi),
|
||||
.io_jtag_tdo(soc_tdo),
|
||||
.io_jtag_tms(soc_tms),
|
||||
.io_gpioA_read (io_gpioA_read),
|
||||
.io_gpioA_write (io_gpioA_write),
|
||||
.io_gpioA_writeEnable(io_gpioA_writeEnable),
|
||||
.io_uart_txd(serial_tx),
|
||||
.io_uart_rxd(serial_rx)
|
||||
);
|
||||
endmodule
|
5
scripts/Murax/arty_a7/vivado_params.tcl
Normal file
5
scripts/Murax/arty_a7/vivado_params.tcl
Normal file
|
@ -0,0 +1,5 @@
|
|||
set outputdir ./vivado_project
|
||||
set part "xc7a35ticsg324-1L"
|
||||
set base ".."
|
||||
set projectName "fpga"
|
||||
set topv "$base/../../../Murax.v"
|
3
scripts/Murax/arty_a7/write_flash
Executable file
3
scripts/Murax/arty_a7/write_flash
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
cd ./build
|
||||
vivado -mode batch -source ../write_flash.tcl -notrace
|
26
scripts/Murax/arty_a7/write_flash.tcl
Normal file
26
scripts/Murax/arty_a7/write_flash.tcl
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
open_hw
|
||||
connect_hw_server
|
||||
open_hw_target
|
||||
current_hw_device [get_hw_devices xc7a35t_0]
|
||||
refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0]
|
||||
|
||||
create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {s25fl128sxxxxxx0-spi-x1_x2_x4}] 0]
|
||||
set_property PROBES.FILE {} [get_hw_devices xc7a35t_0]
|
||||
set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0]
|
||||
refresh_hw_device [lindex [get_hw_devices xc7a35t_0] 0]
|
||||
set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.FILES [list "latest.mcs" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.PRM_FILE {} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
|
||||
if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices xc7a35t_0] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]]]] } { create_hw_bitstream -hw_device [lindex [get_hw_devices xc7a35t_0] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices xc7a35t_0] 0]]; program_hw_devices [lindex [get_hw_devices xc7a35t_0] 0]; };
|
||||
program_hw_cfgmem -hw_cfgmem [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]
|
||||
|
||||
close_hw_target
|
||||
close_hw
|
3
scripts/Murax/arty_a7/write_fpga
Executable file
3
scripts/Murax/arty_a7/write_fpga
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
cd ./build
|
||||
vivado -mode batch -source ../write_fpga.tcl -notrace
|
10
scripts/Murax/arty_a7/write_fpga.tcl
Normal file
10
scripts/Murax/arty_a7/write_fpga.tcl
Normal file
|
@ -0,0 +1,10 @@
|
|||
open_hw
|
||||
connect_hw_server
|
||||
open_hw_target
|
||||
current_hw_device [get_hw_devices xc7a35t_0]
|
||||
refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0]
|
||||
set_property PROBES.FILE {} [get_hw_devices xc7a35t_0]
|
||||
set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0]
|
||||
set_property PROGRAM.FILE {latest.bit} [get_hw_devices xc7a35t_0]
|
||||
program_hw_devices [get_hw_devices xc7a35t_0]
|
||||
disconnect_hw_server
|
|
@ -3,10 +3,10 @@
|
|||
VERILOG = ../../../Murax.v toplevel.v
|
||||
|
||||
generate :
|
||||
(cd ../../..; sbt "run-main vexriscv.demo.MuraxWithRamInit")
|
||||
(cd ../../..; sbt "runMain vexriscv.demo.MuraxWithRamInit")
|
||||
|
||||
../../../Murax.v :
|
||||
(cd ../../..; sbt "run-main vexriscv.demo.MuraxWithRamInit")
|
||||
(cd ../../..; sbt "runMain vexriscv.demo.MuraxWithRamInit")
|
||||
|
||||
../../../Murax.v*.bin:
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ This example is for the
|
|||
[Lattice iCE40HX-8K Breakout Board](http://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx).
|
||||
|
||||
An image of this board is shown below;
|
||||
![img/iCE40HX8K-breakout-revA.png]
|
||||
|
||||

|
||||
|
||||
This board can be purchased for ~$USD 49 directly from Lattice and is supported
|
||||
by the IceStorm
|
||||
|
@ -20,7 +21,8 @@ mode. This requires removing jumper `J7` and putting the pair of jumpers on
|
|||
This is shown in **Figure 5** of the
|
||||
[iCE40HX-8K Breakout Board User Guide](http://www.latticesemi.com/view_document?document_id=50373).
|
||||
which is also reproduced below;
|
||||
![img/cram-programming-config.png]
|
||||
|
||||

|
||||
|
||||
Once your board is ready, you should follow the setup instructions at the
|
||||
[top level](../../../README.md).
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
|
||||
VBASE = ../../..
|
||||
VNAME = Murax_iCE40_hx8k_breakout_board_xip
|
||||
VERILOG = ${VBASE}/${VNAME}.v
|
||||
|
||||
VERILOG = ../../../Murax_iCE40_hx8k_breakout_board_xip.v
|
||||
all: prog
|
||||
|
||||
generate :
|
||||
#(cd ../../..; sbt "run-main vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip")
|
||||
${VERILOG} :
|
||||
(cd ${VBASE}; sbt "runMain vexriscv.demo.${VNAME}")
|
||||
|
||||
../../../Murax_iCE40_hx8k_breakout_board_xip.v :
|
||||
#(cd ../../..; sbt "run-main vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip")
|
||||
generate : ${VERILOG}
|
||||
|
||||
../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin:
|
||||
${VERILOG}*.bin:
|
||||
|
||||
bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin
|
||||
bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ${VERILOG}*.bin
|
||||
mkdir -p bin
|
||||
rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin
|
||||
cp ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin . | true
|
||||
cp ${VERILOG}*.bin . | true
|
||||
yosys -v3 -p "synth_ice40 -top Murax_iCE40_hx8k_breakout_board_xip -blif bin/Murax_iCE40_hx8k_breakout_board_xip.blif" ${VERILOG}
|
||||
|
||||
bin/Murax_iCE40_hx8k_breakout_board_xip.asc : Murax_iCE40_hx8k_breakout_board_xip.pcf bin/Murax_iCE40_hx8k_breakout_board_xip.blif
|
||||
|
@ -28,11 +30,15 @@ time: bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
|||
icetime -tmd hx8k bin/Murax_iCE40_hx8k_breakout_board_xip.asc
|
||||
|
||||
prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
||||
lsusb -d 0403:6010
|
||||
iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
||||
|
||||
sudo-prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
||||
sudo lsusb -d 0403:6010
|
||||
sudo iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
||||
|
||||
clean :
|
||||
rm -rf bin
|
||||
rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin
|
||||
rm -f ${VERILOG}*.bin
|
||||
rm -f ${VERILOG}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
## iCE40-hx8k breakout board
|
||||
|
||||
set_io io_J3 J3
|
||||
set_io io_H16 H16
|
||||
set_io io_G15 G15
|
||||
set_io io_G16 G16
|
||||
set_io io_F15 F15
|
||||
set_io io_B12 B12
|
||||
set_io io_B10 B10
|
||||
set_io io_mainClk J3
|
||||
set_io io_jtag_tck H16
|
||||
set_io io_jtag_tdi G15
|
||||
set_io io_jtag_tdo G16
|
||||
set_io io_jtag_tms F15
|
||||
set_io io_uart_txd B12
|
||||
set_io io_uart_rxd B10
|
||||
set_io io_led[0] B5
|
||||
set_io io_led[1] B4
|
||||
set_io io_led[2] A2
|
||||
|
@ -17,7 +17,7 @@ set_io io_led[6] B3
|
|||
set_io io_led[7] C3
|
||||
|
||||
#XIP
|
||||
set_io io_P12 P12
|
||||
set_io io_P11 P11
|
||||
set_io io_R11 R11
|
||||
set_io io_R12 R12
|
||||
set_io io_miso P12
|
||||
set_io io_mosi P11
|
||||
set_io io_sclk R11
|
||||
set_io io_spis R12
|
||||
|
|
|
@ -2,12 +2,17 @@ This example is for the
|
|||
[Lattice iCE40HX-8K Breakout Board](http://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx).
|
||||
|
||||
An image of this board is shown below;
|
||||
![img/iCE40HX8K-breakout-revA.png]
|
||||
|
||||

|
||||
|
||||
This board can be purchased for ~$USD 49 directly from Lattice and is supported
|
||||
by the IceStorm
|
||||
[`iceprog`](https://github.com/cliffordwolf/icestorm/tree/master/iceprog) tool.
|
||||
|
||||
# Bootloader operations
|
||||
|
||||
A bootloader is implemented in a ROM within the FPGA bitfile. It configure the SPI and attempt to read the first word in 'XIP' area of the flash (0xE0040000 in CPU address space, 0x40000 in flash). If this first word is not 0xFFFFFFFF and the same value is read 3 times,
|
||||
then the bootloader jump at 0xE0040000.
|
||||
|
||||
# Using the example
|
||||
|
||||
|
@ -20,7 +25,8 @@ mode. This requires removing jumper `J7` and putting the pair of jumpers on
|
|||
This is shown in **Figure 5** of the
|
||||
[iCE40HX-8K Breakout Board User Guide](http://www.latticesemi.com/view_document?document_id=50373).
|
||||
which is also reproduced below;
|
||||
![img/cram-programming-config.png]
|
||||
|
||||

|
||||
|
||||
Once your board is ready, you should follow the setup instructions at the
|
||||
[top level](../../../README.md).
|
||||
|
@ -57,12 +63,29 @@ The process should take around 30 seconds on a reasonable fast computer.
|
|||
|
||||
## Programming
|
||||
|
||||
Make sure the FPGA board is the only USB peripheral with ID 0403:6010
|
||||
|
||||
For example, this is bad:
|
||||
```
|
||||
user@lafite:~$ lsusb -d 0403:6010
|
||||
Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
|
||||
Bus 001 Device 090: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
|
||||
```
|
||||
This is good:
|
||||
```
|
||||
user@lafite:~$ lsusb -d 0403:6010
|
||||
Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
|
||||
```
|
||||
|
||||
|
||||
After building you should be able to run `make prog`. You may need to run `make
|
||||
sudo-prog` if root is needed to access your USB devices.
|
||||
|
||||
You should get output like the following;
|
||||
```
|
||||
iceprog -S bin/toplevel.bin
|
||||
lsusb -d 0403:6010
|
||||
Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
|
||||
iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin
|
||||
init..
|
||||
cdone: high
|
||||
reset..
|
||||
|
@ -72,13 +95,113 @@ cdone: high
|
|||
Bye.
|
||||
```
|
||||
|
||||
After programming the LEDs at the top of the board should start flashing in an
|
||||
interesting pattern.
|
||||
WARNING: having this output does NOT guarantee you actually programmed anything in the FPGA!
|
||||
|
||||
## Connect
|
||||
After programming nothing visual will happen, except the LEDs being off.
|
||||
The bootloader is waiting for a valid content in the flash (see Bootloader operations).
|
||||
|
||||
After programming you should be able to connect to the serial port and have the
|
||||
output echoed back to you.
|
||||
## Programming flash image
|
||||
|
||||
On Linux you can do this using a command like `screen /dev/ttyUSB1`. Then as
|
||||
you type you should get back the same characters.
|
||||
### Connect JTAG
|
||||
|
||||
We will use vexrisc JTAG to program the flash, so you need openocd and a
|
||||
suitable JTAG dongle.
|
||||
|
||||
Pin-out:
|
||||
```
|
||||
TCK: H16 aka J2.25
|
||||
TDO: G16 aka J2.26
|
||||
TDI: G15 aka J2.27
|
||||
TMS: F15 aka J2.28
|
||||
```
|
||||
In addition you need to connect the ground and VTarget aka VIO: J2.2 on the
|
||||
board.
|
||||
|
||||
### Start GDB server / OpenOCD
|
||||
Make sure to use https://github.com/SpinalHDL/openocd_riscv
|
||||
Make sure to select the configuration file which match your JTAG dongle.
|
||||
|
||||
An example with the dongle "ft2232h_breakout":
|
||||
```
|
||||
src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg
|
||||
```
|
||||
|
||||
You should get an output like below:
|
||||
```
|
||||
Open On-Chip Debugger 0.10.0+dev-01214-g0ace94f (2019-10-02-18:23)
|
||||
Licensed under GNU GPL v2
|
||||
For bug reports, read
|
||||
http://openocd.org/doc/doxygen/bugs.html
|
||||
../VexRiscv/cpu0.yaml
|
||||
adapter speed: 100 kHz
|
||||
adapter_nsrst_delay: 260
|
||||
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
|
||||
jtag_ntrst_delay: 250
|
||||
Info : set servers polling period to 50ms
|
||||
Error: libusb_get_string_descriptor_ascii() failed with LIBUSB_ERROR_INVALID_PARAM
|
||||
Info : clock speed 100 kHz
|
||||
Info : JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
|
||||
Info : Listening on port 3333 for gdb connections
|
||||
requesting target halt and executing a soft reset
|
||||
Info : Listening on port 6666 for tcl connections
|
||||
Info : Listening on port 4444 for telnet connections
|
||||
```
|
||||
|
||||
### Loading the flash with telnet
|
||||
|
||||
First we connect and stop execution on the device:
|
||||
```
|
||||
user@lafite:~/Downloads/vexrisc_full/VexRiscv/src/main/c/murax/xipBootloader$ telnet 127.0.0.1 4444
|
||||
Trying 127.0.0.1...
|
||||
Connected to 127.0.0.1.
|
||||
Escape character is '^]'.
|
||||
Open On-Chip Debugger
|
||||
> reset
|
||||
JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
|
||||
>
|
||||
```
|
||||
|
||||
Now we can safely connect the J7 jumper on the board to be able to access the flash.
|
||||
After that, we can load the program in flash:
|
||||
```
|
||||
> flash erase_sector 0 4 4
|
||||
erased sectors 4 through 4 on flash bank 0 in 0.872235s
|
||||
> flash write_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000
|
||||
wrote 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin to flash bank 0 at offset 0x00040000 in 0.285539s (0.164 KiB/s)
|
||||
> flash verify_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000
|
||||
read 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin and flash bank 0 at offset 0x00040000 in 0.192036s (0.244 KiB/s)
|
||||
contents match
|
||||
> reset
|
||||
JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
|
||||
> resume
|
||||
> exit
|
||||
Connection closed by foreign host.
|
||||
```
|
||||
|
||||
From now the device runs the code from flash, LEDs shall display a dot moving from D9 to D2.
|
||||
|
||||
### Loading flash using GDB / eclipse
|
||||
```
|
||||
src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg
|
||||
```
|
||||
- Make sure J7 is connected.
|
||||
- Connect to GDB / eclipse as usual.
|
||||
|
||||
From there code loading, step, break points works as usual (including software break points in flash).
|
||||
|
||||
## Update hardware/bootloader
|
||||
|
||||
- Stop any OpenOCD connection
|
||||
- Remove J7, then:
|
||||
```
|
||||
make clean prog
|
||||
```
|
||||
- Remember to check a single FTDI device is listed in the output. If not:
|
||||
- Disconnect the other devices
|
||||
```
|
||||
make prog
|
||||
```
|
||||
- Connect J7, flash software shall start executing.
|
||||
|
||||
## Flash software
|
||||
Refer to "Loading the flash with telnet" or "Loading flash using GDB / eclipse".
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
VERILOG = ../../../Murax.v toplevel.v toplevel_pll.v
|
||||
|
||||
generate :
|
||||
(cd ../../..; sbt "run-main vexriscv.demo.MuraxWithRamInit")
|
||||
(cd ../../..; sbt "runMain vexriscv.demo.MuraxWithRamInit")
|
||||
|
||||
../../../Murax.v :
|
||||
(cd ../../..; sbt "run-main vexriscv.demo.MuraxWithRamInit")
|
||||
(cd ../../..; sbt "runMain vexriscv.demo.MuraxWithRamInit")
|
||||
|
||||
../../../Murax.v*.bin:
|
||||
|
||||
|
|
3
scripts/regression/.gitignore
vendored
Normal file
3
scripts/regression/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
verilator*
|
||||
verilator
|
||||
!verilator.mk
|
7
scripts/regression/makefile
Normal file
7
scripts/regression/makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
.ONESHELL:
|
||||
|
||||
include verilator.mk
|
||||
include regression.mk
|
||||
|
||||
|
||||
|
48
scripts/regression/regression.mk
Normal file
48
scripts/regression/regression.mk
Normal file
|
@ -0,0 +1,48 @@
|
|||
.ONESHELL:
|
||||
|
||||
|
||||
regression_random:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=4
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=4
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
regression_random_linux:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=2
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=1.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_SECURE_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=2
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
|
||||
regression_random_machine_os:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=10
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE=1.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_SECURE_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=2
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
regression_random_baremetal:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=30
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_SECURE_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=no
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
|
||||
regression_dhrystone:
|
||||
cd ../..
|
||||
sbt "testOnly vexriscv.DhrystoneBench"
|
20
scripts/regression/verilator.mk
Normal file
20
scripts/regression/verilator.mk
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
.ONESHELL:
|
||||
|
||||
verilator/configure:
|
||||
rm -rf verilator*
|
||||
wget https://www.veripool.org/ftp/verilator-4.034.tgz
|
||||
tar xvzf verilator*.t*gz
|
||||
mv verilator-4.034 verilator
|
||||
|
||||
verilator/Makefile: verilator/configure
|
||||
cd verilator
|
||||
./configure
|
||||
|
||||
verilator/bin/verilator_bin: verilator/Makefile
|
||||
cd verilator
|
||||
make -j$(shell nproc)
|
||||
rm -rf src/obj_dbg
|
||||
rm -rf src/obj_opt
|
||||
|
||||
verilator_binary: verilator/bin/verilator_bin
|
151
src/main/c/common/ram.ld
Executable file
151
src/main/c/common/ram.ld
Executable file
|
@ -0,0 +1,151 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram : ORIGIN = DEFINED(__ram_origin) ? __ram_origin : 0x80000000, LENGTH = 64k
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}> ram
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.note.gnu.build-id)
|
||||
} > ram
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} > ram
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} > ram
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} > ram
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} > ram
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} > ram
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} > ram
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} > ram
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
.bss :
|
||||
{
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
|
||||
.stack :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} > ram
|
||||
}
|
16
src/main/c/common/riscv64-unknown-elf.mk
Normal file
16
src/main/c/common/riscv64-unknown-elf.mk
Normal file
|
@ -0,0 +1,16 @@
|
|||
RISCV_BIN ?= riscv64-unknown-elf-
|
||||
RISCV_CC=${RISCV_BIN}gcc
|
||||
RISCV_OBJCOPY=${RISCV_BIN}objcopy
|
||||
RISCV_OBJDUMP=${RISCV_BIN}objdump
|
||||
|
||||
MARCH := rv32i
|
||||
ifeq ($(MULDIV),yes)
|
||||
MARCH := $(MARCH)M
|
||||
endif
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
MARCH := $(MARCH)AC
|
||||
endif
|
||||
|
||||
CFLAGS += -march=$(MARCH) -mabi=ilp32 -DUSE_GP
|
||||
LDFLAGS += -march=$(MARCH) -mabi=ilp32
|
||||
|
74
src/main/c/common/standalone.mk
Normal file
74
src/main/c/common/standalone.mk
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
|
||||
LDFLAGS += -lc
|
||||
|
||||
CFLAGS += -I${STANDALONE}/include
|
||||
|
||||
|
||||
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CFLAGS += -g3 -Og
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),no)
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
|
||||
LDFLAGS += -nostdlib -lgcc -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
|
||||
|
||||
|
||||
|
||||
OBJDIR ?= build
|
||||
OBJS := $(SRCS)
|
||||
OBJS := $(OBJS:.c=.o)
|
||||
OBJS := $(OBJS:.cpp=.o)
|
||||
OBJS := $(OBJS:.S=.o)
|
||||
OBJS := $(OBJS:..=miaou)
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
|
||||
|
||||
|
||||
|
||||
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).bin
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
|
||||
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
%.hex: %.elf
|
||||
$(RISCV_OBJCOPY) -O ihex $^ $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(RISCV_OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.v: %.elf
|
||||
$(RISCV_OBJCOPY) -O verilog $^ $@
|
||||
|
||||
%.asm: %.elf
|
||||
$(RISCV_OBJDUMP) -S -d $^ > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.S
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).elf
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).hex
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).map
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).v
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).bin
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).asm
|
||||
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
|
||||
|
||||
.SECONDARY: $(OBJS)
|
6
src/main/c/emulator/.gitignore
vendored
Normal file
6
src/main/c/emulator/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
||||
*.hex
|
||||
!*.bin
|
620
src/main/c/emulator/build/emulator.asm
Normal file
620
src/main/c/emulator/build/emulator.asm
Normal file
|
@ -0,0 +1,620 @@
|
|||
|
||||
build/emulator.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .init:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00001117 auipc sp,0x1
|
||||
80000004: 18810113 addi sp,sp,392 # 80001188 <_sp>
|
||||
80000008: 00001517 auipc a0,0x1
|
||||
8000000c: 8dc50513 addi a0,a0,-1828 # 800008e4 <__init_array_end>
|
||||
80000010: 00001597 auipc a1,0x1
|
||||
80000014: 8d458593 addi a1,a1,-1836 # 800008e4 <__init_array_end>
|
||||
80000018: 00001617 auipc a2,0x1
|
||||
8000001c: 97060613 addi a2,a2,-1680 # 80000988 <__bss_start>
|
||||
80000020: 00c5fc63 bgeu a1,a2,80000038 <_start+0x38>
|
||||
80000024: 00052283 lw t0,0(a0)
|
||||
80000028: 0055a023 sw t0,0(a1)
|
||||
8000002c: 00450513 addi a0,a0,4
|
||||
80000030: 00458593 addi a1,a1,4
|
||||
80000034: fec5e8e3 bltu a1,a2,80000024 <_start+0x24>
|
||||
80000038: 00001517 auipc a0,0x1
|
||||
8000003c: 95050513 addi a0,a0,-1712 # 80000988 <__bss_start>
|
||||
80000040: 00001597 auipc a1,0x1
|
||||
80000044: 94858593 addi a1,a1,-1720 # 80000988 <__bss_start>
|
||||
80000048: 00b57863 bgeu a0,a1,80000058 <_start+0x58>
|
||||
8000004c: 00052023 sw zero,0(a0)
|
||||
80000050: 00450513 addi a0,a0,4
|
||||
80000054: feb56ce3 bltu a0,a1,8000004c <_start+0x4c>
|
||||
80000058: 7e4000ef jal ra,8000083c <__libc_init_array>
|
||||
8000005c: 178000ef jal ra,800001d4 <init>
|
||||
80000060: 00000097 auipc ra,0x0
|
||||
80000064: 01408093 addi ra,ra,20 # 80000074 <done>
|
||||
80000068: 00000513 li a0,0
|
||||
8000006c: c30005b7 lui a1,0xc3000
|
||||
80000070: 30200073 mret
|
||||
|
||||
80000074 <done>:
|
||||
80000074: 0000006f j 80000074 <done>
|
||||
|
||||
80000078 <_init>:
|
||||
80000078: 00008067 ret
|
||||
|
||||
8000007c <trapEntry>:
|
||||
8000007c: 34011173 csrrw sp,mscratch,sp
|
||||
80000080: 00112223 sw ra,4(sp)
|
||||
80000084: 00312623 sw gp,12(sp)
|
||||
80000088: 00412823 sw tp,16(sp)
|
||||
8000008c: 00512a23 sw t0,20(sp)
|
||||
80000090: 00612c23 sw t1,24(sp)
|
||||
80000094: 00712e23 sw t2,28(sp)
|
||||
80000098: 02812023 sw s0,32(sp)
|
||||
8000009c: 02912223 sw s1,36(sp)
|
||||
800000a0: 02a12423 sw a0,40(sp)
|
||||
800000a4: 02b12623 sw a1,44(sp)
|
||||
800000a8: 02c12823 sw a2,48(sp)
|
||||
800000ac: 02d12a23 sw a3,52(sp)
|
||||
800000b0: 02e12c23 sw a4,56(sp)
|
||||
800000b4: 02f12e23 sw a5,60(sp)
|
||||
800000b8: 05012023 sw a6,64(sp)
|
||||
800000bc: 05112223 sw a7,68(sp)
|
||||
800000c0: 05212423 sw s2,72(sp)
|
||||
800000c4: 05312623 sw s3,76(sp)
|
||||
800000c8: 05412823 sw s4,80(sp)
|
||||
800000cc: 05512a23 sw s5,84(sp)
|
||||
800000d0: 05612c23 sw s6,88(sp)
|
||||
800000d4: 05712e23 sw s7,92(sp)
|
||||
800000d8: 07812023 sw s8,96(sp)
|
||||
800000dc: 07912223 sw s9,100(sp)
|
||||
800000e0: 07a12423 sw s10,104(sp)
|
||||
800000e4: 07b12623 sw s11,108(sp)
|
||||
800000e8: 07c12823 sw t3,112(sp)
|
||||
800000ec: 07d12a23 sw t4,116(sp)
|
||||
800000f0: 07e12c23 sw t5,120(sp)
|
||||
800000f4: 07f12e23 sw t6,124(sp)
|
||||
800000f8: 2c4000ef jal ra,800003bc <trap>
|
||||
800000fc: 00412083 lw ra,4(sp)
|
||||
80000100: 00c12183 lw gp,12(sp)
|
||||
80000104: 01012203 lw tp,16(sp)
|
||||
80000108: 01412283 lw t0,20(sp)
|
||||
8000010c: 01812303 lw t1,24(sp)
|
||||
80000110: 01c12383 lw t2,28(sp)
|
||||
80000114: 02012403 lw s0,32(sp)
|
||||
80000118: 02412483 lw s1,36(sp)
|
||||
8000011c: 02812503 lw a0,40(sp)
|
||||
80000120: 02c12583 lw a1,44(sp)
|
||||
80000124: 03012603 lw a2,48(sp)
|
||||
80000128: 03412683 lw a3,52(sp)
|
||||
8000012c: 03812703 lw a4,56(sp)
|
||||
80000130: 03c12783 lw a5,60(sp)
|
||||
80000134: 04012803 lw a6,64(sp)
|
||||
80000138: 04412883 lw a7,68(sp)
|
||||
8000013c: 04812903 lw s2,72(sp)
|
||||
80000140: 04c12983 lw s3,76(sp)
|
||||
80000144: 05012a03 lw s4,80(sp)
|
||||
80000148: 05412a83 lw s5,84(sp)
|
||||
8000014c: 05812b03 lw s6,88(sp)
|
||||
80000150: 05c12b83 lw s7,92(sp)
|
||||
80000154: 06012c03 lw s8,96(sp)
|
||||
80000158: 06412c83 lw s9,100(sp)
|
||||
8000015c: 06812d03 lw s10,104(sp)
|
||||
80000160: 06c12d83 lw s11,108(sp)
|
||||
80000164: 07012e03 lw t3,112(sp)
|
||||
80000168: 07412e83 lw t4,116(sp)
|
||||
8000016c: 07812f03 lw t5,120(sp)
|
||||
80000170: 07c12f83 lw t6,124(sp)
|
||||
80000174: 34011173 csrrw sp,mscratch,sp
|
||||
80000178: 30200073 mret
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
8000017c <putString>:
|
||||
8000017c: ff010113 addi sp,sp,-16
|
||||
80000180: 00812423 sw s0,8(sp)
|
||||
80000184: 00112623 sw ra,12(sp)
|
||||
80000188: 00050413 mv s0,a0
|
||||
8000018c: 00054503 lbu a0,0(a0)
|
||||
80000190: 00050a63 beqz a0,800001a4 <putString+0x28>
|
||||
80000194: 00140413 addi s0,s0,1
|
||||
80000198: 668000ef jal ra,80000800 <putC>
|
||||
8000019c: 00044503 lbu a0,0(s0)
|
||||
800001a0: fe051ae3 bnez a0,80000194 <putString+0x18>
|
||||
800001a4: 00c12083 lw ra,12(sp)
|
||||
800001a8: 00812403 lw s0,8(sp)
|
||||
800001ac: 01010113 addi sp,sp,16
|
||||
800001b0: 00008067 ret
|
||||
|
||||
800001b4 <setup_pmp>:
|
||||
800001b4: 01f00793 li a5,31
|
||||
800001b8: fff00713 li a4,-1
|
||||
800001bc: 00000297 auipc t0,0x0
|
||||
800001c0: 01428293 addi t0,t0,20 # 800001d0 <setup_pmp+0x1c>
|
||||
800001c4: 30529073 csrw mtvec,t0
|
||||
800001c8: 3b071073 csrw pmpaddr0,a4
|
||||
800001cc: 3a079073 csrw pmpcfg0,a5
|
||||
800001d0: 00008067 ret
|
||||
|
||||
800001d4 <init>:
|
||||
800001d4: ff010113 addi sp,sp,-16
|
||||
800001d8: 00112623 sw ra,12(sp)
|
||||
800001dc: 00812423 sw s0,8(sp)
|
||||
800001e0: 01f00793 li a5,31
|
||||
800001e4: fff00713 li a4,-1
|
||||
800001e8: 00000297 auipc t0,0x0
|
||||
800001ec: 01428293 addi t0,t0,20 # 800001fc <init+0x28>
|
||||
800001f0: 30529073 csrw mtvec,t0
|
||||
800001f4: 3b071073 csrw pmpaddr0,a4
|
||||
800001f8: 3a079073 csrw pmpcfg0,a5
|
||||
800001fc: 80001437 lui s0,0x80001
|
||||
80000200: 638000ef jal ra,80000838 <halInit>
|
||||
80000204: 95840413 addi s0,s0,-1704 # 80000958 <_sp+0xfffff7d0>
|
||||
80000208: 02a00513 li a0,42
|
||||
8000020c: 00140413 addi s0,s0,1
|
||||
80000210: 5f0000ef jal ra,80000800 <putC>
|
||||
80000214: 00044503 lbu a0,0(s0)
|
||||
80000218: fe051ae3 bnez a0,8000020c <init+0x38>
|
||||
8000021c: 800007b7 lui a5,0x80000
|
||||
80000220: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000224: 30579073 csrw mtvec,a5
|
||||
80000228: 800017b7 lui a5,0x80001
|
||||
8000022c: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
80000230: 34079073 csrw mscratch,a5
|
||||
80000234: 000017b7 lui a5,0x1
|
||||
80000238: 88078793 addi a5,a5,-1920 # 880 <__stack_size+0x80>
|
||||
8000023c: 30079073 csrw mstatus,a5
|
||||
80000240: 30405073 csrwi mie,0
|
||||
80000244: c00007b7 lui a5,0xc0000
|
||||
80000248: 34179073 csrw mepc,a5
|
||||
8000024c: 0000b7b7 lui a5,0xb
|
||||
80000250: 10078793 addi a5,a5,256 # b100 <__stack_size+0xa900>
|
||||
80000254: 30279073 csrw medeleg,a5
|
||||
80000258: 22200793 li a5,546
|
||||
8000025c: 30379073 csrw mideleg,a5
|
||||
80000260: 14305073 csrwi stval,0
|
||||
80000264: 80001437 lui s0,0x80001
|
||||
80000268: 97040413 addi s0,s0,-1680 # 80000970 <_sp+0xfffff7e8>
|
||||
8000026c: 02a00513 li a0,42
|
||||
80000270: 00140413 addi s0,s0,1
|
||||
80000274: 58c000ef jal ra,80000800 <putC>
|
||||
80000278: 00044503 lbu a0,0(s0)
|
||||
8000027c: fe051ae3 bnez a0,80000270 <init+0x9c>
|
||||
80000280: 00c12083 lw ra,12(sp)
|
||||
80000284: 00812403 lw s0,8(sp)
|
||||
80000288: 01010113 addi sp,sp,16
|
||||
8000028c: 00008067 ret
|
||||
|
||||
80000290 <readRegister>:
|
||||
80000290: 800017b7 lui a5,0x80001
|
||||
80000294: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
80000298: 00251513 slli a0,a0,0x2
|
||||
8000029c: 00f50533 add a0,a0,a5
|
||||
800002a0: 00052503 lw a0,0(a0)
|
||||
800002a4: 00008067 ret
|
||||
|
||||
800002a8 <writeRegister>:
|
||||
800002a8: 800017b7 lui a5,0x80001
|
||||
800002ac: 00251513 slli a0,a0,0x2
|
||||
800002b0: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
800002b4: 00f50533 add a0,a0,a5
|
||||
800002b8: 00b52023 sw a1,0(a0)
|
||||
800002bc: 00008067 ret
|
||||
|
||||
800002c0 <redirectTrap>:
|
||||
800002c0: ff010113 addi sp,sp,-16
|
||||
800002c4: 00112623 sw ra,12(sp)
|
||||
800002c8: 530000ef jal ra,800007f8 <stopSim>
|
||||
800002cc: 343027f3 csrr a5,mtval
|
||||
800002d0: 14379073 csrw stval,a5
|
||||
800002d4: 341027f3 csrr a5,mepc
|
||||
800002d8: 14179073 csrw sepc,a5
|
||||
800002dc: 342027f3 csrr a5,mcause
|
||||
800002e0: 14279073 csrw scause,a5
|
||||
800002e4: 105027f3 csrr a5,stvec
|
||||
800002e8: 34179073 csrw mepc,a5
|
||||
800002ec: 00c12083 lw ra,12(sp)
|
||||
800002f0: 01010113 addi sp,sp,16
|
||||
800002f4: 00008067 ret
|
||||
|
||||
800002f8 <emulationTrapToSupervisorTrap>:
|
||||
800002f8: 800007b7 lui a5,0x80000
|
||||
800002fc: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000300: 30579073 csrw mtvec,a5
|
||||
80000304: 343027f3 csrr a5,mtval
|
||||
80000308: 14379073 csrw stval,a5
|
||||
8000030c: 342027f3 csrr a5,mcause
|
||||
80000310: 14279073 csrw scause,a5
|
||||
80000314: 14151073 csrw sepc,a0
|
||||
80000318: 105027f3 csrr a5,stvec
|
||||
8000031c: 34179073 csrw mepc,a5
|
||||
80000320: 0035d793 srli a5,a1,0x3
|
||||
80000324: 00459713 slli a4,a1,0x4
|
||||
80000328: 02077713 andi a4,a4,32
|
||||
8000032c: 1007f793 andi a5,a5,256
|
||||
80000330: 00e7e7b3 or a5,a5,a4
|
||||
80000334: ffffe737 lui a4,0xffffe
|
||||
80000338: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
8000033c: 00e5f5b3 and a1,a1,a4
|
||||
80000340: 00b7e7b3 or a5,a5,a1
|
||||
80000344: 000015b7 lui a1,0x1
|
||||
80000348: 88058593 addi a1,a1,-1920 # 880 <__stack_size+0x80>
|
||||
8000034c: 00b7e7b3 or a5,a5,a1
|
||||
80000350: 30079073 csrw mstatus,a5
|
||||
80000354: 00008067 ret
|
||||
|
||||
80000358 <readWord>:
|
||||
80000358: 00020737 lui a4,0x20
|
||||
8000035c: 30072073 csrs mstatus,a4
|
||||
80000360: 00000717 auipc a4,0x0
|
||||
80000364: 01870713 addi a4,a4,24 # 80000378 <readWord+0x20>
|
||||
80000368: 30571073 csrw mtvec,a4
|
||||
8000036c: 00100693 li a3,1
|
||||
80000370: 00052783 lw a5,0(a0)
|
||||
80000374: 00000693 li a3,0
|
||||
80000378: 00020737 lui a4,0x20
|
||||
8000037c: 30073073 csrc mstatus,a4
|
||||
80000380: 00068513 mv a0,a3
|
||||
80000384: 00f5a023 sw a5,0(a1)
|
||||
80000388: 00008067 ret
|
||||
|
||||
8000038c <writeWord>:
|
||||
8000038c: 00020737 lui a4,0x20
|
||||
80000390: 30072073 csrs mstatus,a4
|
||||
80000394: 00000717 auipc a4,0x0
|
||||
80000398: 01870713 addi a4,a4,24 # 800003ac <writeWord+0x20>
|
||||
8000039c: 30571073 csrw mtvec,a4
|
||||
800003a0: 00100793 li a5,1
|
||||
800003a4: 00b52023 sw a1,0(a0)
|
||||
800003a8: 00000793 li a5,0
|
||||
800003ac: 00020737 lui a4,0x20
|
||||
800003b0: 30073073 csrc mstatus,a4
|
||||
800003b4: 00078513 mv a0,a5
|
||||
800003b8: 00008067 ret
|
||||
|
||||
800003bc <trap>:
|
||||
800003bc: fe010113 addi sp,sp,-32
|
||||
800003c0: 00112e23 sw ra,28(sp)
|
||||
800003c4: 00812c23 sw s0,24(sp)
|
||||
800003c8: 00912a23 sw s1,20(sp)
|
||||
800003cc: 01212823 sw s2,16(sp)
|
||||
800003d0: 01312623 sw s3,12(sp)
|
||||
800003d4: 342027f3 csrr a5,mcause
|
||||
800003d8: 0807cc63 bltz a5,80000470 <trap+0xb4>
|
||||
800003dc: 00200713 li a4,2
|
||||
800003e0: 0ce78463 beq a5,a4,800004a8 <trap+0xec>
|
||||
800003e4: 00900693 li a3,9
|
||||
800003e8: 04d79463 bne a5,a3,80000430 <trap+0x74>
|
||||
800003ec: 80001437 lui s0,0x80001
|
||||
800003f0: 18840413 addi s0,s0,392 # 80001188 <_sp+0x0>
|
||||
800003f4: fc442783 lw a5,-60(s0)
|
||||
800003f8: 00100693 li a3,1
|
||||
800003fc: fa842503 lw a0,-88(s0)
|
||||
80000400: 2ed78463 beq a5,a3,800006e8 <trap+0x32c>
|
||||
80000404: 2ee78e63 beq a5,a4,80000700 <trap+0x344>
|
||||
80000408: 2a078c63 beqz a5,800006c0 <trap+0x304>
|
||||
8000040c: 01812403 lw s0,24(sp)
|
||||
80000410: 01c12083 lw ra,28(sp)
|
||||
80000414: 01412483 lw s1,20(sp)
|
||||
80000418: 01012903 lw s2,16(sp)
|
||||
8000041c: 00c12983 lw s3,12(sp)
|
||||
80000420: 02010113 addi sp,sp,32
|
||||
80000424: 3d40006f j 800007f8 <stopSim>
|
||||
80000428: 00777713 andi a4,a4,7
|
||||
8000042c: 12f70c63 beq a4,a5,80000564 <trap+0x1a8>
|
||||
80000430: 3c8000ef jal ra,800007f8 <stopSim>
|
||||
80000434: 343027f3 csrr a5,mtval
|
||||
80000438: 14379073 csrw stval,a5
|
||||
8000043c: 341027f3 csrr a5,mepc
|
||||
80000440: 14179073 csrw sepc,a5
|
||||
80000444: 342027f3 csrr a5,mcause
|
||||
80000448: 14279073 csrw scause,a5
|
||||
8000044c: 105027f3 csrr a5,stvec
|
||||
80000450: 34179073 csrw mepc,a5
|
||||
80000454: 01c12083 lw ra,28(sp)
|
||||
80000458: 01812403 lw s0,24(sp)
|
||||
8000045c: 01412483 lw s1,20(sp)
|
||||
80000460: 01012903 lw s2,16(sp)
|
||||
80000464: 00c12983 lw s3,12(sp)
|
||||
80000468: 02010113 addi sp,sp,32
|
||||
8000046c: 00008067 ret
|
||||
80000470: 0ff7f793 andi a5,a5,255
|
||||
80000474: 00700713 li a4,7
|
||||
80000478: fae79ce3 bne a5,a4,80000430 <trap+0x74>
|
||||
8000047c: 02000793 li a5,32
|
||||
80000480: 1447a073 csrs sip,a5
|
||||
80000484: 08000793 li a5,128
|
||||
80000488: 3047b073 csrc mie,a5
|
||||
8000048c: 01c12083 lw ra,28(sp)
|
||||
80000490: 01812403 lw s0,24(sp)
|
||||
80000494: 01412483 lw s1,20(sp)
|
||||
80000498: 01012903 lw s2,16(sp)
|
||||
8000049c: 00c12983 lw s3,12(sp)
|
||||
800004a0: 02010113 addi sp,sp,32
|
||||
800004a4: 00008067 ret
|
||||
800004a8: 341024f3 csrr s1,mepc
|
||||
800004ac: 300025f3 csrr a1,mstatus
|
||||
800004b0: 34302473 csrr s0,mtval
|
||||
800004b4: 02f00613 li a2,47
|
||||
800004b8: 07f47693 andi a3,s0,127
|
||||
800004bc: 00c45713 srli a4,s0,0xc
|
||||
800004c0: f6c684e3 beq a3,a2,80000428 <trap+0x6c>
|
||||
800004c4: 07300613 li a2,115
|
||||
800004c8: f6c694e3 bne a3,a2,80000430 <trap+0x74>
|
||||
800004cc: 00377713 andi a4,a4,3
|
||||
800004d0: 10f70c63 beq a4,a5,800005e8 <trap+0x22c>
|
||||
800004d4: 00300793 li a5,3
|
||||
800004d8: 10f70863 beq a4,a5,800005e8 <trap+0x22c>
|
||||
800004dc: 00100993 li s3,1
|
||||
800004e0: 03370463 beq a4,s3,80000508 <trap+0x14c>
|
||||
800004e4: 314000ef jal ra,800007f8 <stopSim>
|
||||
800004e8: 343027f3 csrr a5,mtval
|
||||
800004ec: 14379073 csrw stval,a5
|
||||
800004f0: 341027f3 csrr a5,mepc
|
||||
800004f4: 14179073 csrw sepc,a5
|
||||
800004f8: 342027f3 csrr a5,mcause
|
||||
800004fc: 14279073 csrw scause,a5
|
||||
80000500: 105027f3 csrr a5,stvec
|
||||
80000504: 34179073 csrw mepc,a5
|
||||
80000508: 00001737 lui a4,0x1
|
||||
8000050c: 01445793 srli a5,s0,0x14
|
||||
80000510: c0070693 addi a3,a4,-1024 # c00 <__stack_size+0x400>
|
||||
80000514: 0ed7e263 bltu a5,a3,800005f8 <trap+0x23c>
|
||||
80000518: c0270713 addi a4,a4,-1022
|
||||
8000051c: 0cf77063 bgeu a4,a5,800005dc <trap+0x220>
|
||||
80000520: fffff737 lui a4,0xfffff
|
||||
80000524: 38070713 addi a4,a4,896 # fffff380 <_sp+0x7fffe1f8>
|
||||
80000528: 00e787b3 add a5,a5,a4
|
||||
8000052c: 00200713 li a4,2
|
||||
80000530: 0cf76463 bltu a4,a5,800005f8 <trap+0x23c>
|
||||
80000534: 2e4000ef jal ra,80000818 <rdtimeh>
|
||||
80000538: 00050913 mv s2,a0
|
||||
8000053c: 1c099e63 bnez s3,80000718 <trap+0x35c>
|
||||
80000540: 00545413 srli s0,s0,0x5
|
||||
80000544: 800017b7 lui a5,0x80001
|
||||
80000548: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
8000054c: 07c47413 andi s0,s0,124
|
||||
80000550: 00f40433 add s0,s0,a5
|
||||
80000554: 01242023 sw s2,0(s0)
|
||||
80000558: 00448493 addi s1,s1,4
|
||||
8000055c: 34149073 csrw mepc,s1
|
||||
80000560: ef5ff06f j 80000454 <trap+0x98>
|
||||
80000564: 00d45713 srli a4,s0,0xd
|
||||
80000568: 01245793 srli a5,s0,0x12
|
||||
8000056c: 800016b7 lui a3,0x80001
|
||||
80000570: 10868693 addi a3,a3,264 # 80001108 <_sp+0xffffff80>
|
||||
80000574: 07c77713 andi a4,a4,124
|
||||
80000578: 07c7f793 andi a5,a5,124
|
||||
8000057c: 00d70733 add a4,a4,a3
|
||||
80000580: 00d787b3 add a5,a5,a3
|
||||
80000584: 00072703 lw a4,0(a4)
|
||||
80000588: 0007a603 lw a2,0(a5)
|
||||
8000058c: 00020537 lui a0,0x20
|
||||
80000590: 30052073 csrs mstatus,a0
|
||||
80000594: 00000517 auipc a0,0x0
|
||||
80000598: 01850513 addi a0,a0,24 # 800005ac <trap+0x1f0>
|
||||
8000059c: 30551073 csrw mtvec,a0
|
||||
800005a0: 00100793 li a5,1
|
||||
800005a4: 00072803 lw a6,0(a4)
|
||||
800005a8: 00000793 li a5,0
|
||||
800005ac: 00020537 lui a0,0x20
|
||||
800005b0: 30053073 csrc mstatus,a0
|
||||
800005b4: 18079663 bnez a5,80000740 <trap+0x384>
|
||||
800005b8: 01b45793 srli a5,s0,0x1b
|
||||
800005bc: 01c00513 li a0,28
|
||||
800005c0: e6f568e3 bltu a0,a5,80000430 <trap+0x74>
|
||||
800005c4: 80001537 lui a0,0x80001
|
||||
800005c8: 00279793 slli a5,a5,0x2
|
||||
800005cc: 8e450513 addi a0,a0,-1820 # 800008e4 <_sp+0xfffff75c>
|
||||
800005d0: 00a787b3 add a5,a5,a0
|
||||
800005d4: 0007a783 lw a5,0(a5)
|
||||
800005d8: 00078067 jr a5
|
||||
800005dc: 234000ef jal ra,80000810 <rdtime>
|
||||
800005e0: 00050913 mv s2,a0
|
||||
800005e4: f59ff06f j 8000053c <trap+0x180>
|
||||
800005e8: 00f45993 srli s3,s0,0xf
|
||||
800005ec: 01f9f993 andi s3,s3,31
|
||||
800005f0: 013039b3 snez s3,s3
|
||||
800005f4: f15ff06f j 80000508 <trap+0x14c>
|
||||
800005f8: 200000ef jal ra,800007f8 <stopSim>
|
||||
800005fc: 343027f3 csrr a5,mtval
|
||||
80000600: 14379073 csrw stval,a5
|
||||
80000604: 341027f3 csrr a5,mepc
|
||||
80000608: 14179073 csrw sepc,a5
|
||||
8000060c: 342027f3 csrr a5,mcause
|
||||
80000610: 14279073 csrw scause,a5
|
||||
80000614: 105027f3 csrr a5,stvec
|
||||
80000618: 34179073 csrw mepc,a5
|
||||
8000061c: f21ff06f j 8000053c <trap+0x180>
|
||||
80000620: 01067463 bgeu a2,a6,80000628 <trap+0x26c>
|
||||
80000624: 00080613 mv a2,a6
|
||||
80000628: 00020537 lui a0,0x20
|
||||
8000062c: 30052073 csrs mstatus,a0
|
||||
80000630: 00000517 auipc a0,0x0
|
||||
80000634: 01850513 addi a0,a0,24 # 80000648 <trap+0x28c>
|
||||
80000638: 30551073 csrw mtvec,a0
|
||||
8000063c: 00100793 li a5,1
|
||||
80000640: 00c72023 sw a2,0(a4)
|
||||
80000644: 00000793 li a5,0
|
||||
80000648: 00020537 lui a0,0x20
|
||||
8000064c: 30053073 csrc mstatus,a0
|
||||
80000650: 80000737 lui a4,0x80000
|
||||
80000654: 07c70713 addi a4,a4,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000658: 14079463 bnez a5,800007a0 <trap+0x3e4>
|
||||
8000065c: 00545793 srli a5,s0,0x5
|
||||
80000660: 07c7f793 andi a5,a5,124
|
||||
80000664: 00d786b3 add a3,a5,a3
|
||||
80000668: 0106a023 sw a6,0(a3)
|
||||
8000066c: 00448493 addi s1,s1,4
|
||||
80000670: 34149073 csrw mepc,s1
|
||||
80000674: 30571073 csrw mtvec,a4
|
||||
80000678: dddff06f j 80000454 <trap+0x98>
|
||||
8000067c: 01064633 xor a2,a2,a6
|
||||
80000680: fa9ff06f j 80000628 <trap+0x26c>
|
||||
80000684: fac872e3 bgeu a6,a2,80000628 <trap+0x26c>
|
||||
80000688: 00080613 mv a2,a6
|
||||
8000068c: f9dff06f j 80000628 <trap+0x26c>
|
||||
80000690: f9065ce3 bge a2,a6,80000628 <trap+0x26c>
|
||||
80000694: 00080613 mv a2,a6
|
||||
80000698: f91ff06f j 80000628 <trap+0x26c>
|
||||
8000069c: f8c856e3 bge a6,a2,80000628 <trap+0x26c>
|
||||
800006a0: 00080613 mv a2,a6
|
||||
800006a4: f85ff06f j 80000628 <trap+0x26c>
|
||||
800006a8: 01067633 and a2,a2,a6
|
||||
800006ac: f7dff06f j 80000628 <trap+0x26c>
|
||||
800006b0: 01066633 or a2,a2,a6
|
||||
800006b4: f75ff06f j 80000628 <trap+0x26c>
|
||||
800006b8: 01060633 add a2,a2,a6
|
||||
800006bc: f6dff06f j 80000628 <trap+0x26c>
|
||||
800006c0: fac42583 lw a1,-84(s0)
|
||||
800006c4: 15c000ef jal ra,80000820 <setMachineTimerCmp>
|
||||
800006c8: 08000793 li a5,128
|
||||
800006cc: 3047a073 csrs mie,a5
|
||||
800006d0: 02000793 li a5,32
|
||||
800006d4: 1447b073 csrc sip,a5
|
||||
800006d8: 341027f3 csrr a5,mepc
|
||||
800006dc: 00478793 addi a5,a5,4
|
||||
800006e0: 34179073 csrw mepc,a5
|
||||
800006e4: d71ff06f j 80000454 <trap+0x98>
|
||||
800006e8: 0ff57513 andi a0,a0,255
|
||||
800006ec: 114000ef jal ra,80000800 <putC>
|
||||
800006f0: 341027f3 csrr a5,mepc
|
||||
800006f4: 00478793 addi a5,a5,4
|
||||
800006f8: 34179073 csrw mepc,a5
|
||||
800006fc: d59ff06f j 80000454 <trap+0x98>
|
||||
80000700: 108000ef jal ra,80000808 <getC>
|
||||
80000704: faa42423 sw a0,-88(s0)
|
||||
80000708: 341027f3 csrr a5,mepc
|
||||
8000070c: 00478793 addi a5,a5,4
|
||||
80000710: 34179073 csrw mepc,a5
|
||||
80000714: d41ff06f j 80000454 <trap+0x98>
|
||||
80000718: 0e0000ef jal ra,800007f8 <stopSim>
|
||||
8000071c: 343027f3 csrr a5,mtval
|
||||
80000720: 14379073 csrw stval,a5
|
||||
80000724: 341027f3 csrr a5,mepc
|
||||
80000728: 14179073 csrw sepc,a5
|
||||
8000072c: 342027f3 csrr a5,mcause
|
||||
80000730: 14279073 csrw scause,a5
|
||||
80000734: 105027f3 csrr a5,stvec
|
||||
80000738: 34179073 csrw mepc,a5
|
||||
8000073c: e05ff06f j 80000540 <trap+0x184>
|
||||
80000740: 800007b7 lui a5,0x80000
|
||||
80000744: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000748: 30579073 csrw mtvec,a5
|
||||
8000074c: 343027f3 csrr a5,mtval
|
||||
80000750: 14379073 csrw stval,a5
|
||||
80000754: 342027f3 csrr a5,mcause
|
||||
80000758: 14279073 csrw scause,a5
|
||||
8000075c: 14149073 csrw sepc,s1
|
||||
80000760: 105027f3 csrr a5,stvec
|
||||
80000764: 34179073 csrw mepc,a5
|
||||
80000768: 0035d793 srli a5,a1,0x3
|
||||
8000076c: 00459713 slli a4,a1,0x4
|
||||
80000770: 02077713 andi a4,a4,32
|
||||
80000774: 1007f793 andi a5,a5,256
|
||||
80000778: 00e7e7b3 or a5,a5,a4
|
||||
8000077c: ffffe737 lui a4,0xffffe
|
||||
80000780: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
80000784: 00e5f5b3 and a1,a1,a4
|
||||
80000788: 00001737 lui a4,0x1
|
||||
8000078c: 00b7e7b3 or a5,a5,a1
|
||||
80000790: 88070713 addi a4,a4,-1920 # 880 <__stack_size+0x80>
|
||||
80000794: 00e7e7b3 or a5,a5,a4
|
||||
80000798: 30079073 csrw mstatus,a5
|
||||
8000079c: cb9ff06f j 80000454 <trap+0x98>
|
||||
800007a0: 30571073 csrw mtvec,a4
|
||||
800007a4: 343027f3 csrr a5,mtval
|
||||
800007a8: 14379073 csrw stval,a5
|
||||
800007ac: 342027f3 csrr a5,mcause
|
||||
800007b0: 14279073 csrw scause,a5
|
||||
800007b4: 14149073 csrw sepc,s1
|
||||
800007b8: 105027f3 csrr a5,stvec
|
||||
800007bc: 34179073 csrw mepc,a5
|
||||
800007c0: 0035d793 srli a5,a1,0x3
|
||||
800007c4: 00459713 slli a4,a1,0x4
|
||||
800007c8: 02077713 andi a4,a4,32
|
||||
800007cc: 1007f793 andi a5,a5,256
|
||||
800007d0: 00e7e7b3 or a5,a5,a4
|
||||
800007d4: ffffe737 lui a4,0xffffe
|
||||
800007d8: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
800007dc: 00e5f5b3 and a1,a1,a4
|
||||
800007e0: 00b7e5b3 or a1,a5,a1
|
||||
800007e4: 000017b7 lui a5,0x1
|
||||
800007e8: 88078793 addi a5,a5,-1920 # 880 <__stack_size+0x80>
|
||||
800007ec: 00f5e7b3 or a5,a1,a5
|
||||
800007f0: 30079073 csrw mstatus,a5
|
||||
800007f4: c61ff06f j 80000454 <trap+0x98>
|
||||
|
||||
800007f8 <stopSim>:
|
||||
800007f8: fe002e23 sw zero,-4(zero) # fffffffc <_sp+0x7fffee74>
|
||||
800007fc: 0000006f j 800007fc <stopSim+0x4>
|
||||
|
||||
80000800 <putC>:
|
||||
80000800: fea02c23 sw a0,-8(zero) # fffffff8 <_sp+0x7fffee70>
|
||||
80000804: 00008067 ret
|
||||
|
||||
80000808 <getC>:
|
||||
80000808: ff802503 lw a0,-8(zero) # fffffff8 <_sp+0x7fffee70>
|
||||
8000080c: 00008067 ret
|
||||
|
||||
80000810 <rdtime>:
|
||||
80000810: fe002503 lw a0,-32(zero) # ffffffe0 <_sp+0x7fffee58>
|
||||
80000814: 00008067 ret
|
||||
|
||||
80000818 <rdtimeh>:
|
||||
80000818: fe402503 lw a0,-28(zero) # ffffffe4 <_sp+0x7fffee5c>
|
||||
8000081c: 00008067 ret
|
||||
|
||||
80000820 <setMachineTimerCmp>:
|
||||
80000820: fec00793 li a5,-20
|
||||
80000824: fff00713 li a4,-1
|
||||
80000828: 00e7a023 sw a4,0(a5)
|
||||
8000082c: fea02423 sw a0,-24(zero) # ffffffe8 <_sp+0x7fffee60>
|
||||
80000830: 00b7a023 sw a1,0(a5)
|
||||
80000834: 00008067 ret
|
||||
|
||||
80000838 <halInit>:
|
||||
80000838: 00008067 ret
|
||||
|
||||
8000083c <__libc_init_array>:
|
||||
8000083c: ff010113 addi sp,sp,-16
|
||||
80000840: 00000797 auipc a5,0x0
|
||||
80000844: 0a478793 addi a5,a5,164 # 800008e4 <__init_array_end>
|
||||
80000848: 00812423 sw s0,8(sp)
|
||||
8000084c: 00000417 auipc s0,0x0
|
||||
80000850: 09840413 addi s0,s0,152 # 800008e4 <__init_array_end>
|
||||
80000854: 40f40433 sub s0,s0,a5
|
||||
80000858: 00912223 sw s1,4(sp)
|
||||
8000085c: 01212023 sw s2,0(sp)
|
||||
80000860: 00112623 sw ra,12(sp)
|
||||
80000864: 40245413 srai s0,s0,0x2
|
||||
80000868: 00000493 li s1,0
|
||||
8000086c: 00078913 mv s2,a5
|
||||
80000870: 04849263 bne s1,s0,800008b4 <__libc_init_array+0x78>
|
||||
80000874: 805ff0ef jal ra,80000078 <_init>
|
||||
80000878: 00000797 auipc a5,0x0
|
||||
8000087c: 06c78793 addi a5,a5,108 # 800008e4 <__init_array_end>
|
||||
80000880: 00000417 auipc s0,0x0
|
||||
80000884: 06440413 addi s0,s0,100 # 800008e4 <__init_array_end>
|
||||
80000888: 40f40433 sub s0,s0,a5
|
||||
8000088c: 40245413 srai s0,s0,0x2
|
||||
80000890: 00000493 li s1,0
|
||||
80000894: 00078913 mv s2,a5
|
||||
80000898: 02849a63 bne s1,s0,800008cc <__libc_init_array+0x90>
|
||||
8000089c: 00c12083 lw ra,12(sp)
|
||||
800008a0: 00812403 lw s0,8(sp)
|
||||
800008a4: 00412483 lw s1,4(sp)
|
||||
800008a8: 00012903 lw s2,0(sp)
|
||||
800008ac: 01010113 addi sp,sp,16
|
||||
800008b0: 00008067 ret
|
||||
800008b4: 00249793 slli a5,s1,0x2
|
||||
800008b8: 00f907b3 add a5,s2,a5
|
||||
800008bc: 0007a783 lw a5,0(a5)
|
||||
800008c0: 00148493 addi s1,s1,1
|
||||
800008c4: 000780e7 jalr a5
|
||||
800008c8: fa9ff06f j 80000870 <__libc_init_array+0x34>
|
||||
800008cc: 00249793 slli a5,s1,0x2
|
||||
800008d0: 00f907b3 add a5,s2,a5
|
||||
800008d4: 0007a783 lw a5,0(a5)
|
||||
800008d8: 00148493 addi s1,s1,1
|
||||
800008dc: 000780e7 jalr a5
|
||||
800008e0: fb9ff06f j 80000898 <__libc_init_array+0x5c>
|
BIN
src/main/c/emulator/build/emulator.bin
Executable file
BIN
src/main/c/emulator/build/emulator.bin
Executable file
Binary file not shown.
157
src/main/c/emulator/build/emulator.hex
Normal file
157
src/main/c/emulator/build/emulator.hex
Normal file
|
@ -0,0 +1,157 @@
|
|||
:0200000480007A
|
||||
:100000001711000013018118171500001305C58D85
|
||||
:10001000971500009385458D171600001306069767
|
||||
:1000200063FCC5008322050023A05500130545008D
|
||||
:1000300093854500E3E8C5FE1715000013050595F7
|
||||
:1000400097150000938585946378B50023200500FB
|
||||
:1000500013054500E36CB5FEEF00407EEF0080170E
|
||||
:10006000970000009380400113050000B70500C30E
|
||||
:10007000730020306F0000006780000073110134AE
|
||||
:10008000232211002326310023284100232A510076
|
||||
:10009000232C6100232E7100232081022322910250
|
||||
:1000A0002324A1022326B1022328C102232AD1023C
|
||||
:1000B000232CE102232EF102232001052322110526
|
||||
:1000C000232421052326310523284105232A510510
|
||||
:1000D000232C6105232E71052320810723229107FC
|
||||
:1000E0002324A1072326B1072328C107232AD107E8
|
||||
:1000F000232CE107232EF107EF00402C8320410041
|
||||
:100100008321C100032201018322410103238101D4
|
||||
:100110008323C101032401028324410203258102B8
|
||||
:100120008325C1020326010383264103032781039C
|
||||
:100130008327C10303280104832841040329810480
|
||||
:100140008329C104032A0105832A4105032B810564
|
||||
:10015000832BC105032C0106832C4106032D810648
|
||||
:10016000832DC106032E0107832E4107032F81072C
|
||||
:0C017000832FC10773110134730020308D
|
||||
:10017C00130101FF23248100232611001304050021
|
||||
:10018C0003450500630A050013041400EF008066A4
|
||||
:10019C0003450400E31A05FE8320C10003248100FB
|
||||
:1001AC0013010101678000009307F0011307F0FFB2
|
||||
:1001BC009702000093824201739052307310073BF8
|
||||
:1001CC007390073A67800000130101FF232611008A
|
||||
:1001DC00232481009307F0011307F0FF970200001E
|
||||
:1001EC0093824201739052307310073B7390073A1D
|
||||
:1001FC0037140080EF008063130484951305A0026C
|
||||
:10020C0013041400EF00005F03450400E31A05FE1D
|
||||
:10021C00B70700809387C70773905730B7170080D4
|
||||
:10022C009387871073900734B7170000938707885C
|
||||
:10023C007390073073504030B70700C07390173479
|
||||
:10024C00B7B70000938707107390273093072022CD
|
||||
:10025C0073903730735030143714008013040497A4
|
||||
:10026C001305A00213041400EF00C058034504004A
|
||||
:10027C00E31A05FE8320C100032481001301010150
|
||||
:10028C0067800000B717008093878710131525002F
|
||||
:10029C003305F5000325050067800000B7170080C3
|
||||
:1002AC0013152500938787103305F5002320B5001F
|
||||
:1002BC0067800000130101FF23261100EF0000539B
|
||||
:1002CC00F327303473903714F327103473901714CA
|
||||
:1002DC00F327203473902714F3275010739017349E
|
||||
:1002EC008320C1001301010167800000B707008063
|
||||
:1002FC009387C70773905730F327303473903714B4
|
||||
:10030C00F32720347390271473101514F32750100F
|
||||
:10031C007390173493D73500139745001377070262
|
||||
:10032C0093F70710B3E7E70037E7FFFF1307D76D25
|
||||
:10033C00B3F5E500B3E7B700B71500009385058862
|
||||
:10034C00B3E7B700739007306780000037070200EF
|
||||
:10035C0073200730170700001307870173105730FD
|
||||
:10036C009306100083270500930600003707020050
|
||||
:10037C00733007301385060023A0F500678000005A
|
||||
:10038C003707020073200730170700001307870197
|
||||
:10039C0073105730930710002320B500930700000B
|
||||
:1003AC0037070200733007301385070067800000A1
|
||||
:1003BC00130101FE232E1100232C8100232A91000E
|
||||
:1003CC002328210123263101F327203463CC07088D
|
||||
:1003DC00130720006384E70C930690006394D70402
|
||||
:1003EC003714008013048418832744FC93061000F0
|
||||
:1003FC00032584FA6384D72E638EE72E638C072A39
|
||||
:10040C00032481018320C1018324410103290101BB
|
||||
:10041C008329C100130101026F00403D137777005F
|
||||
:10042C00630CF712EF00803CF327303473903714D1
|
||||
:10043C00F327103473901714F32720347390271478
|
||||
:10044C00F3275010739017348320C10103248101CA
|
||||
:10045C0083244101032901018329C10013010102F5
|
||||
:10046C006780000093F7F70F13077000E39CE7FA1F
|
||||
:10047C009307000273A047149307000873B047302A
|
||||
:10048C008320C1010324810183244101032901013B
|
||||
:10049C008329C1001301010267800000F32410348A
|
||||
:1004AC00F3250030732430341306F0029376F407EE
|
||||
:1004BC001357C400E384C6F613063007E394C6F65C
|
||||
:1004CC0013773700630CF710930730006308F710AD
|
||||
:1004DC009309100063043703EF004031F3273034E5
|
||||
:1004EC0073903714F327103473901714F3272034B8
|
||||
:1004FC0073902714F327501073901734371700009C
|
||||
:10050C0093574401930607C063E2D70E130727C025
|
||||
:10051C006370F70C37F7FFFF13070738B387E70053
|
||||
:10052C00130720006364F70CEF00402E130905003D
|
||||
:10053C00639E091C13545400B717008093878710CF
|
||||
:10054C001374C4073304F40023202401938444005F
|
||||
:10055C00739014346FF05FEF1357D400935724014A
|
||||
:10056C00B7160080938686101377C70793F7C707D3
|
||||
:10057C003307D700B387D7000327070003A607006C
|
||||
:10058C00370502007320053017050000130585019F
|
||||
:10059C0073105530930710000328070093070000D1
|
||||
:1005AC003705020073300530639607189357B40172
|
||||
:1005BC001305C001E368F5E6371500809397270013
|
||||
:1005CC001305458EB387A70083A707006780070034
|
||||
:1005DC00EF004023130905006FF09FF59359F400C9
|
||||
:1005EC0093F9F901B33930016FF05FF1EF0000209E
|
||||
:1005FC00F327303473903714F32710347390171497
|
||||
:10060C00F327203473902714F3275010739017346A
|
||||
:10061C006FF01FF263740601130608003705020021
|
||||
:10062C007320053017050000130585017310553034
|
||||
:10063C00930710002320C700930700003705020022
|
||||
:10064C0073300530370700801307C707639407140E
|
||||
:10065C009357540093F7C707B386D70023A006011E
|
||||
:10066C009384440073901434731057306FF0DFDDB3
|
||||
:10067C00334606016FF09FFAE372C8FA13060800BE
|
||||
:10068C006FF0DFF9E35C06F9130608006FF01FF951
|
||||
:10069C00E356C8F8130608006FF05FF833760601CE
|
||||
:1006AC006FF0DFF7336606016FF05FF73306060174
|
||||
:1006BC006FF0DFF68325C4FAEF00C015930700082E
|
||||
:1006CC0073A047309307000273B04714F32710341C
|
||||
:1006DC0093874700739017346FF01FD71375F50F7E
|
||||
:1006EC00EF004011F32710349387470073901734B1
|
||||
:1006FC006FF09FD5EF0080102324A4FAF327103459
|
||||
:10070C0093874700739017346FF01FD4EF00000EDF
|
||||
:10071C00F327303473903714F32710347390171475
|
||||
:10072C00F327203473902714F32750107390173449
|
||||
:10073C006FF05FE0B70700809387C707739057305F
|
||||
:10074C00F327303473903714F32720347390271425
|
||||
:10075C0073901414F32750107390173493D73500FB
|
||||
:10076C00139745001377070293F70710B3E7E700D9
|
||||
:10077C0037E7FFFF1307D76DB3F5E5003717000018
|
||||
:10078C00B3E7B70013070788B3E7E70073900730A8
|
||||
:10079C006FF09FCB73105730F327303473903714AE
|
||||
:1007AC00F32720347390271473901414F3275010EC
|
||||
:1007BC007390173493D735001397450013770702BE
|
||||
:1007CC0093F70710B3E7E70037E7FFFF1307D76D81
|
||||
:1007DC00B3F5E500B3E5B700B717000093870788BA
|
||||
:1007EC00B3E7F500739007306FF01FC6232E00FEA1
|
||||
:1007FC006F000000232CA0FE67800000032580FF03
|
||||
:10080C0067800000032500FE67800000032540FE82
|
||||
:10081C00678000009307C0FE1307F0FF23A0E700DA
|
||||
:10082C002324A0FE23A0B70067800000678000008F
|
||||
:10083C00130101FF970700009387470A23248100C7
|
||||
:10084C0017040000130484093304F440232291009C
|
||||
:10085C00232021012326110013542440930400006B
|
||||
:10086C001389070063928404EFF05F809707000000
|
||||
:10087C009387C70617040000130444063304F4409E
|
||||
:10088C00135424409304000013890700639A8402D4
|
||||
:10089C008320C1000324810083244100032901002B
|
||||
:1008AC00130101016780000093972400B307F9003E
|
||||
:1008BC0083A7070093841400E78007006FF09FFA6A
|
||||
:1008CC0093972400B307F90083A7070093841400BF
|
||||
:0808DC00E78007006FF09FFBAD
|
||||
:1008E400B8060080280600803004008030040080B0
|
||||
:1008F4007C060080300400803004008030040080D6
|
||||
:10090400B006008030040080300400803004008091
|
||||
:10091400A806008030040080300400803004008089
|
||||
:100924009C06008030040080300400803004008085
|
||||
:100934009006008030040080300400803004008081
|
||||
:10094400840600803004008030040080300400807D
|
||||
:10095400200600802A2A2A20566578526973637615
|
||||
:100964002042494F53202A2A2A0A00002A2A2A20F0
|
||||
:1009740053757065727669736F72202A2A2A0A0089
|
||||
:04098400000000006F
|
||||
:040000058000000077
|
||||
:00000001FF
|
29
src/main/c/emulator/makefile
Executable file
29
src/main/c/emulator/makefile
Executable file
|
@ -0,0 +1,29 @@
|
|||
PROJ_NAME=emulator
|
||||
DEBUG=no
|
||||
MULDIV=no
|
||||
COMPRESSED=no
|
||||
STANDALONE = ..
|
||||
|
||||
|
||||
SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/*.cpp) \
|
||||
$(wildcard src/*.S)
|
||||
|
||||
|
||||
LDSCRIPT = ${STANDALONE}/common/ram.ld
|
||||
|
||||
sim: CFLAGS += -DSIM
|
||||
sim: all
|
||||
|
||||
qemu: CFLAGS += -DQEMU
|
||||
qemu: all
|
||||
|
||||
litex: CFLAGS += -DLITEX -I${LITEX_GENERATED} -I${LITEX_BASE}/litex/soc/software/include
|
||||
litex: | check_litex all
|
||||
check_litex:
|
||||
@[ "${LITEX_BASE}" ] || ( echo ">> LITEX_BASE is not set"; exit 1 )
|
||||
@[ "${LITEX_GENERATED}" ] || ( echo ">> LITEX_GENERATED is not set"; exit 1 )
|
||||
|
||||
include ${STANDALONE}/common/riscv64-unknown-elf.mk
|
||||
include ${STANDALONE}/common/standalone.mk
|
||||
|
12
src/main/c/emulator/src/config.h
Normal file
12
src/main/c/emulator/src/config.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#ifndef OS_CALL
|
||||
#define OS_CALL 0xC0000000
|
||||
#endif
|
||||
|
||||
#ifndef DTB
|
||||
#define DTB 0xC3000000
|
||||
#endif
|
||||
|
||||
#endif
|
203
src/main/c/emulator/src/hal.c
Normal file
203
src/main/c/emulator/src/hal.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
#include "hal.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef SIM
|
||||
void stopSim(){
|
||||
*((volatile uint32_t*) 0xFFFFFFFC) = 0;
|
||||
while(1);
|
||||
}
|
||||
|
||||
void putC(char c){
|
||||
*((volatile uint32_t*) 0xFFFFFFF8) = c;
|
||||
}
|
||||
|
||||
int32_t getC(){
|
||||
return *((volatile int32_t*) 0xFFFFFFF8);
|
||||
}
|
||||
|
||||
uint32_t rdtime(){
|
||||
return *((volatile uint32_t*) 0xFFFFFFE0);
|
||||
}
|
||||
|
||||
uint32_t rdtimeh(){
|
||||
return *((volatile uint32_t*) 0xFFFFFFE4);
|
||||
}
|
||||
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high){
|
||||
volatile uint32_t* base = (volatile uint32_t*) 0xFFFFFFE8;
|
||||
base[1] = 0xffffffff;
|
||||
base[0] = low;
|
||||
base[1] = high;
|
||||
}
|
||||
|
||||
|
||||
void halInit(){
|
||||
// putC('*');
|
||||
// putC('*');
|
||||
// putC('*');
|
||||
// while(1){
|
||||
// int32_t c = getC();
|
||||
// if(c > 0) putC(c);
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef QEMU
|
||||
#define VIRT_CLINT 0x2000000
|
||||
#define SIFIVE_TIMECMP_BASE (VIRT_CLINT + 0x4000)
|
||||
#define SIFIVE_TIME_BASE (VIRT_CLINT + 0xBFF8)
|
||||
#define NS16550A_UART0_CTRL_ADDR 0x10000000
|
||||
#define UART0_CLOCK_FREQ 32000000
|
||||
#define UART0_BAUD_RATE 115200
|
||||
enum {
|
||||
UART_RBR = 0x00, /* Receive Buffer Register */
|
||||
UART_THR = 0x00, /* Transmit Hold Register */
|
||||
UART_IER = 0x01, /* Interrupt Enable Register */
|
||||
UART_DLL = 0x00, /* Divisor LSB (LCR_DLAB) */
|
||||
UART_DLM = 0x01, /* Divisor MSB (LCR_DLAB) */
|
||||
UART_FCR = 0x02, /* FIFO Control Register */
|
||||
UART_LCR = 0x03, /* Line Control Register */
|
||||
UART_MCR = 0x04, /* Modem Control Register */
|
||||
UART_LSR = 0x05, /* Line Status Register */
|
||||
UART_MSR = 0x06, /* Modem Status Register */
|
||||
UART_SCR = 0x07, /* Scratch Register */
|
||||
|
||||
UART_LCR_DLAB = 0x80, /* Divisor Latch Bit */
|
||||
UART_LCR_8BIT = 0x03, /* 8-bit */
|
||||
UART_LCR_PODD = 0x08, /* Parity Odd */
|
||||
|
||||
UART_LSR_DA = 0x01, /* Data Available */
|
||||
UART_LSR_OE = 0x02, /* Overrun Error */
|
||||
UART_LSR_PE = 0x04, /* Parity Error */
|
||||
UART_LSR_FE = 0x08, /* Framing Error */
|
||||
UART_LSR_BI = 0x10, /* Break indicator */
|
||||
UART_LSR_RE = 0x20, /* THR is empty */
|
||||
UART_LSR_RI = 0x40, /* THR is empty and line is idle */
|
||||
UART_LSR_EF = 0x80, /* Erroneous data in FIFO */
|
||||
};
|
||||
|
||||
static volatile uint8_t *uart;
|
||||
|
||||
static void ns16550a_init()
|
||||
{
|
||||
uart = (uint8_t *)(void *)(NS16550A_UART0_CTRL_ADDR);
|
||||
uint32_t uart_freq = (UART0_CLOCK_FREQ);
|
||||
uint32_t baud_rate = (UART0_BAUD_RATE);
|
||||
uint32_t divisor = uart_freq / (16 * baud_rate);
|
||||
uart[UART_LCR] = UART_LCR_DLAB;
|
||||
uart[UART_DLL] = divisor & 0xff;
|
||||
uart[UART_DLM] = (divisor >> 8) & 0xff;
|
||||
uart[UART_LCR] = UART_LCR_PODD | UART_LCR_8BIT;
|
||||
}
|
||||
|
||||
//static int ns16550a_getchar()
|
||||
//{
|
||||
// if (uart[UART_LSR] & UART_LSR_DA) {
|
||||
// return uart[UART_RBR];
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//static int ns16550a_putchar(int ch)
|
||||
//{
|
||||
// while ((uart[UART_LSR] & UART_LSR_RI) == 0);
|
||||
// return uart[UART_THR] = ch & 0xff;
|
||||
//}
|
||||
|
||||
void stopSim(){
|
||||
while(1);
|
||||
}
|
||||
|
||||
void putC(char ch){
|
||||
while ((uart[UART_LSR] & UART_LSR_RI) == 0);
|
||||
uart[UART_THR] = ch & 0xff;
|
||||
}
|
||||
|
||||
int32_t getC(){
|
||||
if (uart[UART_LSR] & UART_LSR_DA) {
|
||||
return uart[UART_RBR];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t rdtime(){
|
||||
return *((volatile uint32_t*) SIFIVE_TIME_BASE);
|
||||
}
|
||||
|
||||
uint32_t rdtimeh(){
|
||||
return *((volatile uint32_t*) (SIFIVE_TIME_BASE + 4));
|
||||
}
|
||||
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high){
|
||||
volatile uint32_t* base = (volatile uint32_t*) SIFIVE_TIMECMP_BASE;
|
||||
base[1] = 0xffffffff;
|
||||
base[0] = low;
|
||||
base[1] = high;
|
||||
}
|
||||
|
||||
void halInit(){
|
||||
ns16550a_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LITEX
|
||||
|
||||
// this is a file generated by LiteX
|
||||
#include <generated/csr.h>
|
||||
|
||||
#if !defined(CSR_UART_BASE) || !defined(CSR_CPU_BASE)
|
||||
#error LiteX configuration with uart and cpu_timer is required.
|
||||
#endif
|
||||
|
||||
void stopSim(){
|
||||
while(1);
|
||||
}
|
||||
|
||||
void putC(char ch){
|
||||
// protect against writing to a full tx fifo
|
||||
while(uart_txfull_read());
|
||||
uart_rxtx_write(ch);
|
||||
}
|
||||
|
||||
int32_t getC(){
|
||||
if(uart_rxempty_read())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// this is required to refresh rexempty status
|
||||
uart_ev_pending_write(1 << 1);
|
||||
return uart_rxtx_read();
|
||||
}
|
||||
|
||||
uint32_t rdtime(){
|
||||
cpu_timer_latch_write(0);
|
||||
uint32_t result = (uint32_t)cpu_timer_time_read();
|
||||
cpu_timer_latch_write(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t rdtimeh(){
|
||||
cpu_timer_latch_write(0);
|
||||
uint32_t result = (uint32_t)(cpu_timer_time_read() >> 32);
|
||||
cpu_timer_latch_write(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high){
|
||||
cpu_timer_latch_write(0);
|
||||
cpu_timer_time_cmp_write((((unsigned long long int)high) << 32) | low);
|
||||
cpu_timer_latch_write(1);
|
||||
}
|
||||
|
||||
void halInit(){
|
||||
cpu_timer_latch_write(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
25
src/main/c/emulator/src/hal.h
Normal file
25
src/main/c/emulator/src/hal.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
#ifndef HAL_H
|
||||
#define HAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SBI_SET_TIMER 0
|
||||
#define SBI_CONSOLE_PUTCHAR 1
|
||||
#define SBI_CONSOLE_GETCHAR 2
|
||||
#define SBI_CLEAR_IPI 3
|
||||
#define SBI_SEND_IPI 4
|
||||
#define SBI_REMOTE_FENCE_I 5
|
||||
#define SBI_REMOTE_SFENCE_VMA 6
|
||||
#define SBI_REMOTE_SFENCE_VMA_ASID 7
|
||||
#define SBI_SHUTDOWN 8
|
||||
|
||||
void halInit();
|
||||
void stopSim();
|
||||
void putC(char c);
|
||||
int32_t getC();
|
||||
uint32_t rdtime();
|
||||
uint32_t rdtimeh();
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high);
|
||||
|
||||
#endif
|
288
src/main/c/emulator/src/main.c
Executable file
288
src/main/c/emulator/src/main.c
Executable file
|
@ -0,0 +1,288 @@
|
|||
#include <stdint.h>
|
||||
#include "riscv.h"
|
||||
#include "config.h"
|
||||
#include "hal.h"
|
||||
|
||||
extern const uint32_t _sp;
|
||||
extern void trapEntry();
|
||||
extern void emulationTrap();
|
||||
|
||||
void putString(char* s){
|
||||
while(*s){
|
||||
putC(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
//Affect mtvec
|
||||
void setup_pmp(void)
|
||||
{
|
||||
// Set up a PMP to permit access to all of memory.
|
||||
// Ignore the illegal-instruction trap if PMPs aren't supported.
|
||||
uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
|
||||
asm volatile ("la t0, 1f\n\t"
|
||||
"csrw mtvec, t0\n\t"
|
||||
"csrw pmpaddr0, %1\n\t"
|
||||
"csrw pmpcfg0, %0\n\t"
|
||||
".align 2\n\t"
|
||||
"1:"
|
||||
: : "r" (pmpc), "r" (-1UL) : "t0");
|
||||
}
|
||||
|
||||
void init() {
|
||||
setup_pmp();
|
||||
halInit();
|
||||
putString("*** VexRiscv BIOS ***\n");
|
||||
uint32_t sp = (uint32_t) (&_sp);
|
||||
csr_write(mtvec, trapEntry);
|
||||
csr_write(mscratch, sp -32*4);
|
||||
csr_write(mstatus, 0x0800 | MSTATUS_MPIE);
|
||||
csr_write(mie, 0);
|
||||
csr_write(mepc, OS_CALL);
|
||||
//In future it would probably need to manage missaligned stuff, now it will stop the simulation
|
||||
csr_write(medeleg, MEDELEG_INSTRUCTION_PAGE_FAULT | MEDELEG_LOAD_PAGE_FAULT | MEDELEG_STORE_PAGE_FAULT | MEDELEG_USER_ENVIRONNEMENT_CALL);
|
||||
csr_write(mideleg, MIDELEG_SUPERVISOR_TIMER | MIDELEG_SUPERVISOR_EXTERNAL | MIDELEG_SUPERVISOR_SOFTWARE);
|
||||
csr_write(sbadaddr, 0); //Used to avoid simulation missmatch
|
||||
|
||||
putString("*** Supervisor ***\n");
|
||||
}
|
||||
|
||||
int readRegister(uint32_t id){
|
||||
unsigned int sp = (unsigned int) (&_sp);
|
||||
return ((int*) sp)[id-32];
|
||||
}
|
||||
void writeRegister(uint32_t id, int value){
|
||||
uint32_t sp = (uint32_t) (&_sp);
|
||||
((uint32_t*) sp)[id-32] = value;
|
||||
}
|
||||
|
||||
|
||||
//Currently, this should not happen, unless kernel things are going wrong
|
||||
void redirectTrap(){
|
||||
stopSim();
|
||||
csr_write(sbadaddr, csr_read(mbadaddr));
|
||||
csr_write(sepc, csr_read(mepc));
|
||||
csr_write(scause, csr_read(mcause));
|
||||
csr_write(mepc, csr_read(stvec));
|
||||
}
|
||||
|
||||
void emulationTrapToSupervisorTrap(uint32_t sepc, uint32_t mstatus){
|
||||
csr_write(mtvec, trapEntry);
|
||||
csr_write(sbadaddr, csr_read(mbadaddr));
|
||||
csr_write(scause, csr_read(mcause));
|
||||
csr_write(sepc, sepc);
|
||||
csr_write(mepc, csr_read(stvec));
|
||||
csr_write(mstatus,
|
||||
(mstatus & ~(MSTATUS_SPP | MSTATUS_MPP | MSTATUS_SIE | MSTATUS_SPIE))
|
||||
| ((mstatus >> 3) & MSTATUS_SPP)
|
||||
| (0x0800 | MSTATUS_MPIE)
|
||||
| ((mstatus & MSTATUS_SIE) << 4)
|
||||
);
|
||||
}
|
||||
|
||||
#define max(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
|
||||
|
||||
//Will modify MTVEC
|
||||
int32_t readWord(uint32_t address, int32_t *data){
|
||||
int32_t result, tmp;
|
||||
int32_t failed;
|
||||
__asm__ __volatile__ (
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrs mstatus, %[tmp]\n"
|
||||
" la %[tmp], 1f\n"
|
||||
" csrw mtvec, %[tmp]\n"
|
||||
" li %[failed], 1\n"
|
||||
" lw %[result], 0(%[address])\n"
|
||||
" li %[failed], 0\n"
|
||||
"1:\n"
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrc mstatus, %[tmp]\n"
|
||||
: [result]"=&r" (result), [failed]"=&r" (failed), [tmp]"=&r" (tmp)
|
||||
: [address]"r" (address)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
*data = result;
|
||||
return failed;
|
||||
}
|
||||
|
||||
//Will modify MTVEC
|
||||
int32_t writeWord(uint32_t address, int32_t data){
|
||||
int32_t result, tmp;
|
||||
int32_t failed;
|
||||
__asm__ __volatile__ (
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrs mstatus, %[tmp]\n"
|
||||
" la %[tmp], 1f\n"
|
||||
" csrw mtvec, %[tmp]\n"
|
||||
" li %[failed], 1\n"
|
||||
" sw %[data], 0(%[address])\n"
|
||||
" li %[failed], 0\n"
|
||||
"1:\n"
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrc mstatus, %[tmp]\n"
|
||||
: [failed]"=&r" (failed), [tmp]"=&r" (tmp)
|
||||
: [address]"r" (address), [data]"r" (data)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trap(){
|
||||
int32_t cause = csr_read(mcause);
|
||||
if(cause < 0){ //interrupt
|
||||
switch(cause & 0xFF){
|
||||
case CAUSE_MACHINE_TIMER:{
|
||||
csr_set(sip, MIP_STIP);
|
||||
csr_clear(mie, MIE_MTIE);
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
} else { //exception
|
||||
switch(cause){
|
||||
case CAUSE_ILLEGAL_INSTRUCTION:{
|
||||
uint32_t mepc = csr_read(mepc);
|
||||
uint32_t mstatus = csr_read(mstatus);
|
||||
#ifdef SIM
|
||||
uint32_t instruction = csr_read(mbadaddr);
|
||||
#endif
|
||||
#if defined(QEMU) || defined(LITEX)
|
||||
uint32_t instruction = 0;
|
||||
uint32_t i;
|
||||
if (mepc & 2) {
|
||||
readWord(mepc - 2, &i);
|
||||
i >>= 16;
|
||||
if (i & 3 == 3) {
|
||||
uint32_t u32Buf;
|
||||
readWord(mepc+2, &u32Buf);
|
||||
i |= u32Buf << 16;
|
||||
}
|
||||
} else {
|
||||
readWord(mepc, &i);
|
||||
}
|
||||
instruction = i;
|
||||
csr_write(mtvec, trapEntry); //Restore mtvec
|
||||
#endif
|
||||
|
||||
uint32_t opcode = instruction & 0x7F;
|
||||
uint32_t funct3 = (instruction >> 12) & 0x7;
|
||||
switch(opcode){
|
||||
case 0x2F: //Atomic
|
||||
switch(funct3){
|
||||
case 0x2:{
|
||||
uint32_t sel = instruction >> 27;
|
||||
uint32_t addr = readRegister((instruction >> 15) & 0x1F);
|
||||
int32_t src = readRegister((instruction >> 20) & 0x1F);
|
||||
uint32_t rd = (instruction >> 7) & 0x1F;
|
||||
int32_t readValue;
|
||||
if(readWord(addr, &readValue)){
|
||||
emulationTrapToSupervisorTrap(mepc, mstatus);
|
||||
return;
|
||||
}
|
||||
int writeValue;
|
||||
switch(sel){
|
||||
case 0x0: writeValue = src + readValue; break;
|
||||
case 0x1: writeValue = src; break;
|
||||
//LR SC done in hardware (cheap), and require to keep track of context switches
|
||||
// case 0x2:{ //LR
|
||||
// }break;
|
||||
// case 0x3:{ //SC
|
||||
// }break;
|
||||
case 0x4: writeValue = src ^ readValue; break;
|
||||
case 0xC: writeValue = src & readValue; break;
|
||||
case 0x8: writeValue = src | readValue; break;
|
||||
case 0x10: writeValue = min(src, readValue); break;
|
||||
case 0x14: writeValue = max(src, readValue); break;
|
||||
case 0x18: writeValue = min((unsigned int)src, (unsigned int)readValue); break;
|
||||
case 0x1C: writeValue = max((unsigned int)src, (unsigned int)readValue); break;
|
||||
default: redirectTrap(); return; break;
|
||||
}
|
||||
if(writeWord(addr, writeValue)){
|
||||
emulationTrapToSupervisorTrap(mepc, mstatus);
|
||||
return;
|
||||
}
|
||||
writeRegister(rd, readValue);
|
||||
csr_write(mepc, mepc + 4);
|
||||
csr_write(mtvec, trapEntry); //Restore mtvec
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
} break;
|
||||
case 0x73:{
|
||||
//CSR
|
||||
uint32_t input = (instruction & 0x4000) ? ((instruction >> 15) & 0x1F) : readRegister((instruction >> 15) & 0x1F);;
|
||||
uint32_t clear, set;
|
||||
uint32_t write;
|
||||
switch (funct3 & 0x3) {
|
||||
case 0: redirectTrap(); break;
|
||||
case 1: clear = ~0; set = input; write = 1; break;
|
||||
case 2: clear = 0; set = input; write = ((instruction >> 15) & 0x1F) != 0; break;
|
||||
case 3: clear = input; set = 0; write = ((instruction >> 15) & 0x1F) != 0; break;
|
||||
}
|
||||
uint32_t csrAddress = instruction >> 20;
|
||||
uint32_t old;
|
||||
switch(csrAddress){
|
||||
case RDCYCLE :
|
||||
case RDINSTRET:
|
||||
case RDTIME : old = rdtime(); break;
|
||||
case RDCYCLEH :
|
||||
case RDINSTRETH:
|
||||
case RDTIMEH : old = rdtimeh(); break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
if(write) {
|
||||
uint32_t newValue = (old & ~clear) | set;
|
||||
switch(csrAddress){
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}
|
||||
|
||||
writeRegister((instruction >> 7) & 0x1F, old);
|
||||
csr_write(mepc, mepc + 4);
|
||||
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}break;
|
||||
case CAUSE_SCALL:{
|
||||
uint32_t which = readRegister(17);
|
||||
uint32_t a0 = readRegister(10);
|
||||
uint32_t a1 = readRegister(11);
|
||||
uint32_t a2 = readRegister(12);
|
||||
switch(which){
|
||||
case SBI_CONSOLE_PUTCHAR:{
|
||||
putC(a0);
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
case SBI_CONSOLE_GETCHAR:{
|
||||
writeRegister(10, getC()); //no char
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
case SBI_SET_TIMER:{
|
||||
setMachineTimerCmp(a0, a1);
|
||||
csr_set(mie, MIE_MTIE);
|
||||
csr_clear(sip, MIP_STIP);
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
default: stopSim(); break;
|
||||
}
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
133
src/main/c/emulator/src/riscv.h
Normal file
133
src/main/c/emulator/src/riscv.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
#ifndef RISCV_H
|
||||
#define RISCV_H
|
||||
|
||||
#define CAUSE_ILLEGAL_INSTRUCTION 2
|
||||
#define CAUSE_MACHINE_TIMER 7
|
||||
#define CAUSE_SCALL 9
|
||||
|
||||
#define MEDELEG_INSTRUCTION_PAGE_FAULT (1 << 12)
|
||||
#define MEDELEG_LOAD_PAGE_FAULT (1 << 13)
|
||||
#define MEDELEG_STORE_PAGE_FAULT (1 << 15)
|
||||
#define MEDELEG_USER_ENVIRONNEMENT_CALL (1 << 8)
|
||||
#define MIDELEG_SUPERVISOR_SOFTWARE (1 << 1)
|
||||
#define MIDELEG_SUPERVISOR_TIMER (1 << 5)
|
||||
#define MIDELEG_SUPERVISOR_EXTERNAL (1 << 9)
|
||||
|
||||
#define MIE_MTIE (1 << 7)
|
||||
#define MIP_STIP (1 << 5)
|
||||
|
||||
#define MSTATUS_UIE 0x00000001
|
||||
#define MSTATUS_SIE 0x00000002
|
||||
#define MSTATUS_HIE 0x00000004
|
||||
#define MSTATUS_MIE 0x00000008
|
||||
#define MSTATUS_UPIE 0x00000010
|
||||
#define MSTATUS_SPIE 0x00000020
|
||||
#define MSTATUS_HPIE 0x00000040
|
||||
#define MSTATUS_MPIE 0x00000080
|
||||
#define MSTATUS_SPP 0x00000100
|
||||
#define MSTATUS_HPP 0x00000600
|
||||
#define MSTATUS_MPP 0x00001800
|
||||
#define MSTATUS_FS 0x00006000
|
||||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_SUM 0x00040000
|
||||
#define MSTATUS_MXR 0x00080000
|
||||
#define MSTATUS_TVM 0x00100000
|
||||
#define MSTATUS_TW 0x00200000
|
||||
#define MSTATUS_TSR 0x00400000
|
||||
#define MSTATUS32_SD 0x80000000
|
||||
#define MSTATUS_UXL 0x0000000300000000
|
||||
#define MSTATUS_SXL 0x0000000C00000000
|
||||
#define MSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define SSTATUS_UIE 0x00000001
|
||||
#define SSTATUS_SIE 0x00000002
|
||||
#define SSTATUS_UPIE 0x00000010
|
||||
#define SSTATUS_SPIE 0x00000020
|
||||
#define SSTATUS_SPP 0x00000100
|
||||
#define SSTATUS_FS 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_SUM 0x00040000
|
||||
#define SSTATUS_MXR 0x00080000
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS_UXL 0x0000000300000000
|
||||
#define SSTATUS64_SD 0x8000000000000000
|
||||
|
||||
|
||||
#define PMP_R 0x01
|
||||
#define PMP_W 0x02
|
||||
#define PMP_X 0x04
|
||||
#define PMP_A 0x18
|
||||
#define PMP_L 0x80
|
||||
#define PMP_SHIFT 2
|
||||
|
||||
#define PMP_TOR 0x08
|
||||
#define PMP_NA4 0x10
|
||||
#define PMP_NAPOT 0x18
|
||||
|
||||
#define RDCYCLE 0xC00 //Read-only cycle Cycle counter for RDCYCLE instruction.
|
||||
#define RDTIME 0xC01 //Read-only time Timer for RDTIME instruction.
|
||||
#define RDINSTRET 0xC02 //Read-only instret Instructions-retired counter for RDINSTRET instruction.
|
||||
#define RDCYCLEH 0xC80 //Read-only cycleh Upper 32 bits of cycle, RV32I only.
|
||||
#define RDTIMEH 0xC81 //Read-only timeh Upper 32 bits of time, RV32I only.
|
||||
#define RDINSTRETH 0xC82 //Read-only instreth Upper 32 bits of instret, RV32I only.
|
||||
|
||||
|
||||
#define csr_swap(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ __volatile__ ("csrr %0, " #csr \
|
||||
: "=r" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrw " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrs " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrc " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
51
src/main/c/emulator/src/start.S
Executable file
51
src/main/c/emulator/src/start.S
Executable file
|
@ -0,0 +1,51 @@
|
|||
.section .init
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
|
||||
#include "config.h"
|
||||
_start:
|
||||
/*#ifdef USE_GP
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
#endif*/
|
||||
la sp, _sp
|
||||
|
||||
|
||||
/* Load data section */
|
||||
la a0, _data_lma
|
||||
la a1, _data
|
||||
la a2, _edata
|
||||
bgeu a1, a2, 2f
|
||||
1:
|
||||
lw t0, (a0)
|
||||
sw t0, (a1)
|
||||
addi a0, a0, 4
|
||||
addi a1, a1, 4
|
||||
bltu a1, a2, 1b
|
||||
2:
|
||||
|
||||
/* Clear bss section */
|
||||
la a0, __bss_start
|
||||
la a1, _end
|
||||
bgeu a0, a1, 2f
|
||||
1:
|
||||
sw zero, (a0)
|
||||
addi a0, a0, 4
|
||||
bltu a0, a1, 1b
|
||||
2:
|
||||
|
||||
call __libc_init_array
|
||||
call init
|
||||
la ra, done
|
||||
li a0, 0
|
||||
li a1, DTB
|
||||
mret
|
||||
done:
|
||||
j done
|
||||
|
||||
|
||||
.globl _init
|
||||
_init:
|
||||
ret
|
71
src/main/c/emulator/src/trap.S
Normal file
71
src/main/c/emulator/src/trap.S
Normal file
|
@ -0,0 +1,71 @@
|
|||
.section .init
|
||||
.globl trapEntry
|
||||
.type trapEntry,@function
|
||||
|
||||
trapEntry:
|
||||
csrrw sp, mscratch, sp
|
||||
sw x1, 1*4(sp)
|
||||
sw x3, 3*4(sp)
|
||||
sw x4, 4*4(sp)
|
||||
sw x5, 5*4(sp)
|
||||
sw x6, 6*4(sp)
|
||||
sw x7, 7*4(sp)
|
||||
sw x8, 8*4(sp)
|
||||
sw x9, 9*4(sp)
|
||||
sw x10, 10*4(sp)
|
||||
sw x11, 11*4(sp)
|
||||
sw x12, 12*4(sp)
|
||||
sw x13, 13*4(sp)
|
||||
sw x14, 14*4(sp)
|
||||
sw x15, 15*4(sp)
|
||||
sw x16, 16*4(sp)
|
||||
sw x17, 17*4(sp)
|
||||
sw x18, 18*4(sp)
|
||||
sw x19, 19*4(sp)
|
||||
sw x20, 20*4(sp)
|
||||
sw x21, 21*4(sp)
|
||||
sw x22, 22*4(sp)
|
||||
sw x23, 23*4(sp)
|
||||
sw x24, 24*4(sp)
|
||||
sw x25, 25*4(sp)
|
||||
sw x26, 26*4(sp)
|
||||
sw x27, 27*4(sp)
|
||||
sw x28, 28*4(sp)
|
||||
sw x29, 29*4(sp)
|
||||
sw x30, 30*4(sp)
|
||||
sw x31, 31*4(sp)
|
||||
call trap
|
||||
lw x1, 1*4(sp)
|
||||
lw x3, 3*4(sp)
|
||||
lw x4, 4*4(sp)
|
||||
lw x5, 5*4(sp)
|
||||
lw x6, 6*4(sp)
|
||||
lw x7, 7*4(sp)
|
||||
lw x8, 8*4(sp)
|
||||
lw x9, 9*4(sp)
|
||||
lw x10, 10*4(sp)
|
||||
lw x11, 11*4(sp)
|
||||
lw x12, 12*4(sp)
|
||||
lw x13, 13*4(sp)
|
||||
lw x14, 14*4(sp)
|
||||
lw x15, 15*4(sp)
|
||||
lw x16, 16*4(sp)
|
||||
lw x17, 17*4(sp)
|
||||
lw x18, 18*4(sp)
|
||||
lw x19, 19*4(sp)
|
||||
lw x20, 20*4(sp)
|
||||
lw x21, 21*4(sp)
|
||||
lw x22, 22*4(sp)
|
||||
lw x23, 23*4(sp)
|
||||
lw x24, 24*4(sp)
|
||||
lw x25, 25*4(sp)
|
||||
lw x26, 26*4(sp)
|
||||
lw x27, 27*4(sp)
|
||||
lw x28, 28*4(sp)
|
||||
lw x29, 29*4(sp)
|
||||
lw x30, 30*4(sp)
|
||||
lw x31, 31*4(sp)
|
||||
csrrw sp, mscratch, sp
|
||||
mret
|
||||
|
||||
|
47
src/main/c/emulator/src/utils.S
Normal file
47
src/main/c/emulator/src/utils.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "riscv.h"
|
||||
/*
|
||||
|
||||
.section .init
|
||||
.globl readMemory
|
||||
.type readMemory,@function
|
||||
readWord:
|
||||
csrr a4, mepc
|
||||
li a2, MSTATUS_MPRV
|
||||
csrs mstatus, a2
|
||||
li a3, emulationTrap
|
||||
csrw mepc, a3
|
||||
lw a0, 0(a0)
|
||||
li a3, trapEntry
|
||||
csrw mepc, a3
|
||||
csrc mstatus, a2
|
||||
|
||||
writeWord:
|
||||
csrr a4, mepc
|
||||
li a2, MSTATUS_MPRV
|
||||
csrs mstatus, a2
|
||||
li a3, emulationTrap
|
||||
csrw mepc, a3
|
||||
sw a1, 0(a0)
|
||||
li a3, trapEntry
|
||||
csrw mepc, a3
|
||||
csrc mstatus, a2
|
||||
*/
|
||||
//Redirect trap to supervisor
|
||||
/*
|
||||
.section .init
|
||||
.globl emulationTrap
|
||||
.type emulationTrap,@function
|
||||
emulationTrap:
|
||||
li a0, MSTATUS_MPRV
|
||||
csrc mstatus, a0
|
||||
|
||||
la sp, _sp
|
||||
csrw sepc, a4
|
||||
csrr a0, mcause
|
||||
csrw scause, a0
|
||||
csrr a0, mbadaddr
|
||||
csrw sbadaddr, a0
|
||||
|
||||
call init
|
||||
mret
|
||||
*/
|
134
src/main/c/murax/hello_world/makefile
Normal file
134
src/main/c/murax/hello_world/makefile
Normal file
|
@ -0,0 +1,134 @@
|
|||
PROJ_NAME=hello_world
|
||||
DEBUG=no
|
||||
BENCH=no
|
||||
MULDIV=no
|
||||
|
||||
SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/*.cpp) \
|
||||
$(wildcard src/*.S)
|
||||
|
||||
OBJDIR = build
|
||||
|
||||
INC =
|
||||
LIBS =
|
||||
LIBSINC = -L$(OBJDIR)
|
||||
LDSCRIPT = ./src/linker.ld
|
||||
|
||||
#include ../../../resources/gcc.mk
|
||||
# Set it to yes if you are using the sifive precompiled GCC pack
|
||||
SIFIVE_GCC_PACK ?= yes
|
||||
|
||||
ifeq ($(SIFIVE_GCC_PACK),yes)
|
||||
RISCV_NAME ?= riscv64-unknown-elf
|
||||
RISCV_PATH ?= /opt/riscv/
|
||||
else
|
||||
RISCV_NAME ?= riscv32-unknown-elf
|
||||
ifeq ($(MULDIV),yes)
|
||||
RISCV_PATH ?= /opt/riscv32im/
|
||||
else
|
||||
RISCV_PATH ?= /opt/riscv32i/
|
||||
endif
|
||||
endif
|
||||
|
||||
MABI=ilp32
|
||||
MARCH := rv32i
|
||||
ifeq ($(MULDIV),yes)
|
||||
MARCH := $(MARCH)m
|
||||
endif
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
MARCH := $(MARCH)ac
|
||||
endif
|
||||
|
||||
CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG
|
||||
LDFLAGS += -march=$(MARCH) -mabi=$(MABI)
|
||||
|
||||
|
||||
|
||||
#include ../../../resources/subproject.mk
|
||||
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CFLAGS += -g3 -O0
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),no)
|
||||
CFLAGS += -g -Os
|
||||
endif
|
||||
|
||||
ifeq ($(BENCH),yes)
|
||||
CFLAGS += -fno-inline
|
||||
endif
|
||||
|
||||
ifeq ($(SIFIVE_GCC_PACK),yes)
|
||||
RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
|
||||
else
|
||||
RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
|
||||
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
|
||||
RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
|
||||
|
||||
CFLAGS += -MD -fstrict-volatile-bitfields -fno-strict-aliasing
|
||||
LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
|
||||
#LDFLAGS += -lgcc -lc -lg -nostdlib -lgcc -msave-restore --strip-debug,
|
||||
|
||||
OBJS := $(SRCS)
|
||||
OBJS := $(OBJS:.c=.o)
|
||||
OBJS := $(OBJS:.cpp=.o)
|
||||
OBJS := $(OBJS:.S=.o)
|
||||
OBJS := $(OBJS:..=miaou)
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
|
||||
|
||||
|
||||
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
|
||||
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBSINC) $(LIBS)
|
||||
|
||||
%.hex: %.elf
|
||||
$(RISCV_OBJCOPY) -O ihex $^ $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(RISCV_OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.v: %.elf
|
||||
$(RISCV_OBJCOPY) -O verilog $^ $@
|
||||
|
||||
%.asm: %.elf
|
||||
$(RISCV_OBJDUMP) -S -d $^ > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
$(RISCV_CC) -S $(CFLAGS) $(INC) -o $@.disasm $^
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.S
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(OBJDIR)/src
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).elf
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).hex
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).map
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).v
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).asm
|
||||
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
|
||||
find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
|
||||
|
||||
clean-all : clean
|
||||
|
||||
.SECONDARY: $(OBJS)
|
98
src/main/c/murax/hello_world/src/crt.S
Normal file
98
src/main/c/murax/hello_world/src/crt.S
Normal file
|
@ -0,0 +1,98 @@
|
|||
.global crtStart
|
||||
.global main
|
||||
.global irqCallback
|
||||
|
||||
.section .start_jump,"ax",@progbits
|
||||
crtStart:
|
||||
//long jump to allow crtInit to be anywhere
|
||||
//do it always in 12 bytes
|
||||
lui x2, %hi(crtInit)
|
||||
addi x2, x2, %lo(crtInit)
|
||||
jalr x1,x2
|
||||
nop
|
||||
|
||||
.section .text
|
||||
|
||||
.global trap_entry
|
||||
.align 5
|
||||
trap_entry:
|
||||
sw x1, - 1*4(sp)
|
||||
sw x5, - 2*4(sp)
|
||||
sw x6, - 3*4(sp)
|
||||
sw x7, - 4*4(sp)
|
||||
sw x10, - 5*4(sp)
|
||||
sw x11, - 6*4(sp)
|
||||
sw x12, - 7*4(sp)
|
||||
sw x13, - 8*4(sp)
|
||||
sw x14, - 9*4(sp)
|
||||
sw x15, -10*4(sp)
|
||||
sw x16, -11*4(sp)
|
||||
sw x17, -12*4(sp)
|
||||
sw x28, -13*4(sp)
|
||||
sw x29, -14*4(sp)
|
||||
sw x30, -15*4(sp)
|
||||
sw x31, -16*4(sp)
|
||||
addi sp,sp,-16*4
|
||||
call irqCallback
|
||||
lw x1 , 15*4(sp)
|
||||
lw x5, 14*4(sp)
|
||||
lw x6, 13*4(sp)
|
||||
lw x7, 12*4(sp)
|
||||
lw x10, 11*4(sp)
|
||||
lw x11, 10*4(sp)
|
||||
lw x12, 9*4(sp)
|
||||
lw x13, 8*4(sp)
|
||||
lw x14, 7*4(sp)
|
||||
lw x15, 6*4(sp)
|
||||
lw x16, 5*4(sp)
|
||||
lw x17, 4*4(sp)
|
||||
lw x28, 3*4(sp)
|
||||
lw x29, 2*4(sp)
|
||||
lw x30, 1*4(sp)
|
||||
lw x31, 0*4(sp)
|
||||
addi sp,sp,16*4
|
||||
mret
|
||||
.text
|
||||
|
||||
|
||||
crtInit:
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
la sp, _stack_start
|
||||
|
||||
bss_init:
|
||||
la a0, _bss_start
|
||||
la a1, _bss_end
|
||||
bss_loop:
|
||||
beq a0,a1,bss_done
|
||||
sw zero,0(a0)
|
||||
add a0,a0,4
|
||||
j bss_loop
|
||||
bss_done:
|
||||
|
||||
ctors_init:
|
||||
la a0, _ctors_start
|
||||
addi sp,sp,-4
|
||||
ctors_loop:
|
||||
la a1, _ctors_end
|
||||
beq a0,a1,ctors_done
|
||||
lw a3,0(a0)
|
||||
add a0,a0,4
|
||||
sw a0,0(sp)
|
||||
jalr a3
|
||||
lw a0,0(sp)
|
||||
j ctors_loop
|
||||
ctors_done:
|
||||
addi sp,sp,4
|
||||
|
||||
|
||||
li a0, 0x880 //880 enable timer + external interrupts
|
||||
csrw mie,a0
|
||||
li a0, 0x1808 //1808 enable interrupts
|
||||
csrw mstatus,a0
|
||||
|
||||
call main
|
||||
infinitLoop:
|
||||
j infinitLoop
|
15
src/main/c/murax/hello_world/src/gpio.h
Normal file
15
src/main/c/murax/hello_world/src/gpio.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef GPIO_H_
|
||||
#define GPIO_H_
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t INPUT;
|
||||
volatile uint32_t OUTPUT;
|
||||
volatile uint32_t OUTPUT_ENABLE;
|
||||
} Gpio_Reg;
|
||||
|
||||
|
||||
#endif /* GPIO_H_ */
|
||||
|
||||
|
17
src/main/c/murax/hello_world/src/interrupt.h
Normal file
17
src/main/c/murax/hello_world/src/interrupt.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef INTERRUPTCTRL_H_
|
||||
#define INTERRUPTCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t PENDINGS;
|
||||
volatile uint32_t MASKS;
|
||||
} InterruptCtrl_Reg;
|
||||
|
||||
static void interruptCtrl_init(InterruptCtrl_Reg* reg){
|
||||
reg->MASKS = 0;
|
||||
reg->PENDINGS = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
#endif /* INTERRUPTCTRL_H_ */
|
110
src/main/c/murax/hello_world/src/linker.ld
Normal file
110
src/main/c/murax/hello_world/src/linker.ld
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(crtStart)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = 0x80000000, LENGTH = 2k
|
||||
}
|
||||
|
||||
_stack_size = DEFINED(_stack_size) ? _stack_size : 256;
|
||||
_heap_size = DEFINED(_heap_size) ? _heap_size : 0;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
._vector ORIGIN(RAM): {
|
||||
*crt.o(.start_jump);
|
||||
*crt.o(.text);
|
||||
} > RAM
|
||||
|
||||
._user_heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
PROVIDE ( _heap_start = .);
|
||||
. = . + _heap_size;
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( _heap_end = .);
|
||||
} > RAM
|
||||
|
||||
._stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_stack_end = .);
|
||||
. = . + _stack_size;
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_stack_start = .);
|
||||
} > RAM
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_bss_start = .;
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_bss_end = .;
|
||||
} > RAM
|
||||
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} > RAM
|
||||
|
||||
.noinit (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.memory : {
|
||||
*(.text);
|
||||
end = .;
|
||||
} > RAM
|
||||
|
||||
.ctors :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_ctors_start = .;
|
||||
KEEP(*(.init_array*))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4);
|
||||
_ctors_end = .;
|
||||
PROVIDE ( END_OF_SW_IMAGE = . );
|
||||
} > RAM
|
||||
|
||||
}
|
42
src/main/c/murax/hello_world/src/main.c
Normal file
42
src/main/c/murax/hello_world/src/main.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
//#include "stddefs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "murax.h"
|
||||
|
||||
void print(const char*str){
|
||||
while(*str){
|
||||
uart_write(UART,*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
void println(const char*str){
|
||||
print(str);
|
||||
uart_write(UART,'\n');
|
||||
}
|
||||
|
||||
void delay(uint32_t loops){
|
||||
for(int i=0;i<loops;i++){
|
||||
int tmp = GPIO_A->OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
GPIO_A->OUTPUT_ENABLE = 0x0000000F;
|
||||
GPIO_A->OUTPUT = 0x00000001;
|
||||
println("hello world arty a7 v1");
|
||||
const int nleds = 4;
|
||||
const int nloops = 2000000;
|
||||
while(1){
|
||||
for(unsigned int i=0;i<nleds-1;i++){
|
||||
GPIO_A->OUTPUT = 1<<i;
|
||||
delay(nloops);
|
||||
}
|
||||
for(unsigned int i=0;i<nleds-1;i++){
|
||||
GPIO_A->OUTPUT = (1<<(nleds-1))>>i;
|
||||
delay(nloops);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void irqCallback(){
|
||||
}
|
17
src/main/c/murax/hello_world/src/murax.h
Normal file
17
src/main/c/murax/hello_world/src/murax.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef __MURAX_H__
|
||||
#define __MURAX_H__
|
||||
|
||||
#include "timer.h"
|
||||
#include "prescaler.h"
|
||||
#include "interrupt.h"
|
||||
#include "gpio.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define GPIO_A ((Gpio_Reg*)(0xF0000000))
|
||||
#define TIMER_PRESCALER ((Prescaler_Reg*)0xF0020000)
|
||||
#define TIMER_INTERRUPT ((InterruptCtrl_Reg*)0xF0020010)
|
||||
#define TIMER_A ((Timer_Reg*)0xF0020040)
|
||||
#define TIMER_B ((Timer_Reg*)0xF0020050)
|
||||
#define UART ((Uart_Reg*)(0xF0010000))
|
||||
|
||||
#endif /* __MURAX_H__ */
|
16
src/main/c/murax/hello_world/src/prescaler.h
Normal file
16
src/main/c/murax/hello_world/src/prescaler.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef PRESCALERCTRL_H_
|
||||
#define PRESCALERCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t LIMIT;
|
||||
} Prescaler_Reg;
|
||||
|
||||
static void prescaler_init(Prescaler_Reg* reg){
|
||||
|
||||
}
|
||||
|
||||
#endif /* PRESCALERCTRL_H_ */
|
20
src/main/c/murax/hello_world/src/timer.h
Normal file
20
src/main/c/murax/hello_world/src/timer.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef TIMERCTRL_H_
|
||||
#define TIMERCTRL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t CLEARS_TICKS;
|
||||
volatile uint32_t LIMIT;
|
||||
volatile uint32_t VALUE;
|
||||
} Timer_Reg;
|
||||
|
||||
static void timer_init(Timer_Reg *reg){
|
||||
reg->CLEARS_TICKS = 0;
|
||||
reg->VALUE = 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TIMERCTRL_H_ */
|
42
src/main/c/murax/hello_world/src/uart.h
Normal file
42
src/main/c/murax/hello_world/src/uart.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef UART_H_
|
||||
#define UART_H_
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t DATA;
|
||||
volatile uint32_t STATUS;
|
||||
volatile uint32_t CLOCK_DIVIDER;
|
||||
volatile uint32_t FRAME_CONFIG;
|
||||
} Uart_Reg;
|
||||
|
||||
enum UartParity {NONE = 0,EVEN = 1,ODD = 2};
|
||||
enum UartStop {ONE = 0,TWO = 1};
|
||||
|
||||
typedef struct {
|
||||
uint32_t dataLength;
|
||||
enum UartParity parity;
|
||||
enum UartStop stop;
|
||||
uint32_t clockDivider;
|
||||
} Uart_Config;
|
||||
|
||||
static uint32_t uart_writeAvailability(Uart_Reg *reg){
|
||||
return (reg->STATUS >> 16) & 0xFF;
|
||||
}
|
||||
static uint32_t uart_readOccupancy(Uart_Reg *reg){
|
||||
return reg->STATUS >> 24;
|
||||
}
|
||||
|
||||
static void uart_write(Uart_Reg *reg, uint32_t data){
|
||||
while(uart_writeAvailability(reg) == 0);
|
||||
reg->DATA = data;
|
||||
}
|
||||
|
||||
static void uart_applyConfig(Uart_Reg *reg, Uart_Config *config){
|
||||
reg->CLOCK_DIVIDER = config->clockDivider;
|
||||
reg->FRAME_CONFIG = ((config->dataLength-1) << 0) | (config->parity << 8) | (config->stop << 16);
|
||||
}
|
||||
|
||||
#endif /* UART_H_ */
|
||||
|
||||
|
|
@ -42,13 +42,33 @@ crtStart:
|
|||
li t0, 0x1
|
||||
sw t0, CTRL_XIP_CONFIG(CTRL)
|
||||
li t0, XIP_BASE
|
||||
lw t1, (t0)
|
||||
li t2, 0xFFFFFFFF
|
||||
xor t3,t1,t2
|
||||
beqz t3,retry
|
||||
//if we are here we have read a value from flash which is not all ones
|
||||
lw t2, (t0)
|
||||
xor t3,t1,t2
|
||||
bnez t3,retry
|
||||
lw t2, (t0)
|
||||
xor t3,t1,t2
|
||||
bnez t3,retry
|
||||
//if we are here we have read the same value 3 times, so flash seems good, lets's jump
|
||||
jr t0
|
||||
|
||||
retry:
|
||||
li a0, 0x800
|
||||
call spiWrite
|
||||
li t1,100000
|
||||
loop:
|
||||
addi t1,t1,-1
|
||||
bnez t1, loop
|
||||
j crtStart
|
||||
|
||||
spiWrite:
|
||||
sw a0,CTRL_DATA(CTRL)
|
||||
spiWrite_wait:
|
||||
lw t0,CTRL_STATUS(CTRL)
|
||||
srli t0,t0,0x10
|
||||
slli t0,t0,0x10
|
||||
beqz t0,spiWrite_wait
|
||||
ret
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue