From b1b29bcfb3c47324a0d8b27e96479a515ef9a160 Mon Sep 17 00:00:00 2001 From: wanda-phi <145241585+wanda-phi@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:54:53 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20=20@=20689fa?= =?UTF-8?q?2a05867eb0dd18e44514f68cd2a0ea33659=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .buildinfo | 4 + .doctrees/environment.pickle | Bin 0 -> 556475 bytes .doctrees/index.doctree | Bin 0 -> 3430 bytes .doctrees/xc9500/bitstream-xc9500.doctree | Bin 0 -> 84099 bytes .doctrees/xc9500/bitstream-xc9500xl.doctree | Bin 0 -> 54802 bytes .doctrees/xc9500/index.doctree | Bin 0 -> 2959 bytes .doctrees/xc9500/intro.doctree | Bin 0 -> 58267 bytes .doctrees/xc9500/jtag.doctree | Bin 0 -> 46966 bytes .doctrees/xc9500/structure.doctree | Bin 0 -> 131115 bytes .nojekyll | 0 _sources/index.rst.txt | 17 + _sources/xc9500/bitstream-xc9500.rst.txt | 415 +++++++++ _sources/xc9500/bitstream-xc9500xl.rst.txt | 272 ++++++ _sources/xc9500/index.rst.txt | 12 + _sources/xc9500/intro.rst.txt | 126 +++ _sources/xc9500/jtag.rst.txt | 171 ++++ _sources/xc9500/structure.rst.txt | 622 +++++++++++++ _static/alabaster.css | 703 +++++++++++++++ _static/basic.css | 925 ++++++++++++++++++++ _static/custom.css | 1 + _static/doctools.js | 156 ++++ _static/documentation_options.js | 13 + _static/file.png | Bin 0 -> 286 bytes _static/language_data.js | 199 +++++ _static/minus.png | Bin 0 -> 90 bytes _static/plus.png | Bin 0 -> 90 bytes _static/pygments.css | 84 ++ _static/searchtools.js | 574 ++++++++++++ _static/sphinx_highlight.js | 154 ++++ genindex.html | 102 +++ index.html | 111 +++ objects.inv | Bin 0 -> 379 bytes search.html | 121 +++ searchindex.js | 1 + xc9500/bitstream-xc9500.html | 543 ++++++++++++ xc9500/bitstream-xc9500xl.html | 385 ++++++++ xc9500/index.html | 162 ++++ xc9500/intro.html | 607 +++++++++++++ xc9500/jtag.html | 373 ++++++++ xc9500/structure.html | 753 ++++++++++++++++ 40 files changed, 7606 insertions(+) create mode 100644 .buildinfo create mode 100644 .doctrees/environment.pickle create mode 100644 .doctrees/index.doctree create mode 100644 .doctrees/xc9500/bitstream-xc9500.doctree create mode 100644 .doctrees/xc9500/bitstream-xc9500xl.doctree create mode 100644 .doctrees/xc9500/index.doctree create mode 100644 .doctrees/xc9500/intro.doctree create mode 100644 .doctrees/xc9500/jtag.doctree create mode 100644 .doctrees/xc9500/structure.doctree create mode 100644 .nojekyll create mode 100644 _sources/index.rst.txt create mode 100644 _sources/xc9500/bitstream-xc9500.rst.txt create mode 100644 _sources/xc9500/bitstream-xc9500xl.rst.txt create mode 100644 _sources/xc9500/index.rst.txt create mode 100644 _sources/xc9500/intro.rst.txt create mode 100644 _sources/xc9500/jtag.rst.txt create mode 100644 _sources/xc9500/structure.rst.txt create mode 100644 _static/alabaster.css create mode 100644 _static/basic.css create mode 100644 _static/custom.css create mode 100644 _static/doctools.js create mode 100644 _static/documentation_options.js create mode 100644 _static/file.png create mode 100644 _static/language_data.js create mode 100644 _static/minus.png create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/searchtools.js create mode 100644 _static/sphinx_highlight.js create mode 100644 genindex.html create mode 100644 index.html create mode 100644 objects.inv create mode 100644 search.html create mode 100644 searchindex.js create mode 100644 xc9500/bitstream-xc9500.html create mode 100644 xc9500/bitstream-xc9500xl.html create mode 100644 xc9500/index.html create mode 100644 xc9500/intro.html create mode 100644 xc9500/jtag.html create mode 100644 xc9500/structure.html diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..2e68ce94 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 117c0c5490c7a38a33b72ed05e1d75dd +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..b13b067353570199a9f2388185a9ad26720ebb1b GIT binary patch literal 556475 zcmeFa37i~9c{i;4SRJd=wtPS%kXgyv)gHQ$9m}$8grt?QBrGsuG`l;yGo#s=^&C13 zCMF!Q%p?%J90r>+fPp0BgdBwXFktQ+Z%9a9;DZE0xbKjc?>VZvx~jWtduncAIn*Z`yvu4l2|C+06Q~5&qd|$47wot8iM$l-~3#GoyRJNWk6-K6;i!#UR z)uZrj`d+wk_Lk}9ynJOcH{D!NZIsJ7xN+XOO7+Zivumna9IZ@_6w0~j{PN~Jpk0Gr znGxh-y1BSd3|5=2Pu~I!wdyF2n_t|M@5(R9FU>E@FNgoTxplNs9xqHxH2|TQbFhIef7#%WjfnjI906_ zbEBZB?xXxKZ=Yblxp=fPb)j0A$V2Or!T!Oa&EBoq@>mww&Nk}#3P?R)Tv&zVGKKPJ zsWFzz;FsF;-Oc6o+~ia#ThG-#=i!mugIO}J3!I(T$Q-&$**WGKAvw(j@0_b zK=q6JZafCsuT*o>xn@_sK3U4t^EuT0;%q59lC8mwU}kEl)wA`&s6W{9+*D&EGg_-< z#tS7-4UE5>`e~Pz(WPRb)3S1767-%KuT&?qb;8QR8Yl_$2ofCQe|a0wu+XgmoHZBT zRG8?aOY`g5krG^4bR7TErLNJ+Sgv=ZR2fBt94gf6h4KWpG@1*}W=jpST2KD*`6o2z z0(hr~e|tLr#C%WwX81>QrLa&YV2xRbKhOmA+>pOIe+YXn1Pq|9r}GE-)`itvDVMDQ z62*o2V43U%|LbDv>OFrF>tG5}Q4;X?jio6d6k zWvqmZyqC0H&Z3Dfd3Lo@so&Z6Y}t0_vjLKK3c}t*4$OYOp2?O#Nq#Z2;wZwJ}-;>y9Ch(>1=MTilT=gHgeZ0K-Oo zymx1BtuVpEj>X~W<5F<=*S$1p;R8c0l0hFuY z#_~Co?`}aAJ4{x_8ekICvfluca5PgH!RefVo2muX^w@Ayrj`etGkrwzSYkS4zh z?w$nvSL)?TJ(sEG#&f_2Drzb_nvzVZOfXOfEN-IhU=L!6-g6D{GCZ zDFTV#a!L$#38;|30TXL-vQh>-H zQWnM*c3M6KI?Prt0N_Zo%{fyr^=L*dEkn2g1yQ`39v(()ui$F|k9{Y!K*Q3>YbJCith1Ua5 z2mi{9<)$Fq9h^<$<)4(_!vkM6nLS^agm%DtIg8UHQ-WZZDdox&&|k3E4SqA90Wu@G zD$Z^>#!9-LyB$<5y{oumiM#`xiPT_My;RG9Q!9*Lke8O=rBT3OwO*5hbv0@@$^^!H zNv#H&uixGP@cQ;x6}Xnk3U5C5_8Y-Hl2O(K+eKi)aN5&cEWH=Gzd6M$gsw#t(ZS(@ zHX)S&8-ed2N0Dm?O)-Wu5CiksTA`N9Kr9^1{{80b7g5GDt2qy^lWXjv9vm6-U(A0I?^>m8|5?Q$~ka3 z)PV=DjZ$pSe~T|JqPrS}v1zzMR${(KG2fZq7`!wAy>jxB;10kkBR_X#E~Y9tS4B!d z4f$>P?K~puOy(t8rzWccT&b8FbD1b}j+Y_n5|iKWT7$3+8onnuKDe0-xCWTg5(R5W zPMBJJJ#(%whLdj=-^J39vjrD`&bm;>NhdVN%`gcd0mEQ-H%qdDXhKRjS}l+_MIDl= zxdoC*a9$$~NUi*qm2}U!Y5_A83^EYIyCBmm+yR}lB_1$8kRKGzm{KPKolLs8VO5|Z zfIN1r+(yW2K1RS@W}Th~zO;eygE9c&i$!(^jMOvrR&L~cQ42(iX?Sqq6>t{B&{DcG zo;_Otm57V^9r>Nqn%|Y*&Hot6Z{_~o)E^vmHLFX#mPteUk!ehgLEa02oN_A~hV#rC zpmZb)^B*D`UFMr0ri0Ea}`H+p55F6^c%(5WI zszXA>q**>>1?EY)mdjR0^O&Fp7{W;??-eFvhHx;Wfyog=Dqj|Axs3V2w1>xmdnYkM zONM=zK?e@a;!Z{gP8iGtrD<5rl}3H4feDw)2j^2hD8%E502v14O_2FO>hD{L4bRaQ z!=%VTn{)a+aWfAfc=bK7P=Sz?6c+UEq&OZ{N;wJ{0nG7(97}{*Fr^<8?j~q8mK6gM zrW?`{SCZ~<9Yf0)iuvV=%<+m#UZ`m?BR_-g-#&V^?*=k=oSKm^en%pA#UO%)YSKGD)jL|zeS?V1{ z-k`J48s#2H(R4h^;1rULmjJI*S&aqG73QXkbLV$h}v|ix9UfqRt?K z(B*!U@-Fpk6|Q2|!m;I2*#{O;;9SMx3)lARZaQ)3kT<;d@P2R4{=<6@9J+q*jW^!1 z|JbqXrg`MG>Q-Jf!rDGN2{n{Mdxvj6vG-=U@6e&^ONG8lbwb{=6w3kUVYW7FIx9?H{-ug8f`*9Cu^ z3;=nArbZGiN+HcT&w8B1xEI$C7h1G*+{gs4R2{1@^}v-+LcEu( z-h6%a{j|8?&Wm9xiHro00aFoHwZW+f-pb72P>ns=gR}kFw+v}0Obg6jj#nqMXCSom zB*FR;{Hp@-SaexkgNakhaoCo5Q*qFbH7mgn6w2cjEa_0rDE)=WBrI@xia&$*03$@W)3BoOyuBLp*Dmhq$%UB`X!ZT2|L{E5M0;QhjB3X73 zXk05vltIv3JzFTjByUI^T_#&cs}-n)`IQUcDdsb_QHrfYkjyZ)NfA_gp@ zF6G=gR17rFYm}i7!tr4>wPDH0&s2~!t;LWtA}tpBS_Z?bwewJ}g~Cd`?yumxM>B=7 z4AgsR?E%99T&V9VEZjoQ5Y@I~G{gD!ncM}KI%8z$=0Zq&p$LHj(Z4F=z&rS^5?sKT zTEZ}~7*|?_GNyUWMOYhwngy)Ymx)?2mJX{>@LO8XS7DB4sJ02dj#zr^C?GUJx#QB& zsVUBw!^I>bw30eRioFJ#Vg-L3wkG0X1@?sWtT6#HRL;OsRL&yRKq$k#4%yaI%%08i z0x{Vr>!2!HmaE&)?wiJ5mW{ zwf|M#2U*r|@yT;$&BEMdjcOjtoyAfb?FY=ym3zTY_}wm3-Nfj!Y}1@Qpt>zr-FVsQ z69|lRW(2F;V^D@x>5kyOSCLwwNWl$MB#a_f%}ru0S8u;m-OI&L8GSDLB-W`elZ7(m zc-2Y2+UIu)=&lCY56{v3Nxwb7BkvwSA<1v-RwIbj{Tef2)ipWNE&y@og;m&1a(+$zlKh$cfl*n`P9o7&O;0ndsl&5u)5d0H0Bma#YBt0a|Qdh z;!?4motS=Ua|K}=;D#v^6`bz`o)#1EY2&MSKX|+56){6_m)ByKt75vGFL9^WU?<5? zfc^vebx;ELe>Gn34sgqtUyqm9h|9iQ-1a(XYk){X6qJf)A&5j`6yF3LipXv8_wfT+ zD!v&%kcr}3@B@b}z7;=kq~e44fpm*+gAYJX{s<~)g#ZF4akakD>4S5dmzfvyuy+a@ zb#;W-rDkJ66f~hto>TCt!7+q`i~XYq@-it6X{|G8shEvytTtM)$T59zPIIkso#W^9 z!Fi$aal;dCFxjfr$KY~)Jv1#~TGI#jG@5HfIKu)l%popYPG4-U(yl|j3wEJk`&LK; z>$>J5&<)m=c~fOM)hi$s6#H(?IS_4|%cw368BCTpSLfkG2W019Ckawe+);$>2GH@v z=Gsx{bq2OqAS2E|f{NRGkObV_Tsj3if#{(q)-|E*$0a4WTsU`YZFaV*E4fs}c; zxwJYy8o2jrc`sCRvrrrvg+*ImAy*$K0sy=%=y#D4-ltJoUMOpI!TjybdWdKR5sUi_K-SkO(Nwx;;j&LJe*43V z7tnONXW`#{tBbzjl)7i(3;t#aeZy&W&%%?R;cqy#?pe6!WlO0Ir`J6T&po(|zTp(R zXJO+>-T1B1gpF`4!$1uc_pF;spy*KIMIn9@o5WD1se|L?oj1S{G|k1?cJK5H@hHtA zvDrR0UHm7YUi=sMpoV2og2c=|TRNA$P@8@UoJz>x)+v@h(IAix z{{=kf4;H@-e_*v;{4V@$&gYa!>l3bhiF^2#dB-8KKvjj#^t^DIk3KEnegEm=PjHCE zC@Kq3{7<~FK(IdC#Q6t%?2VCZvn#M>L#H^mK+7;#YKij~AlrNnbnvf5uol|{MY1|R@i%djAlyYHagEN|X5 z7w^OU2gpr!!zy>8R2c!MupnO;gJ}c*S|(`u7Z&lN99+V|SL(W*2}{aYkR| zD8*}lg+_5Dd=@Xm541#a6@HLb=drog!Ue!Yv{stkLYKYgs*v+Stv_3gQj{2GH4={l zff^bx$o9mgJ(f9jb2e8U;5x1cN7Ov3Xu_h5XHxMOXyK?1JRf-UYk`kioJ^4dG#5j8 zV>cg(fl@XEpj`EAZd%Coq-1g(Tnd8ifxetk5;mKwt_}TX2oq|*7Th3CZWiWn%fb{7 zBEN^=qecFgNASOLleZh@`|i_lD1#>EX`TIu_8|ASJ#yT4+qjoUgyOhY?LqDfj~w?a zBDn9Cy65dbgZEHtkn?ko9Oo+=BRRu;G`qz@t5>X8!Eb1O*6-k{4w~y_T&Y4r{CMaxGU zRY(WqY7wJ@yutyu_#W)G65}$Z3gd8~8Js_4$P1pvCr14^g+X+Py`%n^pM@QM{gbzx~WH$}BP+%ba{NAc4j5M;P3 zp|}qUq7}Q!d*@S$6NXtXmif>F*Ucz3Cg^au0#4c9UHk+Pft347JqypkDQVaZft4DR z1!0eK0Ww3?wYY8k=2b?EL8AD_FlU;}nQrJ1K=Vqy!MM4(!Y`kK67Y1`bn)}Z_{rvK z*b9L|Hy*=NnelM`QV>(EnIJuRFLW=y4?dd9#u}4QnU!lS&=6gKLIc&9&@|n2g`kTI z5Orw^cKhJ~H-t0j1*fv%gcP18Qg@P>;RM6kLao3U>xTUru3~W|1#Vm@PlxavSqjYK zQD@%62Fr{6Z~y33@iV~p-OVMCj`-^rfD~?%$peMFJ2icH#S@Dkh0epp52L&vL3!8W z;*C~80A>GJIb@!2y>~K` zsRFyT#VkiLHiKJPAm3jYmdbEr@);#q*FC7N(7TLx%(c8!px;(}i!? zgVOU_bD8fHD3=F%%SJ_A1J}MZ!ZKXe%YL{`(_9(6!u{YXXnt~}Qu5CjQ`a@dMZfoA zjpAZCD&4e7qYwT9wsQbQYfW0B1(IQyK%=lA09%@C&4v5K^?N~Ew0c|)D*$u}oVxcTIkmV7ZK$f!l&VlZQN0+u8A1W!QE%`Y4&dsz?Xzen?Wvj?SV?;M=c z&3S%N)+^LJI1W^(d*Bl*-g>BQWozsEJa0eL4ZNFf=zw`+1=qehZejkeg&sjj{nc?Wmv1LDc@{8&7@CAbB=~*Dptl~+)c6pBFTwVK zZQgo5a0Fet2xR;<*lD|0sd_sJq`LtNcs!}*_4n>Xboe82`(^}PDF@KvUb}h+wrbtB z6Bz?IA4nnxAO$4}03|F7^bsRtw?|SQ4I)qIJVX|;&zun=_n>OwnJ14GkC>oIEbK_O zfemyhWK_VH!=VK{pMv|q9t5pPux{;4ja)+)cm?)egJeRaB&{s5pcAq?i(ebb zNRKP}XxAfl|AG__ZlZxxM>G`gwzi>iT~R)q(S-m&O^Do1t{N|&y~@=Kz0Om z)iI1JxL@L(Eo8l?9N&90XGB^qM42vZwZjt*Ubg0qT!3oB<}OZbF#2qVD1+2e>)IHdLk{5E&1Qg*h*}@nnL-bFh8J+9Of+kpuB0md=0!UW(VCv)gr(H#Py;fPXc3@YoviZM;}N3|2sjt1l5&ck?342)@G zY{^Iib_w~R3O%X!7f)gfZ81J~k%6OPlX}1A8UpFSQ18I@-ISuy^HUN7MqXFUp}@f% zh3MNgB~5f*N$XfiqcD=wiY$vP(*Db{!ps)^^cR+U#S!Qb%yh2@{dog}yE*znm>BEo z>h=0}L(G7P1#yknGH`8Rw;nDyEzfDzltF-+W*GW^~+dHqmt5|(+NlSg^E{eWoQq=ZGnhV%xPB&-w%5BPLqR7TdSD2WQ z-O2!>$fHag;Zpo*7&83RF~`(h2YHs==vBy7Z|fZZTVuK_E)4ZZ)?(YSs z#Ook$16-C+2>Y4K;>MJ>u)B%xrs3zaoyX5(89xsbep>K4%XJ0%;+Zbzt0+Ry<(M~W z0)MUZ0zZxg{xS*NmcRK|)|u&#IgA@fiq+50P5ngQu4(BPo!8QO*3wTqrlqxnpSXz? z^2w|fqr0zE^2pI$G{vo+4`58M_#9Q$dps+y8%Am~ePVdE;x3CHMqqpdZN^7#qMWh7 zKTr5psJG{g3+NcN5(npOhDY8>9$A(udU$i$&!sm?hdk7~L-X4KU|5{Pv1q@28+(LFb)}oTi*Zomb8iSvgN8<+SC}_p^RY zm%fa&C_xviuB@pp<33F#UbT%zzwc=V6Ic|Y+b^)zWZ^?1DLO2oIqMk5E%UL3}xqgl{@J2aMImEL%RN~8G zwhsH9V(%HtaHmfXoIc&xh4+N+pyqyP_B?p;A8c%#gOVf`=3wItALq8g*2J-9E{-l|@iNyc*Te32Zavlv8*~pG+knRqOBbN7NryCH=b!49r%%J6 zk`BV1P7)Cpz>?U%7dy1a_TRGa$c_7H8RA#Gdw6ls+ma^4IZZLwUvHTx;=HSP$kC`> z%_oiOlM)^<)Mnw^EyNw%?t@5;kq z|3=&$g9opmcri5vn`Js|qdI6}ej{CTs3SIC4--}e-GhT+r+#u7?A{$<$Ew7FZ4=m# zK@VJ$8#v;m3vSKS3h<=;1uXT#+iKu3By_Ieo8jy zj>}GZBmjjCEbAjN=DJJlH6b^Z(pea|2G5y*0QANH4_=Hk+JKjwKsc%G_IHGYtH1MC zsvO-d{3L8$Ra>Jil11{}gJ$d?E$b+q3yRn2&t8z~;`^7#E=3PyTt<(3etm4MOK;O| zO1@_+t3#iqpct~fGyzN~L zcz>(bcnxgmZ}PUn+i~GGJcl6f)9Gx2!%1|rSklX08of>4z)tEEq=P-Qn>NYw40vFC ze5BSjJ|d|ZOkCsP%|5X%I%FXG%DY13;6&xPSHxFKR5JK{a}Ro`jk~)%_-}l~yOwjt zEnDCV(c%Vl2pga+aIG-TUH4G&S@FT7kQ`_-Ku^;cQKcaT<>*#52H8oG##=?DT5-J7 zr;5#(OpCS+o@&CgemWgWl6wUdG!p&@h!E-qdfBdZ(MC~C{K6EkN9zmf-LuCV81kN@ zUGAr=gT_@<9`xR3T<#G(0VCTsVh59&>;MJ)js7qjH={b}t1iEkU5A!`pR7q!}bCarp1|CpF3e|p64*ZX`<)GdN6(y41$v#FM8KqhoHRL>pwqE zRQT;a=neLmℑ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 z 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 P8e=0ee-eYO_pkW><8&Z0 literal 0 HcmV?d00001 diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b38d1fc1c3e8af24d5d0c072eaca11ea5a4f4fcd GIT binary patch literal 3430 zcmbVPZEGAi5O!>z@6Ns#pYuW?aqCjjByH>qr7f)?PzV%?sVSwTg%UQpUENCYuC$f3 z_W47gg{IV?PmTHq0{K1tOMSGvxA)?-9}+mS8jWT~qi3EO|JwNb=k7}J&-Qi3xR@M} zC=xQF+Syhl!#t(JxR>tUZ|=FfYuk#PX_>2#I=cdmknto^RJbS3_Pn~`i9V>#H#H3n zm!dw-8f=3#pSZiMZ5xK0gwAc*{&z|~!->5|G97V2omYkC`VVyCL%6K)!j(~NWCSr7 z#|E|?)IqZ~yHUk@Y}XTS@i-q5yGe{ue3Tp9(cfu}N7~2V3=^U?g!pah# z5eZKe9ebVJHVujWmScT(lXciFw#Iht=R+n_I#jt3R1MFhIvHl_Sy2sS@VkfKP1`8E z;D$(&;>Ep=ZD$gG`PqX9Wd!aIM{I|SFv%l2=1HN$z9P1jl1W4}!`#soWQb(NgWC2Z zDGaRXLuc3HM2_5r-C#V50EG+Ntqj$ImdMi)RWx!(D|WMZc`Ze94&6;4Y8Fzl3EO4&k(_npc!>97^B1-KDj)l2iewp8j?CZPpWmOojkf~`AjeJQcmdh0VRya} z5f7=}BO=-}WaN`jK=8&Jw@UEA_)mH%sQCzNdy*!HIwQVfTA8Ans#EHGV2>9AJL({^ zAIm!P(LB8Lua4%@&O=v6!~QQCHfHggT=y1S4?fyE1jrAc##9u@c{=s{hMn5+>DxH& zzu9prqyKO`+o>J@{x*)c7aaGeH`bJ>kk$9SB(I(R^)^li`H0r=wf(H*yZwqA0Ntu| z>#e=nR#naZ^)>;VwUTX$$^dOFR>cAUryR)c+iOMOL@51xrNEZagMQj(VCl64pPqZNQ5v zVx)3dLRk{ga`vl9)YMHA9t1c=&@I35y;jZD?BMOBTLqk!LLej>=gw$Wk{b_q#WVs2b2z?dA z&bD(i-v44>b9~=g+zhBvQUwf@m4N)v@Nl=#pjXP=ELv$4R-D~k+F3He{;|E%=q!Ng z(OZifODFBNzX0H+8S;}9jMq(wh;tHCq&orwuA)EKtBQtFMFIK>Mf($>Z%M~?Ba~u{ zJ0cxC0zA=&CXQ{`9?6XiW+J=Ffv9ejr&&;=4p}V(9BoMnl6ZstLQ-Jfzx_;hlg$Yl&ao=v=vAv9D0g{3?D$u3iq~j$c zg4lg!*msyQnLZp2A=U@kxnWWqNEHvAz3w%O0H7Hdn&Np((U54ifBV6w$Y)QD!zJ@x zGBf|-)I2Jcc)Xrab-<|^7d}w)LuS$h&f4gmD51#D3@y70K&C-moAm{PvL{~HZGA2b znFNf-EWr=pT~DOPeMhGRRrX7cqSi>%)nZ*PgG7d;98>IW$Oz)W!61Le zjNvEKV(6$y022x%T#SK%DJ$%Fp3wPdNsp%{3_dU>$zaUUYnE5r{ kyL4C+$AWmP78g&pRgJoUNbLV`*o-{4RW#sxbUr%x7xmdXbpQYW literal 0 HcmV?d00001 diff --git a/.doctrees/xc9500/bitstream-xc9500.doctree b/.doctrees/xc9500/bitstream-xc9500.doctree new file mode 100644 index 0000000000000000000000000000000000000000..1a0aefd774a7e1e284300251b89baa76a316c2ae GIT binary patch literal 84099 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 C5L4*@ literal 0 HcmV?d00001 diff --git a/.doctrees/xc9500/index.doctree b/.doctrees/xc9500/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e912e81499fe35b9cfa48c7052e2bf4cb37a6034 GIT binary patch literal 2959 zcmaJ@?Q0xG7*CVj%1hF z4+RA)2F6bv|6hNzySKRu=)rP3&ph+I{(jHSZ>@j+*jg!nerO8Dpl+!5;>nZ!d)5DoADg%5A)dma^t}1K#2F2Bzg7L$y{-{7?bow z(@E5Ee#4S!+zM>S?yw%a%huSQ|9Zq!PDk2FN%iPV>61~RU#BV`BZ9?O1ZqaJG*)87 zWkzR*+8~Dyk5=6n73kndp`6SXDpwVit-!TPt)`1rt@l1cO6)#r_%WUbcpl<;jOUK; zEjmNKD4FJEmXD4XHmz3S&v5LwYjtC_ORdwil)hg}$J}CrlKh|&l$#&?$L36w+gtVa zYZMLw>U&(K!ew;AMHL78hJDMvW8bqMsPE)tmeInpaI}i%kfKDG?>(Hv#d>8kEbq7k2E}r|dJf$M(^X zb+mT`=&;4&`eEIJgELKvg6cpP>mAP@T*4yS0s3fT!r!WjQI~Hf<}atPQ}@o_u5|YA zRsS>5yhW|Lv(eKgJgrp#EF%VlmZMz^t)T_m_cyF2(g+f3n-p42H8mA2T2@&is;bpG zWf5KUcg+t{rz7c-hGM{=fUqzl(JG;y0Ce4&G+N9 z0xXi*MCm+0G60l$k$`b=2pX8YQ%R_xr6f7ymL>B60gv^8dSZY+nifjiM9@=;qOJN( zMnto0`5ijrsFfwwnYmKSw=z0*Q@9(P5iL9=D7fR|yYk3d4f_XUwtN2V0z&ahquZ~b*mQ>C*6e5V+NGL3WT*tb(9C&&@y z;2GeFK`{%g?FYnJm0XJaDhHzanahi$K^>}E3OL4vmPAB@!%|XWKKA}nR2b?qmCW*p zr)@ebl%dJu$r2)|O-{Mt6+VYa#tj*Zm`EMv#+(gcRu9P-;J>66jP`4_WIpWtd+`lU z4Amw5sEpP!^m_}F3Ei%iz~@e+6ksE#K%w9{x8bMlhkj7dB0*6w-eg)9tQRF?g4iQ7 z{4Hi}VV;gg5Szo|+%hE(m7b1*zZo^l0HB#znxj1y?dU*$@ZibksOLaW(ktepN^MMTJj-!|vcl3Bv| zlnFcl@48SC_dSynu9_QDDytMEEAK^unySA>mrcgbRR?zKF$yJR1; zRoghsZ(g-k@8I)~iIL(;1y}^Xl`0`nSmc0D#>TT+{tn5%4L<|@xKx5ixCR>ZyK>kJ gjwSI{BQ9IERbN2>k!kGKW)^2#JqF@8+KmtY1=d-H_5c6? literal 0 HcmV?d00001 diff --git a/.doctrees/xc9500/intro.doctree b/.doctrees/xc9500/intro.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a06020dd43ec240e055d3f7fad3f659c9c4f0947 GIT binary patch literal 58267 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 Ryemu6V>y$MY2Ho`{~w@0ZJ7W7 literal 0 HcmV?d00001 diff --git a/.doctrees/xc9500/jtag.doctree b/.doctrees/xc9500/jtag.doctree new file mode 100644 index 0000000000000000000000000000000000000000..75fb0240197f981091ad6289e549a9bbe8382875 GIT binary patch literal 46966 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 F{{gG#O_u-w literal 0 HcmV?d00001 diff --git a/.doctrees/xc9500/structure.doctree b/.doctrees/xc9500/structure.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8063ded9f3518c9a988b3ca6f263dfe06bfb7e2a GIT binary patch literal 131115 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 13 & 0xf + assert fb < device.num_fbs + if addr & (1 << 12): + row = addr >> 5 & 0x7f + assert row < 72 + col_hi = addr >> 3 & 3 + assert col_hi < 3 + col_lo = addr & 7 + assert col_lo < 5 + column = col_hi * 5 + col_lo + if column < 9: + cfuse = column * 8 + bit + else: + cfuse = 8 * 8 + (column - 9) * 6 + bit + return fb * fb_bits + row * main_row_bits + cfuse + else: + subarea = addr >> 8 & 0xf + assert subarea < device.num_fbs + row = addr >> 3 & 0x1f + assert row < 18 + column = addr & 7 + assert column < 5 + if column == 0: + cfuse = bit + else: + cfuse = 8 + (column - 1) * 7 + bit + return fb * fb_bits + main_area_bits + subarea * uim_subarea_bits + row * uim_row_bits + cfuse + + +Fuses — product terms +===================== + +The product term masks are stored in bits 0-5 of every column and every row of the main area. +The formulas are as follows: + +1. ``FB[i].MC[j].PT[k].IM[l].P`` is stored at: + + - row: ``l * 2`` + - column: ``k + (j % 3) * 5`` + - bit: ``j // 3`` + +2. ``FB[i].MC[j].PT[k].IM[l].N`` is stored at: + + - row: ``l * 2`` + - column: ``k + (j % 3) * 5`` + - bit: ``j // 3`` + + +Fuses — macrocells +================== + +Per-MC config fuses (that are not product term masks) are stored in bits 6-7 of +columns 0-8 of rows 12-54 of the main area. The formulas are as follows: + +- row: corresponds to fuse function +- column: ``mc_idx % 9`` +- bit: ``6 + mc_idx // 9`` + +The row is: + +- 12: ``PT[0].ALLOC`` bit 0 +- 13: ``PT[0].ALLOC`` bit 1 +- 14: ``PT[1].ALLOC`` bit 0 +- 15: ``PT[1].ALLOC`` bit 1 +- 16: ``PT[2].ALLOC`` bit 0 +- 17: ``PT[2].ALLOC`` bit 1 +- 18: ``PT[3].ALLOC`` bit 0 +- 19: ``PT[3].ALLOC`` bit 1 +- 20: ``PT[4].ALLOC`` bit 0 +- 21: ``PT[5].ALLOC`` bit 1 +- 22: ``INV`` +- 23: ``IMPORT_UP_ALLOC`` +- 24: ``IMPORT_DOWN_ALLOC`` +- 25: ``EXPORT_DIR`` +- 26: ``SUM_HP`` +- 27: ``IOB_OE_MUX`` bit 0 +- 28: ``IOB_OE_MUX`` bit 1 +- 29: ``OE_MUX`` bit 0 +- 30: ``OE_MUX`` bit 1 +- 31: ``OE_MUX`` bit 2 +- 32-34: unused? +- 35: ``OUT_MUX`` +- 36: ``CLK_MUX`` bit 0 +- 37: ``CLK_MUX`` bit 1 +- 38-39: unused +- 40: ``REG_MODE`` +- 41: ``RST_MUX`` +- 42: ``SET_MUX`` +- 43: ``INIT`` +- 44: ``UIM_OE_MUX`` bit 0 +- 45: ``UIM_OE_MUX`` bit 1 +- 46: ``UIM_OUT_INV`` +- 47: unused +- 48: ``GND`` +- 49: ``SLEW`` +- 50: ``PT[0].HP`` +- 51: ``PT[1].HP`` +- 52: ``PT[2].HP`` +- 53: ``PT[3].HP`` +- 54: ``PT[4].HP`` + +The fuse combination assignments are: + +- ``PT[*].ALLOC``: + + - ``11``: ``NONE`` + - ``10``: ``OR_MAIN`` + - ``01``: ``OR_EXPORT`` + - ``00``: ``SPECIAL`` + +- ``IMPORT_*_ALLOC``: + + - ``1``: ``OR_EXPORT`` + - ``0``: ``OR_MAIN`` + +- ``EXPORT_DIR``: + + - ``1``: ``UP`` + - ``0``: ``DOWN`` + +- ``IOB_OE_MUX``: + + - ``11``: ``GND`` + - ``10``: ``OE_MUX`` + - ``01``: ``VCC`` + +- ``OUT_MUX``: + + - ``1``: ``COMB`` + - ``0``: ``FF`` + +- ``OE_MUX``: + + - ``111``: ``PT`` + - ``110``: ``FOE0`` + - ``101``: ``FOE1`` + - ``100``: ``FOE2`` + - ``011``: ``FOE3`` + +- ``CLK_MUX``: + + - ``11``: ``FCLK1`` + - ``10``: ``FCLK2`` + - ``01``: ``FCLK0`` + - ``00``: ``PT`` + +- ``REG_MODE``: + + - ``1``: ``DFF`` + - ``0``: ``TFF`` + +- ``RST_MUX``, ``SET_MUX``: + + - ``1``: ``PT`` + - ``0``: ``FSR`` + +- ``UIM_OE_MUX``: + + - ``11``: ``OE_MUX`` + - ``10``: ``GND`` + - ``01``: ``VCC`` + +- ``SLEW``: + + - ``1``: ``SLOW`` + - ``0``: ``FAST`` + +- everything else: + + - ``1``: false + - ``0``: true + + +Fuses — FB inputs +================= + +The FB input mux configuraton is stored in rows 55-66, columns 0-8, bits 6-7. +The exact bit assignments are irregular and should be obtained from the database. + + +Fuses — per-FB bits and globals +=============================== + +Per-FB bits are stored in rows 67-68, columns 0-8, bits 6-7. The bits are (row, column, bit): + +- (67, 0, 6): ``ENABLE`` +- (67, 1, 6): ``EXPORT_ENABLE`` +- (68, 6, 6): ``PULLUP_DISABLE`` + +Global bits are stored in rows (0, 3, 4, 6, 7), columns 0-8, bits 6-7 of FB 0. The bits are (row, column, bit): + +- (0, 1, 6): ``FSR_INV`` +- (0, 2, 6): ``FCLK[0].INV`` +- (0, 3, 6): ``FCLK[1].INV`` +- (0, 4, 6): ``FCLK[2].INV`` +- (0, 5, 6): ``FOE[0].INV`` +- (0, 6, 6): ``FOE[1].INV`` +- (0, 7, 6): ``FOE[2].INV`` +- (0, 8, 6): ``FOE[3].INV`` +- (3, 2, 6): ``FCLK[0].MUX`` bit 0 +- (3, 3, 6): ``FCLK[1].MUX`` bit 0 +- (3, 4, 6): ``FCLK[2].MUX`` bit 0 +- (3, 5, 6): ``FOE[0].MUX`` bit 0 +- (3, 6, 6): ``FOE[1].MUX`` bit 0 +- (3, 7, 6): ``FOE[2].MUX`` bit 0 +- (3, 8, 6): ``FOE[3].MUX`` bit 0 +- (4, 2, 6): ``FCLK[0].MUX`` bit 1 +- (4, 3, 6): ``FCLK[1].MUX`` bit 1 +- (4, 4, 6): ``FCLK[2].MUX`` bit 1 +- (4, 5, 6): ``FOE[0].MUX`` bit 1 +- (4, 6, 6): ``FOE[1].MUX`` bit 1 +- (4, 7, 6): ``FOE[2].MUX`` bit 1 +- (4, 8, 6): ``FOE[3].MUX`` bit 1 +- (6, i, j) for i < 8, j in (6, 7): ``USERCODE`` bit ``16 + (7 - i) * 2 + (j - 6)`` +- (7, i, j) for i < 8, j in (6, 7): ``USERCODE`` bit ``(7 - i) * 2 + (j - 6)`` + +The fuse combination assignments are: + +- ``FCLK[0].MUX``: + + - ``11``: ``NONE`` + - ``10``: ``GCLK[1]`` + - ``01``: ``GCLK[0]`` + +- ``FCLK[1].MUX``: + + - ``11``: ``NONE`` + - ``10``: ``GCLK[2]`` + - ``01``: ``GCLK[1]`` + +- ``FCLK[2].MUX``: + + - ``11``: ``NONE`` + - ``10``: ``GCLK[0]`` + - ``01``: ``GCLK[2]`` + +- ``FOE[0].MUX`` (small device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[1]`` + - ``01``: ``GOE[0]`` + +- ``FOE[1].MUX`` (small device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[0]`` + - ``01``: ``GOE[1]`` + +- ``FOE[0].MUX`` (large device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[1]`` + - ``01``: ``GOE[0]`` + +- ``FOE[1].MUX`` (large device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[2]`` + - ``01``: ``GOE[1]`` + +- ``FOE[2].MUX`` (large device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[3]`` + - ``01``: ``GOE[2]`` + +- ``FOE[3].MUX`` (large device): + + - ``11``: ``NONE`` + - ``10``: ``GOE[0]`` + - ``01``: ``GOE[3]`` + +- ``USERCODE``: each bit stored inverted + +- everything else: + + - ``1``: false + - ``0``: true + + +Fuses — input buffer enable +=========================== + +On XC95288, the ``IBUF_ENABLE`` fuses are stored in rows (1, 2, 5, 8, 9), +columns 0-8, bits 6-7 of FBs (0, 1, 14, 15) in an irregular manner. Each +fuse is duplicated twice: once in FBs (0, 1) and once in FBs (14, 15). +The purpose of this duplication is unknown. Consult the database for exact +bit assignments. + + +Fuses — protection bits +======================= + +The protection bits are stored as follows (row, column, bit) in every FB: + +- (11, 3, 6): ``READ_PROT_A`` +- (68, 3, 6): ``READ_PROT_B`` +- (68, 0, 6): ``WRITE_PROT`` + + +Fuses — UIM wire-AND +==================== + +The ``FB[i].IM[j].UIM.FB[k].MC[l]`` fuse is stored at: + + - subarea: ``k`` + - row: ``l`` + - column: ``j % 5`` + - bit: ``j // 5`` diff --git a/_sources/xc9500/bitstream-xc9500xl.rst.txt b/_sources/xc9500/bitstream-xc9500xl.rst.txt new file mode 100644 index 00000000..fb8d18d4 --- /dev/null +++ b/_sources/xc9500/bitstream-xc9500xl.rst.txt @@ -0,0 +1,272 @@ +Bitstream structure — XC9500XL/XV +################################# + +The main differences from XC9500 are: + +1. The UIM wire-AND area is completely gone, only the main areas exist. +2. The main area has 108 rows per FB instead of 72. +3. Unprogrammed fuse state is ``0``, programmed fuse state is ``1``. + Thus, the sense of every bitstream bit is inverted from the XC9500 version. +4. While in XC9500 all areas are loaded sequentially, in XC9500XL/XV the areas + are loaded in parallel. Thus, the JTAG unit is not a byte, but a word of + size ``8 * num_fbs``. Likewise, the bytes for each FB are interleaved + in the JED format. + +On a high level, the whole bitstream is split into "areas". Each FB +of the device corresponds to one area. + +Each area is made of 108 "rows". Each row is made of 15 "columns". +Each column is made of 6 or 8 bits: columns 0-8 are made of 8 bits, while +columns 9-14 are made of 6 bits. + +The low 6 bits of every column are used to store product term masks, and +the high 2 bits of columns 0-8 are used to store everything else. + +When programmed or read via JTAG, the bitstream is transmitted as words. +Each word is 8 bits per FB. Each word of the bitstream has its address. +Not all addresses are valid, and valid addresses are not contiguous. +Address is 12 bits long, and is split to several fields: + +- bits 5-11: row +- bits 3-4: column / 5 +- bits 0-2: column % 5 + +The unprogrammed state of a bit on XC9500XL/XV is ``0``. +The programmed state is ``1``. Thus, whenever a boolean fuse is mentioned +in the documentation, the "true" value is actually represented as ``1`` +in the bitstream. + + +JED format mapping +================== + +In the JED format, all fuses of the device are simply concatenated in order, +skipping over invalid addresses. The bytes are *not* padded to 8 bits, but +have their native size. Thus, converting from JED fuse index to device +address involves some complex calculations:: + + row_bits = (8 * 9 + 6 * 6) * device.num_fbs + total_bits = row_bits * 108 + + def jed_to_jtag(fuse): + row = fuse // row_bits + fuse %= row_bits + if fuse < 8 * 9 * device.num_fbs: + column = fuse // (8 * device.num_fbs) + fuse %= (8 * device.num_fbs) + fb = fuse // 8 + bit = fuse % 8 + else: + fuse -= 8 * 9 * device.num_fbs + column = 9 + fuse // (6 * device.num_fbs) + fuse %= (6 * device.num_fbs) + fb = fuse // 6 + bit = fuse % 6 + return ( + row << 5 | + (column // 5) << 3 | + (column % 5) + ), (fb * 8 + bit) + + def jtag_to_jed(addr, bit): + fb = bit // 8 + bit %= 8 + row = addr >> 5 & 0x7f + assert row < 108 + col_hi = addr >> 3 & 3 + assert col_hi < 3 + col_lo = addr & 7 + assert col_lo < 5 + column = col_hi * 5 + col_lo + if column < 9: + cfuse = column * 8 * device.num_fbs + fb * 8 + bit + else: + cfuse = 8 * 8 + (column - 9) * 6 * device.num_fbs + fb * 6 + bit + return row * row_bits + cfuse + + +Fuses — product terms +===================== + +The product term masks are stored in bits 0-5 of every column and every row of the main area. +The formulas are as follows (unchanged from XC9500, but now with more rows): + +1. ``FB[i].MC[j].PT[k].IM[l].P`` is stored at: + + - row: ``l * 2`` + - column: ``k + (j % 3) * 5`` + - bit: ``j // 3`` + +2. ``FB[i].MC[j].PT[k].IM[l].N`` is stored at: + + - row: ``l * 2`` + - column: ``k + (j % 3) * 5`` + - bit: ``j // 3`` + + +Fuses — macrocells +================== + +Per-MC config fuses (that are not product term masks) are stored in bits 6-7 of +columns 0-8 of rows 12-49 of the main area. The formulas are as follows: + +- row: corresponds to fuse function +- column: ``mc_idx % 9`` +- bit: ``6 + mc_idx // 9`` + +The row is: + +- 12: ``PT[0].ALLOC`` bit 0 +- 13: ``PT[0].ALLOC`` bit 1 +- 14: ``PT[1].ALLOC`` bit 0 +- 15: ``PT[1].ALLOC`` bit 1 +- 16: ``PT[2].ALLOC`` bit 0 +- 17: ``PT[2].ALLOC`` bit 1 +- 18: ``PT[3].ALLOC`` bit 0 +- 19: ``PT[3].ALLOC`` bit 1 +- 20: ``PT[4].ALLOC`` bit 0 +- 21: ``PT[5].ALLOC`` bit 1 +- 22: ``INV`` +- 23: ``IMPORT_UP_ALLOC`` +- 24: ``IMPORT_DOWN_ALLOC`` +- 25: ``EXPORT_DIR`` +- 26: ``SUM_HP`` +- 27: ``OE_MUX`` bit 0 +- 28: ``OE_MUX`` bit 1 +- 29: ``OE_MUX`` bit 2 +- 30: ``OE_INV`` +- 31: unused +- 32: ``OUT_MUX`` +- 33: ``CLK_MUX`` bit 0 +- 34: ``CLK_MUX`` bit 1 +- 35: ``CLK_INV`` +- 36: ``CE_MUX`` bit 0 +- 37: ``CE_MUX`` bit 1 +- 38: unused +- 39: ``REG_MODE`` +- 40: ``RST_MUX`` +- 41: ``SET_MUX`` +- 42: ``INIT`` +- 43: ``GND`` +- 44: ``SLEW`` +- 45: ``PT[0].HP`` +- 46: ``PT[1].HP`` +- 47: ``PT[2].HP`` +- 48: ``PT[3].HP`` +- 49: ``PT[4].HP`` + +The fuse combination assignments are: + +- ``PT[*].ALLOC``: + + - ``00``: ``NONE`` + - ``01``: ``OR_MAIN`` + - ``10``: ``OR_EXPORT`` + - ``11``: ``SPECIAL`` + +- ``IMPORT_*_ALLOC``: + + - ``0``: ``OR_EXPORT`` + - ``1``: ``OR_MAIN`` + +- ``EXPORT_DIR``: + + - ``0``: ``UP`` + - ``1``: ``DOWN`` + +- ``OUT_MUX``: + + - ``0``: ``COMB`` + - ``1``: ``FF`` + +- ``CLK_MUX``: + + - ``00``: ``FCLK1`` + - ``01``: ``FCLK0`` + - ``10``: ``FCLK2`` + - ``11``: ``PT`` + +- ``CE_MUX``: + + - ``00``: ``NONE`` + - ``01``: ``PT2`` + - ``10``: ``PT3`` + +- ``REG_MODE``: + + - ``0``: ``DFF`` + - ``1``: ``TFF`` + +- ``RST_MUX``, ``SET_MUX``: + + - ``0``: ``PT`` + - ``1``: ``FSR`` + +- ``SLEW``: + + - ``0``: ``SLOW`` + - ``1``: ``FAST`` + +- everything else: + + - ``0``: false + - ``1``: true + + +Fuses — FB inputs +================= + +The FB input mux configuraton is stored in rows 50-76, columns 0-8, bits 6-7. +``FB[i].IM[j].MUX`` has 9 bits and is stored at the following coordinates: + +- row: ``50 + j % 27`` +- column: mux fuse index (0-8) +- bit: 6 if ``j < 27``, 7 otherwise + +The exact bit assignments are irregular and should be obtained from the database. + + +Fuses — per-FB bits and globals +=============================== + +Per-FB bits are stored in row 78, columns 0-8, bits 6-7. The bits are (row, column, bit): + +- (78, 0, 6): ``ENABLE`` +- (78, 1, 6): ``EXPORT_ENABLE`` +- (78, 6, 6): ``PULLUP_DISABLE`` + +Global bits are stored in rows (2, 6, 7), columns 0-8, bits 6-7 of FB 0. The bits are (row, column, bit): + +- (2, 0, 6): ``FSR_INV`` +- (2, 1, 6): ``FCLK[0].EN`` +- (2, 2, 6): ``FCLK[1].EN`` +- (2, 3, 6): ``FCLK[2].EN`` +- (2, 4, 6): ``FOE[0].EN`` +- (2, 5, 6): ``FOE[1].EN`` +- (2, 6, 6): ``FOE[2].EN`` +- (2, 7, 6): ``FOE[3].EN`` +- (2, 8, 6): ``KEEPER`` +- (6, i, j) for i < 8, j in (6, 7): ``USERCODE`` bit ``16 + (7 - i) * 2 + (j - 6)`` +- (7, i, j) for i < 8, j in (6, 7): ``USERCODE`` bit ``(7 - i) * 2 + (j - 6)`` + +The fuse combination assignments are: + +- ``USERCODE``: each bit stored directly + +- everything else: + + - ``0``: false + - ``1``: true + + +Fuses — protection bits, DONE +============================= + +The protection bits are stored as follows (row, column, bit) in every FB: + +- (11, 0, 6): ``WRITE_PROT`` +- (11, 3, 6): ``READ_PROT`` + +The ``DONE`` bit is stored only once, in FB 0: + +- (11, 6, 6): ``DONE`` diff --git a/_sources/xc9500/index.rst.txt b/_sources/xc9500/index.rst.txt new file mode 100644 index 00000000..87f80ec7 --- /dev/null +++ b/_sources/xc9500/index.rst.txt @@ -0,0 +1,12 @@ +XC9500, XC9500XL, XC9500XV +########################## + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + intro + structure + bitstream-xc9500 + bitstream-xc9500xl + jtag \ No newline at end of file diff --git a/_sources/xc9500/intro.rst.txt b/_sources/xc9500/intro.rst.txt new file mode 100644 index 00000000..b48d096c --- /dev/null +++ b/_sources/xc9500/intro.rst.txt @@ -0,0 +1,126 @@ +Introduction +############ + +XC9500 is a family of flash-based CPLDs manufactured by Xilinx. It is a derivative of the earlier XC7200 and XC7300 +EPLD families. It comes in three variants: + +1. XC9500: 5V core logic, 3.3V or 5V I/O, original version. +2. XC9500XL: 3.3V core logic, 2.5V or 3.3V I/O (5V tolerant), with some functional changes from XC9500: + + - UIM no longer has wired-AND functionality + - FFs have clock enable function + - 54 (instead of 36) UIM inputs per function block + - FF has configurable clock polarity + - FOE/FCLK multiplexers and inversion have been removed + - optional weak bus keeper can be configured for all pins + +3. XC9500XV: 2.5V core logic, 1.8V, 2.5V, or 3.3V I/O, with minor functional changes from XC9500XL: + + - larger devices have two I/O banks with separate VCCIO + - the bitstream now contains a ``DONE`` bit tied to ``ISC_DONE``, preventing problems with partially configured devices + + +Devices +======= + +The following devices exist: + +========= ======== =============== +Device Variant Function Blocks +========= ======== =============== +XC9536 XC9500 2 +XC9572 XC9500 4 +XC95108 XC9500 6 +XC95144 XC9500 8 +XC95216 XC9500 12 +XC95288 XC9500 16 +XC9536XL XC9500XL 2 +XC9572XL XC9500XL 4 +XC95144XL XC9500XL 8 +XC95288XL XC9500XL 16 +XA9536XL XC9500XL 2 +XA9572XL XC9500XL 4 +XA95144XL XC9500XL 8 +XC9536XV XC9500XV 2 +XC9572XV XC9500XV 4 +XC95144XV XC9500XV 8 +XC95288XV XC9500XV 16 +========= ======== =============== + +The parts starting with XA are automotive versions. They are functionally completely identical to corresponding XC versions. + + +Packages +======== + +The devices come in the following packages: + +- PLCC: + + - PC44 (JEDEC MO-047) + - PC84 (JEDEC MO-047) + +- QFP: + + - very thin QFP (1mm thickness): + + - VQ44 (0.8mm pitch; JEDEC MS-026-ACB) + - VQ64 (0.5mm pitch; JEDEC MS-026-ACD) + + - thin QFP (1.4mm thickness): + + - TQ100 (0.5mm pitch; JEDEC MS-026-BED) + - TQ144 (0.5mm pitch; JEDEC MS-026-BFB) + + - plastic QFP: + + - PQ100 (2.7mm thickness, non-square, 30×20 pins, 0.65mm pitch; JEDEC MS-022-GC1) + - PQ160 (3.4mm thickness, 0.65mm pitch; JEDEC MS-022-DD1) + - PQ208 (3.4mm thickness, 0.5mm pitch; JEDEC MS-029-FA-1) + + - platic QFP with heat sink: + + - HQ208 (same footprint as PQ208) + +- BGA: + + - standard BGA (1.27mm pitch): + + - BG256 (JEDEC MS-034-BAL-2) + - BG352 + + - fine-pitch BGA (1mm pitch): + + - FG256 + + - chip-scale BGA (0.8mm pitch): + + - CS48 + - CS144 (JEDEC MO-216-BAG-2) + - CS280 (JEDEC MO-216-BAL-1) + + +========= ==== ==== ==== ==== ===== ===== ===== ===== ===== ===== ===== ===== ===== ==== ===== ===== +Device PC44 PC84 VQ44 VQ64 TQ100 TQ144 PQ100 PQ160 PQ208 HQ208 BG256 BG352 FG256 CS48 CS144 CS280 +========= ==== ==== ==== ==== ===== ===== ===== ===== ===== ===== ===== ===== ===== ==== ===== ===== +XC9536 X X X +XC9572 X X X X +XC95108 X X X X +XC95144 X X X +XC95216 X X X +XC95288 X X +XC9536XL X X X X +XC9572XL X X X X X +XC95144XL X X X +XC95288XL X X X X X +XA9536XL X +XA9572XL X X X +XA95144XL X +XC9536XV X X X +XC9572XV X X X X +XC95144XV X X X +XC95288XV X X X X +========= ==== ==== ==== ==== ===== ===== ===== ===== ===== ===== ===== ===== ===== ==== ===== ===== + +Pin compatibility is maintained across all 3 variants of the XC9500 family within a single package. +Additionally, devices in PQ208 and HQ208 packages are pin compatible with each other. \ No newline at end of file diff --git a/_sources/xc9500/jtag.rst.txt b/_sources/xc9500/jtag.rst.txt new file mode 100644 index 00000000..f925a078 --- /dev/null +++ b/_sources/xc9500/jtag.rst.txt @@ -0,0 +1,171 @@ +JTAG interface +############## + +IR +== + +The IR is 8 bits long. The following instructions exist: + +============ ============ ==================== ======= +IR Instruction Register Notes +============ ============ ==================== ======= +``00000000`` ``EXTEST`` ``BOUNDARY`` +``00000001`` ``SAMPLE`` ``BOUNDARY`` +``00000010`` ``INTEST`` ``BOUNDARY`` +``11100101`` ``FBLANK`` ``ISPADDRESS`` XC9500XL/XV only +``11101000`` ``ISPEN`` ``ISPENABLE`` +``11101001`` ``ISPENC`` ``ISPENABLE`` XC9500XL/XV only +``11101010`` ``FPGM`` ``ISPCONFIGURATION`` +``11101011`` ``FPGMI`` ``ISPDATA`` +``11101100`` ``FERASE`` ``ISPCONFIGURATION`` XC9500 only +``11101100`` ``FERASE`` ``ISPADDRESS`` XC9500XL/XV only +``11101101`` ``FBULK`` ``ISPCONFIGURATION`` XC9500 only +``11101101`` ``FBULK`` ``ISPADDRESS`` XC9500XL/XV only +``11101110`` ``FVFY`` ``ISPCONFIGURATION`` +``11101111`` ``FVFYI`` ``ISPDATA`` +``11110000`` ``ISPEX`` ``BYPASS`` +``11111010`` ``CLAMP`` ``BYPASS`` XC9500XL/XV only +``11111100`` ``HIGHZ`` ``BYPASS`` +``11111101`` ``USERCODE`` ``USERCODE`` +``11111110`` ``IDCODE`` ``IDCODE`` +``11111111`` ``BYPASS`` ``BYPASS`` +============ ============ ==================== ======= + +The IR status is: + +- bit 0: const 1 +- bit 1: const 0 +- bit 2: ``WRITE_PROT`` status +- bit 3: ``READ_PROT`` status +- bit 4: ISP mode enabled +- bit 5: ``DONE`` status (XC9500XV only, const 0 on other devices) +- bits 6-7: const 0 + +.. todo:: verify + + +Boundary scan register +====================== + +The boundary scan register is ``3 * 18 * num_fbs`` bits long, and consists of 3 bits for every MC +in the device: input, output, and output enable. Such bits are included even for MCs that do not +have a corresponding IOB. + +The boundary register bit indices for ``FB[i].MC[j]`` are: + +- input: ``(num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 2`` +- output: ``(num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 1`` +- output enable: ``(num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 0`` + +All bits of the register are ``BC_1`` type cells. + +.. todo:: details on the cell connection, EXTEST, INTEST semantics + + +ISP instructions +================ + +ISP DR registers — XC9500 +------------------------- + +The following DR registers exist on XC9500: + +1. ``ISPENABLE`` (16 bits): function and contents unclear +2. ``ISPCONFIGURATION`` (27 bits): used to load and store bitstream bytes + + - bit 0: valid bit + - bit 1: strobe bit + - bits 2-9: data byte + - bits 10-26: address + +3. ``ISPDATA`` (10 bits): a subset of ``ISPCONFIGURATION`` used by instructions with autoincrementing address + + - bit 0: valid bit + - bit 1: strobe bit + - bits 2-9: data byte + +.. todo:: ISPENABLE, describe valid & strobe + + +ISP DR registers — XC9500XL/XV +------------------------------ + +The following DR registers exist on XC9500XL/XV: + +1. ``ISPENABLE`` (6 bits): function and contents unclear +2. ``ISPCONFIGURATION`` (``18 + num_fbs * 8`` bits): used to load and store bitstream words + + - bit 0: valid bit + - bit 1: strobe bit + - bits 2-``(num_sbs * 8 + 1)``: data word + - bits ``(num_fbs * 8 + 2)``-``(num_fbs * 8 + 17)``: address + +3. ``ISPDATA`` (``2 + num_fbs * 8`` bits): a subset of ``ISPCONFIGURATION`` used by instructions with autoincrementing address + + - bit 0: valid bit + - bit 1: strobe bit + - bits 2-``(num_sbs * 8 + 1)``: data word + +4. ``ISPADDRESS`` (18 bits): a subset of ``ISPCONFIGURATION`` used by some instructions: + + - bit 0: valid bit + - bit 1: strobe bit + - bits 2-17: address + + +Entering and exiting ISP mode +----------------------------- + +Before any programming or readout can be done, the device needs to be put into ISP mode. +For that purpose, the ``ISPEN`` or ``ISPENC`` (XC9500XL/XV only) instructions can be used. +Both instructions use the ``ISPENABLE`` register, which is 16 bits on XC9500 +and 6 bits on XC9500XL/XV. Its meaning, if any, is unknown. + +To enter ISP mode: + +- shift ``ISPEN`` or ``ISPENC`` into IR +- shift 0s into DR +- go to Run-Test/Idle state for at least 1 clock + +If the ``ISPEN`` instruction is used, all outputs will be put in high-Z with weak pull-ups while ISP mode is active. +If the ``ISPENC`` ("clamp" mode) instruction is used, all output and output enable signals will be snapshotted +and outputs will continue driving the last value while ISP mode is active. + +To exit ISP mode: + +- shift ``ISPEX`` into IR +- go to Run-Test/Idle state for at least 1 clock + +When ISP mode is exitted, the device will initialize itself and start normal operation. + +.. todo:: verify, see if anything can be figured out about the DR + + +Erasing fuses +------------- + +.. todo:: write me + + +Programming fuses +----------------- + +.. todo:: write me + + +Reading fuses +------------- + +.. todo:: write me + + +Blank check +----------- + +.. todo:: write me + + +Programming sequence +==================== + +.. todo:: write me \ No newline at end of file diff --git a/_sources/xc9500/structure.rst.txt b/_sources/xc9500/structure.rst.txt new file mode 100644 index 00000000..133e2bb3 --- /dev/null +++ b/_sources/xc9500/structure.rst.txt @@ -0,0 +1,622 @@ +Device structure +################ + +Overview +======== + +An XC9500 family device is made of: + +- the UIM (universal interconnect matrix), which routes MC and IOB outputs to FB inputs +- 2-16 FBs (function blocks), each of which has: + + - 36 (XC9500) or 54 (XC9500XL/XV) routable inputs from UIM + - 18 MCs (macrocells), each of which has: + + - configurable low power / high performance mode + - 5 PTs (product terms) + - PT router, which can route PTs to: + + - the sum term for this MC + - the sum term for export into neighbouring MCs + - a special function (OE, RST, SET, CLK, CE, XOR depending on the PT) + + - PT export/import logic for borrowing PTs between neighbouring MCs + - a sum term + - a dedicated XOR gate + - optional inverter + - a flip-flop, with: + + - configurable DFF or TFF function + - configurable initial value + - clock (freely invertible on XC9500XL/XV), routable from FCLK or PT + - async reset, routable from FSR or PT + - async set, routable from FSR or PT + - (XC9500XL/XV only) clock enable, routable from PT + + - a single output (selectable from combinatorial or FF output), routed to IOB and UIM + - (XC9500 only) UIM output enable and inversion + - IOB (input/output buffer) (on larger devices, not all macrocells have an IOB), with: + + - input buffer (routed to UIM) + - output enable (freely invertible on XC9500XL/XV), routable from FOE or PT + - configurable slew rate (fast or slow) + - programmable ground + +- global signals + + - 3 FCLK (fast clock) signals + + - (XC9500) freely invertible and routable from GCLK pins + - (XC9500XL/XV) hardwired 1-1 to GCLK pins + + - 1 FSR (fast set/reset) signal + + - freely invertible + - always routed from GSR pin + + - 2-4 FOE (fast output enable) signals + + - (XC9500) freely invertible and routable from GOE pins + - (XC9500XL/XV) hardwired 1-1 to GOE pins + +- global pull-up enable (only meant to be used in unconfigured devices) +- (XC9500XL/XV) global bus keeper enable +- special global configuration bits + + - 32-bit standard JTAG USERCODE + - read protection enable + - write protection enable + - (XC9500XV only) DONE bit + + +UIM and FB inputs — XC9500 +========================== + +The core interconnect structure in XC9500 devices is the UIM, Universal Interconnect Matrix. +The name is quite appropriate, at least for internal signals: any FB input can be routed +to any MC output. More than that, any FB input can be routed to a *wire-AND* of an arbitrary +subset of MC outputs from the entire device. Together with the UIM OE functionality within +the MC, this can be used for emulated internal tri-state buses. + +The name is, however, less appropriate when it comes to external signals: a given FB input +can only be routed to some subset of input signals from IOBs. The set of routable IOBs +depends on the FB input index and the device. + +Additionally, on devices other than XC9536, some FB inputs can be routed to "fast feedback" +paths, which come straight from MC outputs within the same FB. This is functionally redundant +with the wire-AND path, but much faster. + +Each FB has 36 inputs, which we call ``FB[i].IM[j]``. Each FB input is controlled by two sets of fuses: + +- mux fuses (``FB[i].IM[j].MUX``) select what is routed to the input. The combinations include: + + - ``EMPTY``: the input is a constant ??? (for unused inputs) + - ``UIM``: the input is a wire-AND of MC outputs (and the second set of fuses is relevant) + - ``FBK_MC{k}``: the input is routed through fast feedback path from ``FB[i].MC[k].OUT`` + - ``PAD_FB{k}_MC{l}``: the input is routed from an input buffer ``FB[k].MC[l].IOB.I`` + + The allowable combinations differ between inputs within a single FB, but don't differ across + FBs within a single device. In other words, the set of allowed values for these fuses + depends only on the ``j`` coordinate, but not on ``i``. + +- wire-AND fuses (``FB[i].IM[j].UIM.FB[k].MC[l]``) select which MC outputs participate in the + wire-AND. If a given fuse is programmed, it means that ``FB[k].MC[l].OUT_UIM`` is included + in the product. These fuses are only relevant when the mux fuse set is set to ``UIM``. + +.. todo:: check ``EMPTY`` semantics + +.. todo:: verify ``FBK`` doesn't go through OE and inversion + + +UIM and FB inputs — XC9500XL/XV +=============================== + +The core interconnect structure in XC9500XL/XV devices is the UIM 2. This version of the UIM +is not really universal, and is much more of a classic CPLD design. + +Each FB has 54 inputs, which we call ``FB[i].IM[j]``. Each FB input is controlled by a set of fuses: + +- mux fuses (``FB[i].IM[j].MUX``) select what is routed to the input. The combinations include: + + - ``EMPTY``: the input is a constant ??? (for unused inputs) + - ``FB{k}_MC{l}``: the input is routed from the macrocell output ``FB[k].MC[l].OUT`` + - ``PAD_FB{k}_MC{l}``: the input is routed from the input buffer ``FB[k].MC[l].IOB.I`` + + The allowable combinations differ between inputs within a single FB, but don't differ across + FBs within a single device. In other words, the set of allowed values for these fuses + depends only on the ``j`` coordinate, but not on ``i``. + +.. todo:: check ``EMPTY`` semantics + + +FB global fuses +=============== + +Each function block has two fuses controlling the entire FB: + +- ``FB[i].ENABLE``: function block enable; needs to be programmed to use this function block +- ``FB[i].EXPORT_ENABLE``: function block PT export enable; needs to be programmed to use PT + import/export within this function block + +.. todo:: determine what these do exactly + + +Product terms +============= + +Each function block has 90 product terms, 5 per macrocell. We call them ``FB[i].MC[j].PT[k]``. +Each of the 5 PTs has a dedicated function, as follows: + +- ``*.PT[0]``: clock +- ``*.PT[1]``: output enable +- ``*.PT[2]``: async reset (or clock enable on XC9500XL/XV) +- ``*.PT[3]``: async set (or clock enable on XC9500XL/XV) +- ``*.PT[4]``: second XOR input + +The inputs to all product terms within a FB are the same, and consist of all FB inputs, in both +true and inverted forms. + +Each product term can be individually configured as low power or high performance. This affects propagation time. + +Each product term can be routed to at most one of three destinations: + +- ``OR_MAIN``: input to the MC's sum term +- ``OR_EXPORT``: input to the export OR gate +- ``SPECIAL``: used for the dedicated function + +The fuses controlling a product term are: + +- ``FB[i].MC[j].PT[k].IM[l].P``: if programmed, ``FB[i].IM[l]`` is included in the product term (true polarity) +- ``FB[i].MC[j].PT[k].IM[l].N``: if programmed, ``~FB[i].IM[l]`` is included in the product term (inverted polarity) +- ``FB[i].MC[j].PT[k].HP``: if programmed, the product term is in high performance mode; otherwise, it is in low power mode +- ``FB[i].MC[j].PT[k].ALLOC``: has one of four values: + + - ``EMPTY``: product term is unused + - ``OR_MAIN``: product term is used for MC's sum term; dedicated function wired to 0 + - ``OR_EXPORT`` product term is used for export sum term; dedicated function wired to 0 + - ``SPECIAL``: product term is used for the dedicated function + +The product term's corresponding dedicated function is called ``FB[i].MC[j].PT[k].SPECIAL``. +It is equal to ``FB[i].MC[j].PT[k]`` if the dedicated function is enabled in ``ALLOC``, 0 otherwise. + +PT import/export +---------------- + +Product terms can be borrowed between neighbouring MCs within a FB. To this end, each MC has two outputs, +``FB[i].MC[j].EXPORT_{UP|DOWN}``, and two inputs, ``FB[i].MC[j].IMPORT_{UP|DOWN}``. The "down" direction +corresponds to exporting PTs toward lower-numbered MCs (with a wraparound from 0 to 17), and the "up" +direction corresponds to exporting PTs towards higher-numbered MCs (with a wraparound from 17 to 0). +Accordingly, we have:: + + FB[i].MC[j].IMPORT_DOWN = FB[i].MC[(j + 1) % 18].EXPORT_DOWN; + FB[i].MC[j].IMPORT_UP = FB[i].MC[(j - 1) % 18].EXPORT_UP; + +A MC can only export product terms in one direction (up or down). +Product terms can be imported from both directions at once. +Imported terms from a given direction can be used for either the main sum term, or for further export, but not both at once. + +PT import/export is controlled by the following per-MC fuses: + +- ``FB[i].MC[j].EXPORT_DIR``: one of: + + - ``DOWN``: exports PTs downwards + - ``UP``: exports PTs upwards + +- ``FB[i].MC[j].IMPORT_UP_ALLOC``: one of: + + - ``OR_MAIN``: includes PTs imported upwards in the main sum term + - ``OR_EXPORT``: includes PTs imported upwards in the export sum term + +- ``FB[i].MC[j].IMPORT_DOWN_ALLOC``: one of: + + - ``OR_MAIN``: includes PTs imported downwards in the main sum term + - ``OR_EXPORT``: includes PTs imported downwards in the export sum term + +Additionally, the per-FB ``FB[i].EXPORT_ENABLE`` fuse needs to be set if any term within a FB is exported or imported. + +Export works as follows:: + + FB[i].MC[j].EXPORT = + (FB[i].MC[j].IMPORT_UP_ALLOC == OR_EXPORT ? FB[i].MC[j].IMPORT_UP : 0) | + (FB[i].MC[j].IMPORT_DOWN_ALLOC == OR_EXPORT ? FB[i].MC[j].IMPORT_DOWN : 0) | + (FB[i].MC[j].PT[0].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[0] : 0) | + (FB[i].MC[j].PT[1].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[1] : 0) | + (FB[i].MC[j].PT[2].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[2] : 0) | + (FB[i].MC[j].PT[3].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[3] : 0) | + (FB[i].MC[j].PT[4].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[4] : 0); + + FB[i].MC[j].EXPORT_UP = (FB[i].MC[j].EXPORT_DIR == UP ? FB[i].MC[j].EXPORT : 0); + FB[i].MC[j].EXPORT_DOWN = (FB[i].MC[j].EXPORT_DIR == DOWN ? FB[i].MC[j].EXPORT : 0); + +.. todo:: verify all of the above + + +Sum term, XOR gate +================== + +Each macrocell has a main sum term, which includes all product terms and imports routed towards it:: + + FB[i].MC[j].SUM = + (FB[i].MC[j].IMPORT_UP_ALLOC == OR_MAIN ? FB[i].MC[j].IMPORT_UP : 0) | + (FB[i].MC[j].IMPORT_DOWN_ALLOC == OR_MAIN ? FB[i].MC[j].IMPORT_DOWN : 0) | + (FB[i].MC[j].PT[0].ALLOC == OR_MAIN ? FB[i].MC[j].PT[0] : 0) | + (FB[i].MC[j].PT[1].ALLOC == OR_MAIN ? FB[i].MC[j].PT[1] : 0) | + (FB[i].MC[j].PT[2].ALLOC == OR_MAIN ? FB[i].MC[j].PT[2] : 0) | + (FB[i].MC[j].PT[3].ALLOC == OR_MAIN ? FB[i].MC[j].PT[3] : 0) | + (FB[i].MC[j].PT[4].ALLOC == OR_MAIN ? FB[i].MC[j].PT[4] : 0); + +The sum term then goes through a XOR gate (whose other input is either 0 or a dedicated PT) and a programmable inverter:: + + FB[i].MC[j].XOR = FB[i].MC[j].SUM ^ FB[i].MC[j].PT[4].SPECIAL ^ FB[i].MC[j].INV; + +The fuses involved are: + +- ``FB[i].MC[j].SUM_HP``: if programmed, the sum term is in high performance mode; otherwise, it's in low power mode +- ``FB[i].MC[j].INV``: if programmed, the output of the XOR gate is further inverted + +Flip-flop +========= + +Each macrocell includes a flip-flop. It has: + +- configurable DFF or TFF function +- D or T input connected to the (potentially inverted) XOR gate output +- configurable initial value +- clock (freely invertible on XC9500XL/XV), routable from FCLK or ``PT[0]`` +- async reset, routable from FSR or ``PT[2]`` +- async set, routable from FSR or ``PT[3]`` +- (XC9500XL/XV only) clock enable, routable from ``PT[2]`` or ``PT[3]`` + +The fuses involved are: + +- ``FB[i].MC[j].CLK_MUX``: selects CLK input + + - ``PT``: product term 0 dedicated function + - ``FCLK[0-2]``: global ``FCLK[0-2]`` network + +- ``FB[i].MC[j].CLK_INV``: if programmed, the CLK input is inverted (ie. clock is negedge) (XC9500XL/XV only) + +- ``FB[i].MC[j].RST_MUX``: selects RST input + + - ``PT``: product term 2 dedicated function or 0; if PT 2 is used for clock enable, it will not be routed to RST (0 will be substituted) + - ``FSR``: global ``FSR`` network + +- ``FB[i].MC[j].SET_MUX``: selects SET input + + - ``PT``: product term 3 dedicated function or 0; if PT 3 is used for clock enable, it will not be routed to SET (0 will be substituted) + - ``FSR``: global ``FSR`` network + +- ``FB[i].MC[j].CE_MUX``: selects CE input (XC9500XL/XV only) + + - ``NONE``: const 1 + - ``PT2``: product term 2 dedicated function + - ``PT3``: product term 3 dedicated function + +- ``FB[i].MC[j].INIT``: if programmed, the initial value of the FF is 1; otherwise, it is 0 + +- ``FB[i].MC[j].REG_MODE``: selects FF mode + + - ``DFF`` + - ``TFF`` + +On XC9500, the FF works as follows:: + + case(FB[i].MC[j].CLK_MUX) + PT: FB[i].MC[j].CLK = FB[i].MC[j].PT[0].SPECIAL; + FCLK0: FB[i].MC[j].CLK = FCLK[0]; + FCLK1: FB[i].MC[j].CLK = FCLK[1]; + FCLK2: FB[i].MC[j].CLK = FCLK[2]; + endcase + + case(FB[i].MC[j].RST_MUX) + PT: FB[i].MC[j].RST = FB[i].MC[j].PT[2].SPECIAL; + FSR: FB[i].MC[j].RST = FSR; + endcase + + case(FB[i].MC[j].SET_MUX) + PT: FB[i].MC[j].SET = FB[i].MC[j].PT[3].SPECIAL; + FSR: FB[i].MC[j].SET = FSR; + endcase + + initial FB[i].MC[j].FF = FB[i].MC[j].INIT; + + // Pretend the usual synth/sim mismatch doesn't happen. + always @(posedge FB[i].MC[j].CLK, posedge FB[i].MC[j].RST_MUX, posedge FB[i].MC[j].SET_MUX) + if (FB[i].MC[j].RST_MUX) + FB[i].MC[j].FF = 0; + else if (FB[i].MC[j].SET_MUX) + FB[i].MC[j].FF = 1; + else + FB[i].MC[j].FF = FB[i].MC[j].XOR; + +On XC9500XL/XV, the FF works as follows:: + + case(FB[i].MC[j].CLK_MUX) + PT: FB[i].MC[j].CLK = FB[i].MC[j].PT[0].SPECIAL ^ FB[i].MC[j].CLK_INV; + FCLK0: FB[i].MC[j].CLK = FCLK[0] ^ FB[i].MC[j].CLK_INV; + FCLK1: FB[i].MC[j].CLK = FCLK[1] ^ FB[i].MC[j].CLK_INV; + FCLK2: FB[i].MC[j].CLK = FCLK[2] ^ FB[i].MC[j].CLK_INV; + endcase + + case(FB[i].MC[j].RST_MUX) + PT: FB[i].MC[j].RST = (FB[i].MC[j].CE_MUX == PT2 ? 0 : FB[i].MC[j].PT[2].SPECIAL); + FSR: FB[i].MC[j].RST = FSR; + endcase + + case(FB[i].MC[j].SET_MUX) + PT: FB[i].MC[j].SET = (FB[i].MC[j].CE_MUX == PT3 ? 0 : FB[i].MC[j].PT[3].SPECIAL); + FSR: FB[i].MC[j].SET = FSR; + endcase + + case(FB[i].MC[j].CE_MUX) + PT2: FB[i].MC[j].CE = FB[i].MC[j].PT[2].SPECIAL; + PT3: FB[i].MC[j].CE = FB[i].MC[j].PT[3].SPECIAL; + NONE: FB[i].MC[j].CE = 1; + endcase + + initial FB[i].MC[j].FF = FB[i].MC[j].INIT; + + // Pretend the usual synth/sim mismatch doesn't happen. + always @(posedge FB[i].MC[j].CLK, posedge FB[i].MC[j].RST_MUX, posedge FB[i].MC[j].SET_MUX) + if (FB[i].MC[j].RST_MUX) + FB[i].MC[j].FF = 0; + else if (FB[i].MC[j].SET_MUX) + FB[i].MC[j].FF = 1; + else if (FB[i].MC[j].CE) + FB[i].MC[j].FF = FB[i].MC[j].XOR; + +.. todo:: verify (in particular, CE vs RST/SET shenanigans) + + +Macrocell output — XC9500 +========================= + +The output of the macrocell can be selected from combinatorial (XOR gate output) or registered (FF output):: + + FB[i].MC[j].OUT = (FB[i].MC[j].OUT_MUX == COMB ? FB[i].MC[j].XOR : FB[i].MC[j].FF); + +The macrocell also has an output enable, which can be from a product term, or a global network. +It can be used for the IOB output buffer, for UIM output, or both:: + + case(FB[i].MC[j].OE_MUX) + PT: FB[i].MC[j].OE = FB[i].MC[j].PT[1].SPECIAL; + FOE0: FB[i].MC[j].OE = FOE[0]; + FOE1: FB[i].MC[j].OE = FOE[1]; + FOE2: FB[i].MC[j].OE = FOE[2]; + FOE3: FB[i].MC[j].OE = FOE[3]; + endcase + + case(FB[i].MC[j].UIM_OE_MUX) + GND: FB[i].MC[j].UIM_OE = 0; + VCC: FB[i].MC[j].UIM_OE = 1; + OE_MUX: FB[i].MC[j].UIM_OE = FB[i].MC[j].OE; + endcase + + case(FB[i].MC[j].IOB_OE_MUX) + GND: FB[i].MC[j].IOB_OE = 0; + VCC: FB[i].MC[j].IOB_OE = 1; + OE_MUX: FB[i].MC[j].IOB_OE = FB[i].MC[j].OE; + endcase + +The output is routed to up to three places: + +- this MC's IOB (``FB[i].MC[j].OUT``) +- this FB's inputs via the feedback path (``FB[i].MC[j].OUT``) +- the UIM (``FB[i].MC[j].OUT_UIM``) + +The output to UIM additionally goes through (emulated) output enable logic, which can be used +to implement emulated on-chip tristate buses in conjunction with the UIM wire-AND logic:: + + FB[i].MC[j].OUT_UIM = FB[i].MC[j].UIM_OE ? FB[i].MC[j].OUT ^ FB[i].MC[j].UIM_OUT_INV : 1; + +The fuses involved are: + +- ``FB[i].MC[j].OUT_MUX``: selects output mode + + - ``COMB``: combinatorial, the output is connected to XOR gate output + - ``FF``: registered, the output is connected to FF output + +- ``FB[i].MC[j].OE_MUX``: selects output enable source + + - ``PT``: product term 1 dedicated function or 0 + - ``FOE[0-3]``: global ``FOE[0-3]`` network + +- ``FB[i].MC[j].UIM_OE_MUX``: selects output enable for UIM output + + - ``GND``: const 0 + - ``VCC``: const 1 + - ``OE_MUX``: the input selected by the ``OE_MUX`` fuses + +- ``FB[i].MC[j].IOB_OE_MUX``: selects output enable for IOB output + + - ``GND``: const 0 + - ``VCC``: const 1 + - ``OE_MUX``: the input selected by the ``OE_MUX`` fuses + +- ``FB[i].MC[j].UIM_OUT_INV``: if programmed, the output to UIM is inverted + + +.. todo:: verify all of the above (in particular, feedback path vs OE and UIM out) + + +Macrocell output — XC9500XL/XV +============================== + +The output of the macrocell can be selected from combinatorial (XOR gate output) or registered (FF output):: + + FB[i].MC[j].OUT = (FB[i].MC[j].OUT_MUX == COMB ? FB[i].MC[j].XOR : FB[i].MC[j].FF); + +The output is routed to the UIM and this MC's IOB. + +The macrocell also has an output enable, which can be from a product term, or a global network, and can +be freely inverted. It is used for the IOB output buffer:: + + case(FB[i].MC[j].OE_MUX) + PT: FB[i].MC[j].IOB_OE = FB[i].MC[j].PT[1].SPECIAL ^ FB[i].MC[j].OE_INV; + FOE0: FB[i].MC[j].IOB_OE = FOE[0] ^ FB[i].MC[j].OE_INV; + FOE1: FB[i].MC[j].IOB_OE = FOE[1] ^ FB[i].MC[j].OE_INV; + FOE2: FB[i].MC[j].IOB_OE = FOE[2] ^ FB[i].MC[j].OE_INV; + FOE3: FB[i].MC[j].IOB_OE = FOE[3] ^ FB[i].MC[j].OE_INV; + endcase + +The fuses involved are: + +- ``FB[i].MC[j].OUT_MUX``: selects output mode + + - ``COMB``: combinatorial, the output is connected to XOR gate output + - ``FF``: registered, the output is connected to FF output + +- ``FB[i].MC[j].OE_MUX``: selects output enable source + + - ``PT``: product term 1 dedicated function or 0 + - ``FOE[0-3]``: global ``FOE[0-3]`` network + +- ``FB[i].MC[j].OE_INV``: if programmed, the output enable is inverted + + +Input/output buffer +=================== + +All I/O buffers (except dedicated JTAG pins) are associated with a macrocell. Not all MCs +have associated IOBs. + +The output buffer is controlled by the ``FB[i].MC[j].OUT`` and ``FB[i].MC[j].IOB_OE`` signals of the macrocell. +If the pad is supposed to be input only, the OE signal should be programmed to be always 0: + +- on XC9500, ``IOB_OE_MUX`` should be set to ``GND`` +- on XC9500XL/XV, ``OE_MUX`` should be set to ``PT``, ``OE_INV`` should be unset, and ``PT[1]`` should not be allocated to its dedicated function + +Likewise, if the pad is supposed to be always-on output, the OE signal should be programmed to be always 1: + +- on XC9500, ``IOB_OE_MUX`` should be set to ``VCC`` +- on XC9500XL/XV, ``OE_MUX`` should be set to ``PT``, ``OE_INV`` should be set, and ``PT[1]`` should not be allocated to its dedicated function + +The output slew rate is programmable between two settings, "fast" and "slow". + +Instead of being connected to MC output, an IOB can also be a "programmed ground", ie be set to always output a const 0 +regardless of the ``IOB_OE`` and ``OUT`` signals. In this case, ``IOB_OE`` should be 0. + +The input buffer is connected to the ``FB[i].MC[j].IOB.I`` network. On all devices other than XC95288 (non-XL/XV), +it is directly connected to the UIM. On XC95288, there are additional enable fuses for this connection. + +Each I/O buffer has the following fuses: + +- ``FB[i].MC[j].GND``: if programmed, this pin is "programmed ground" and will always output a const 0 +- ``FB[i].MC[j].SLEW``: selects slew rate, one of: + + - ``SLOW`` + - ``FAST`` + +- ``FB[i].MC[j].IBUF_ENABLE`` (XC95288 only): when programmed, the input buffer is active and connected to UIM + +.. todo:: figure out the IBUF_ENABLE thing + + +Configuration pull-ups +====================== + +Before the device is configured, all IOBs are configured with a very weak pull-up +resistor (XC9500) or a bus keeper (XC9500XL/XV). To disable this pull-up, a per-FB fuse +is used which is set in the bitstream: + +- ``FB[i].PULLUP_DISABLE``: if programmed, disables the pre-configuration pull-ups / bus keepers for all IOBs in this FB + + +XC9500XL/XV bus keeper +====================== + +The XC9500XL/XV have a weak bus keeper in each IOB. The keeper functionality can only be enabled +globally for all pads on the device, or not at all, via a global fuse: + +- ``KEEPER``: if programmed, the bus keeper is enabled on all IOBs + + +Global networks — XC9500 +======================== + +The device has several global networks for fast control signals. The networks are always driven by special pads +on the device (which can also be used as normal I/O). The networks are: + +- ``FCLK[0-2]``: clock +- ``FSR``: async set or reset +- ``FOE[0-1]`` (XC9536, XC9572, XC95108) or ``FOE[0-3]`` (XC95144, XC95216, XC95288): output enable + +The special pads are: + +- ``GCLK[0-2]``: clock +- ``GSR``: async set or reset +- ``GOE[0-1]`` (XC9536, XC9572, XC95108) or ``GOE[0-3]`` (XC95144, XC95216, XC95288): output enable + +The mapping of ``G*`` special pads to MCs depends on the device and, in at least one case, the package (!). + +The allowed mappings are: + +- ``FCLK0``: ``GCLK0``, ``GCLK1`` +- ``FCLK1``: ``GCLK1``, ``GCLK2`` +- ``FCLK2``: ``GCLK2``, ``GCLK0`` +- ``FSR``: ``GSR`` +- ``FOE0`` (XC9536, XC9572, XC95108): ``GOE0``, ``GOE1`` +- ``FOE1`` (XC9536, XC9572, XC95108): ``GOE0``, ``GOE1`` +- ``FOE0`` (XC95144, XC95216, XC95288): ``GOE0``, ``GOE1`` +- ``FOE1`` (XC95144, XC95216, XC95288): ``GOE1``, ``GOE2`` +- ``FOE2`` (XC95144, XC95216, XC95288): ``GOE2``, ``GOE3`` +- ``FOE3`` (XC95144, XC95216, XC95288): ``GOE3``, ``GOE0`` + +Additionally, all networks can be inverted from their source pins. + +The fuses involved are: + +- ``FCLK[i].MUX``: selects the input routed to ``FCLK[i]`` + + - ``NONE``: const ??? + - ``GCLK[i]``: the corresponding ``GCLK`` pad + +- ``FOE[i].MUX``: selects the input routed to ``FOE[i]`` + + - ``NONE``: const ??? + - ``FOE[i]``: the corresponding ``FOE`` pad + +- ``FCLK[i].INV``: if programmed, the ``GCLK`` pad is inverted before driving ``FCLK[i]`` network +- ``FSR.INV``: if programmed, the ``GSR`` pad is inverted before driving ``FSR`` network +- ``FOE[i].INV``: if programmed, the ``GOE`` pad is inverted before driving ``FOE[i]`` network + +.. todo:: consts + +.. todo:: no, really, what is it with the XC9572 GOE mapping varying between packages + + +Global networks — XC9500XL/XV +============================= + +Global networks on XC9500XL/XV work similarly, except there are no muxes and no inversion (except for ``FSR``). +Thus the ``GCLK[i]`` and ``GOE[i]`` pads are mapped 1-1 directly to ``FCLK[i]`` and ``FOE[i]`` networks, with only +an enable fuse. + +The fuses involved are: + +- ``FCLK[i].EN``: if programmed, the given ``FCLK`` network is active and connected to the ``GCLK[i]`` pad +- ``FOE[i].EN``: if programmed, the given ``FOE`` network is active and connected to the ``GOE[i]`` pad +- ``FSR.INV``: if programmed, the ``GSR`` pad is inverted before driving ``FSR`` network + +The ``FSR`` network is always enabled. + +.. todo:: what does disabled network do + + +Misc configuration +================== + +The devices also include the following misc fuses: + +- ``USERCODE``: 32-bit fuse set, readable via the JTAG USERCODE instruction + +- ``FB[i].READ_PROT_{A|B}`` (XC9500): if programmed, the device is read protected +- ``FB[i].READ_PROT`` (XC9500XL/XV): if programmed, the device is read protected +- ``FB[i].WRITE_PROT``: if programmed, the device is write protected (needs a special JTAG instruction sequence + to program/erase) +- ``DONE`` (XC9500XV only): used to mark a fully programmed device; if programmed, the device will complete its + boot sequence and activate I/O buffers; otherwise, all output buffers will be disabled + +Due to their special semantics, the protection fuses and the ``DONE`` fuse should be programmed last, after all other fuses in the bitstream. + +.. todo:: exact semantics of protection fuses \ No newline at end of file diff --git a/_static/alabaster.css b/_static/alabaster.css new file mode 100644 index 00000000..517d0b29 --- /dev/null +++ b/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..30fee9d0 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/custom.css b/_static/custom.css new file mode 100644 index 00000000..2a924f1d --- /dev/null +++ b/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..d06a71d7 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 00000000..7e4c114f --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/_static/language_data.js b/_static/language_data.js new file mode 100644 index 00000000..250f5665 --- /dev/null +++ b/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 00000000..57c7df37 --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,84 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight .g { color: #000000 } /* Generic */ +.highlight .k { color: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #582800 } /* Operator */ +.highlight .x { color: #000000 } /* Other */ +.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8f5902 } /* Comment.Preproc */ +.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #a40000 } /* Generic.Deleted */ +.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight .ges { color: #000000 } /* Generic.EmphStrong */ +.highlight .gr { color: #ef2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* Generic.Prompt */ +.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #990000 } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* Name.Decorator */ +.highlight .ni { color: #ce5c00 } /* Name.Entity */ +.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000000 } /* Name.Function */ +.highlight .nl { color: #f57900 } /* Name.Label */ +.highlight .nn { color: #000000 } /* Name.Namespace */ +.highlight .nx { color: #000000 } /* Name.Other */ +.highlight .py { color: #000000 } /* Name.Property */ +.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight .mb { color: #990000 } /* Literal.Number.Bin */ +.highlight .mf { color: #990000 } /* Literal.Number.Float */ +.highlight .mh { color: #990000 } /* Literal.Number.Hex */ +.highlight .mi { color: #990000 } /* Literal.Number.Integer */ +.highlight .mo { color: #990000 } /* Literal.Number.Oct */ +.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ +.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000000 } /* Name.Function.Magic */ +.highlight .vc { color: #000000 } /* Name.Variable.Class */ +.highlight .vg { color: #000000 } /* Name.Variable.Global */ +.highlight .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000000 } /* Name.Variable.Magic */ +.highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 00000000..7918c3fa --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,574 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/genindex.html b/genindex.html new file mode 100644 index 00000000..c9c857f9 --- /dev/null +++ b/genindex.html @@ -0,0 +1,102 @@ + + + + + + + Index — Project Combine documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..9181bb4d --- /dev/null +++ b/index.html @@ -0,0 +1,111 @@ + + + + + + + + Project Combine — Project Combine documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Project Combine

+
+

Contents:

+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..5a8d9128f7e6e20c02a5f6d12613846df3a3f62b GIT binary patch literal 379 zcmY#Z2rkIT%&Sny%qvUHE6FdaR47X=D$dN$Q!wIERtPA{&q_@$v4Sxaobz*&GV@Y_ zQehBfRti9NNJgqcQEF~tW?o8akwSi&LP`i>SATB&2``exACsQVeeOY#5qGdHh zV@~#KCrOVi?erjf|I7@5Z)vHk6HoN-s!zDdshxf9CEE_+tCk*8hSsmr_p~e#F5mw8 z>#Beo3z*}Us~p*_8=>)9amBoXwFj;-dPnYiE9?Dm?mzdM< + + + + + + Search — Project Combine documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 00000000..5ff7f26e --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["index", "xc9500/bitstream-xc9500", "xc9500/bitstream-xc9500xl", "xc9500/index", "xc9500/intro", "xc9500/jtag", "xc9500/structure"], "filenames": ["index.rst", "xc9500/bitstream-xc9500.rst", "xc9500/bitstream-xc9500xl.rst", "xc9500/index.rst", "xc9500/intro.rst", "xc9500/jtag.rst", "xc9500/structure.rst"], "titles": ["Project Combine", "Bitstream structure - XC9500", "Bitstream structure \u2014 XC9500XL/XV", "XC9500, XC9500XL, XC9500XV", "Introduction", "JTAG interface", "Device structure"], "terms": {"xc9500": [0, 2, 4], "xc9500xl": [0, 4], "xc9500xv": [0, 4, 5, 6], "On": [1, 2, 6], "high": [1, 2, 5, 6], "level": [1, 2], "whole": [1, 2], "i": [1, 2, 4, 5, 6], "split": [1, 2], "area": [1, 2], "each": [1, 2, 4, 6], "devic": [1, 2, 3, 5], "correspond": [1, 2, 4, 5, 6], "two": [1, 4, 6], "one": [1, 2, 6], "which": [1, 5, 6], "contain": [1, 4], "configur": [1, 3, 4], "other": [1, 4, 5, 6], "main": [1, 2, 6], "everyth": [1, 2], "els": [1, 2, 6], "The": [1, 2, 4, 5, 6], "made": [1, 2, 6], "72": [1, 2], "row": [1, 2], "15": [1, 2], "column": [1, 2], "6": [1, 2, 4, 5], "8": [1, 2, 4, 5], "0": [1, 2, 4, 5, 6], "ar": [1, 2, 4, 5, 6], "while": [1, 2, 5], "9": [1, 2, 5], "14": [1, 2], "low": [1, 2, 6], "everi": [1, 2, 5], "us": [1, 2, 5, 6], "store": [1, 2, 5], "mask": [1, 2], "2": [1, 2, 4, 5, 6], "turn": 1, "subarea": 1, "18": [1, 2, 5, 6], "5": [1, 2, 5, 6], "1": [1, 2, 4, 5, 6], "4": [1, 2, 4, 5, 6], "7": [1, 2, 5], "make": 1, "36": [1, 2, 4, 6], "total": 1, "when": [1, 2, 5, 6], "program": [1, 2, 3, 6], "read": [1, 2, 6], "via": [1, 2, 6], "jtag": [1, 2, 3, 6], "transmit": [1, 2], "byte": [1, 2, 5], "long": [1, 2, 5], "ha": [1, 2, 4, 6], "its": [1, 2, 6], "address": [1, 2, 5], "Not": [1, 2, 6], "all": [1, 2, 4, 5, 6], "valid": [1, 2, 5], "contigu": [1, 2], "17": [1, 2, 5, 6], "sever": [1, 2, 6], "field": [1, 2], "13": [1, 2], "16": [1, 2, 4, 5, 6], "index": [1, 2, 6], "12": [1, 2, 4], "kind": 1, "config": [1, 2], "11": [1, 2], "3": [1, 2, 4, 5, 6], "sourc": [1, 6], "unprogram": [1, 2], "state": [1, 2, 5, 6], "thu": [1, 2, 6], "whenev": [1, 2], "boolean": [1, 2], "mention": [1, 2], "document": [1, 2], "true": [1, 2, 6], "valu": [1, 2, 5, 6], "actual": [1, 2], "repres": [1, 2], "thi": [1, 6], "includ": [1, 5, 6], "usercod": [1, 2, 5, 6], "In": [1, 2, 6], "simpli": [1, 2], "concaten": [1, 2], "order": [1, 2], "skip": [1, 2], "over": [1, 2], "invalid": [1, 2], "pad": [1, 2, 6], "have": [1, 2, 4, 5, 6], "nativ": [1, 2], "size": [1, 2], "convert": [1, 2], "from": [1, 2, 4, 6], "involv": [1, 2, 6], "some": [1, 2, 4, 5, 6], "complex": [1, 2], "calcul": [1, 2], "main_row_bit": 1, "uim_row_bit": 1, "main_area_bit": 1, "uim_subarea_bit": 1, "uim_area_bit": 1, "num_fb": [1, 2, 5], "fb_bit": 1, "total_bit": [1, 2], "def": [1, 2], "jed_to_jtag": [1, 2], "return": [1, 2], "jtag_to_j": [1, 2], "addr": [1, 2], "0xf": 1, "assert": [1, 2], "0x7f": [1, 2], "col_hi": [1, 2], "col_lo": [1, 2], "cfuse": [1, 2], "0x1f": 1, "formula": [1, 2], "follow": [1, 2, 4, 5, 6], "mc": [1, 2, 5, 6], "j": [1, 2, 5, 6], "pt": [1, 2], "k": [1, 2, 6], "im": [1, 2, 6], "l": [1, 2, 6], "p": [1, 2, 6], "n": [1, 2, 6], "54": [1, 4, 6], "function": [1, 2, 4, 5, 6], "mc_idx": [1, 2], "alloc": [1, 2, 6], "19": [1, 2], "20": [1, 2, 4], "21": [1, 2], "22": [1, 2], "inv": [1, 2, 6], "23": [1, 2], "import_up_alloc": [1, 2, 6], "24": [1, 2], "import_down_alloc": [1, 2, 6], "25": [1, 2], "export_dir": [1, 2, 6], "26": [1, 2, 5], "sum_hp": [1, 2, 6], "27": [1, 2, 5], "iob_oe_mux": [1, 6], "28": [1, 2], "29": [1, 2], "oe_mux": [1, 2, 6], "30": [1, 2, 4], "31": [1, 2], "32": [1, 2, 6], "34": [1, 2], "unus": [1, 2, 6], "35": [1, 2], "out_mux": [1, 2, 6], "clk_mux": [1, 2, 6], "37": [1, 2], "38": [1, 2], "39": [1, 2], "40": [1, 2], "reg_mod": [1, 2, 6], "41": [1, 2], "rst_mux": [1, 2, 6], "42": [1, 2], "set_mux": [1, 2, 6], "43": [1, 2], "init": [1, 2, 6], "44": [1, 2], "uim_oe_mux": [1, 6], "45": [1, 2], "46": [1, 2], "uim_out_inv": [1, 6], "47": [1, 2], "48": [1, 2], "gnd": [1, 2, 6], "49": [1, 2], "slew": [1, 2, 6], "50": [1, 2], "hp": [1, 2, 6], "51": 1, "52": 1, "53": 1, "combin": [1, 2, 6], "assign": [1, 2], "none": [1, 2, 6], "10": [1, 2, 5], "or_main": [1, 2, 6], "01": [1, 2], "or_export": [1, 2, 6], "00": [1, 2], "special": [1, 2, 6], "import_": [1, 2, 6], "_alloc": [1, 2], "up": [1, 2, 3, 5], "down": [1, 2, 6], "vcc": [1, 6], "comb": [1, 2, 6], "ff": [1, 2, 4, 6], "111": 1, "110": 1, "foe0": [1, 6], "101": 1, "foe1": [1, 6], "100": 1, "foe2": [1, 6], "011": 1, "foe3": [1, 6], "fclk1": [1, 2, 6], "fclk2": [1, 2, 6], "fclk0": [1, 2, 6], "dff": [1, 2, 6], "tff": [1, 2, 6], "fsr": [1, 2, 6], "slow": [1, 2, 6], "fast": [1, 2, 6], "fals": [1, 2], "mux": [1, 2, 6], "configuraton": [1, 2], "55": 1, "66": 1, "exact": [1, 2, 6], "irregular": [1, 2], "should": [1, 2, 6], "obtain": [1, 2], "databas": [1, 2], "67": 1, "68": 1, "export_en": [1, 2, 6], "pullup_dis": [1, 2, 6], "fsr_inv": [1, 2], "fclk": [1, 2, 4, 6], "foe": [1, 2, 4, 6], "gclk": [1, 6], "small": 1, "goe": [1, 6], "larg": 1, "invert": [1, 2, 6], "xc95288": [1, 4, 6], "ibuf_en": [1, 6], "an": [1, 6], "manner": 1, "duplic": 1, "twice": 1, "onc": [1, 2, 6], "purpos": [1, 5], "unknown": [1, 5], "consult": 1, "read_prot_a": 1, "read_prot_b": 1, "write_prot": [1, 2, 5, 6], "differ": [2, 6], "uim": [2, 3, 4], "wire": [2, 3, 4, 6], "AND": [2, 3, 4, 6], "complet": [2, 4, 6], "gone": 2, "onli": [2, 5, 6], "exist": [2, 4, 5], "108": 2, "instead": [2, 4, 6], "sens": 2, "version": [2, 4, 6], "load": [2, 5], "sequenti": 2, "parallel": 2, "unit": 2, "word": [2, 5, 6], "likewis": [2, 6], "interleav": 2, "row_bit": 2, "unchang": 2, "now": [2, 4], "more": [2, 6], "oe_inv": [2, 6], "33": 2, "clk_inv": [2, 6], "ce_mux": [2, 6], "pt2": [2, 6], "pt3": [2, 6], "76": 2, "coordin": [2, 6], "otherwis": [2, 6], "78": 2, "enabl": [2, 3, 4, 5, 6], "en": [2, 6], "keeper": [2, 3, 4], "directli": [2, 6], "read_prot": [2, 5, 6], "introduct": 3, "packag": [3, 6], "structur": 3, "overview": 3, "fb": [3, 5], "input": [3, 4, 5], "xv": 3, "global": 3, "fuse": 3, "product": 3, "term": 3, "sum": 3, "xor": 3, "gate": 3, "flip": 3, "flop": 3, "macrocel": 3, "output": [3, 5], "buffer": 3, "pull": [3, 5], "bu": [3, 4], "network": 3, "misc": 3, "bitstream": [3, 4, 5, 6], "jed": 3, "format": 3, "map": [3, 6], "per": [3, 4, 6], "bit": [3, 4, 5, 6], "protect": [3, 6], "done": [3, 4, 5, 6], "interfac": 3, "ir": 3, "boundari": 3, "scan": 3, "regist": [3, 6], "isp": 3, "instruct": [3, 6], "sequenc": [3, 6], "famili": [4, 6], "flash": 4, "base": 4, "cpld": [4, 6], "manufactur": 4, "xilinx": 4, "It": [4, 6], "deriv": 4, "earlier": 4, "xc7200": 4, "xc7300": 4, "epld": 4, "come": [4, 6], "three": [4, 6], "variant": 4, "5v": 4, "core": [4, 6], "logic": [4, 6], "3v": 4, "o": [4, 6], "origin": 4, "toler": 4, "chang": 4, "longer": 4, "clock": [4, 5, 6], "block": [4, 6], "polar": [4, 6], "multiplex": 4, "invers": [4, 6], "been": 4, "remov": 4, "option": [4, 6], "weak": [4, 5, 6], "can": [4, 5, 6], "pin": [4, 6], "8v": 4, "minor": 4, "larger": [4, 6], "bank": 4, "separ": 4, "vccio": 4, "ti": 4, "isc_don": 4, "prevent": 4, "problem": 4, "partial": 4, "xc9536": [4, 6], "xc9572": [4, 6], "xc95108": [4, 6], "xc95144": [4, 6], "xc95216": [4, 6], "xc9536xl": 4, "xc9572xl": 4, "xc95144xl": 4, "xc95288xl": 4, "xa9536xl": 4, "xa9572xl": 4, "xa95144xl": 4, "xc9536xv": 4, "xc9572xv": 4, "xc95144xv": 4, "xc95288xv": 4, "part": 4, "start": [4, 5], "xa": 4, "automot": 4, "thei": 4, "ident": 4, "xc": 4, "plcc": 4, "pc44": 4, "jedec": 4, "mo": 4, "047": 4, "pc84": 4, "qfp": 4, "veri": [4, 6], "thin": 4, "1mm": 4, "thick": 4, "vq44": 4, "8mm": 4, "pitch": 4, "m": 4, "026": 4, "acb": 4, "vq64": 4, "5mm": 4, "acd": 4, "4mm": 4, "tq100": 4, "bed": 4, "tq144": 4, "bfb": 4, "plastic": 4, "pq100": 4, "7mm": 4, "non": [4, 6], "squar": 4, "65mm": 4, "022": 4, "gc1": 4, "pq160": 4, "dd1": 4, "pq208": 4, "029": 4, "fa": 4, "platic": 4, "heat": 4, "sink": 4, "hq208": 4, "same": [4, 6], "footprint": 4, "bga": 4, "standard": [4, 6], "27mm": 4, "bg256": 4, "034": 4, "bal": 4, "bg352": 4, "fine": 4, "fg256": 4, "chip": [4, 6], "scale": 4, "cs48": 4, "cs144": 4, "216": 4, "bag": 4, "cs280": 4, "x": 4, "compat": 4, "maintain": 4, "across": [4, 6], "within": [4, 6], "singl": [4, 6], "addition": [4, 6], "note": 5, "00000000": 5, "extest": 5, "00000001": 5, "sampl": 5, "00000010": 5, "intest": 5, "11100101": 5, "fblank": 5, "ispaddress": 5, "11101000": 5, "ispen": 5, "11101001": 5, "ispenc": 5, "11101010": 5, "fpgm": 5, "ispconfigur": 5, "11101011": 5, "fpgmi": 5, "ispdata": 5, "11101100": 5, "feras": 5, "11101101": 5, "fbulk": 5, "11101110": 5, "fvfy": 5, "11101111": 5, "fvfyi": 5, "11110000": 5, "ispex": 5, "bypass": 5, "11111010": 5, "clamp": 5, "11111100": 5, "highz": 5, "11111101": 5, "11111110": 5, "idcod": 5, "11111111": 5, "statu": 5, "const": [5, 6], "verifi": [5, 6], "consist": [5, 6], "Such": 5, "even": 5, "do": [5, 6], "iob": [5, 6], "indic": 5, "bc_1": 5, "type": 5, "cell": 5, "detail": 5, "connect": [5, 6], "semant": [5, 6], "content": 5, "unclear": 5, "strobe": 5, "data": 5, "subset": [5, 6], "autoincr": 5, "describ": 5, "num_sb": 5, "befor": [5, 6], "ani": [5, 6], "readout": 5, "need": [5, 6], "put": 5, "For": 5, "both": [5, 6], "Its": 5, "mean": [5, 6], "To": [5, 6], "shift": 5, "go": [5, 6], "run": 5, "test": 5, "idl": 5, "least": [5, 6], "If": [5, 6], "z": 5, "activ": [5, 6], "signal": [5, 6], "snapshot": 5, "continu": 5, "drive": [5, 6], "last": [5, 6], "initi": [5, 6], "itself": 5, "normal": [5, 6], "oper": 5, "see": 5, "anyth": 5, "figur": [5, 6], "out": [5, 6], "about": 5, "write": [5, 6], "me": 5, "univers": 6, "interconnect": 6, "matrix": 6, "rout": 6, "routabl": 6, "power": 6, "perform": 6, "mode": 6, "router": 6, "neighbour": 6, "oe": 6, "rst": 6, "set": 6, "clk": 6, "ce": 6, "depend": 6, "borrow": 6, "between": 6, "dedic": 6, "freeli": 6, "async": 6, "reset": 6, "select": 6, "combinatori": 6, "rate": 6, "programm": 6, "ground": 6, "hardwir": 6, "alwai": 6, "gsr": 6, "meant": 6, "unconfigur": 6, "name": 6, "quit": 6, "appropri": 6, "intern": 6, "than": 6, "arbitrari": 6, "entir": 6, "togeth": 6, "emul": 6, "tri": 6, "buse": 6, "howev": 6, "less": 6, "extern": 6, "given": 6, "feedback": 6, "path": 6, "straight": 6, "redund": 6, "much": 6, "faster": 6, "we": 6, "call": 6, "control": 6, "what": 6, "empti": 6, "constant": 6, "second": 6, "relev": 6, "fbk_mc": 6, "through": 6, "pad_fb": 6, "_mc": 6, "allow": 6, "don": 6, "t": 6, "particip": 6, "out_uim": 6, "These": 6, "check": 6, "fbk": 6, "doesn": 6, "realli": 6, "classic": 6, "design": 6, "determin": 6, "exactli": 6, "90": 6, "them": 6, "form": 6, "individu": 6, "affect": 6, "propag": 6, "time": 6, "most": 6, "destin": 6, "": 6, "OR": 6, "four": 6, "equal": 6, "end": 6, "export_": 6, "direct": 6, "toward": 6, "lower": 6, "number": 6, "wraparound": 6, "higher": 6, "accordingli": 6, "import_down": 6, "export_down": 6, "import_up": 6, "export_up": 6, "A": 6, "either": 6, "further": 6, "downward": 6, "upward": 6, "work": 6, "abov": 6, "whose": 6, "d": 6, "potenti": 6, "ie": 6, "negedg": 6, "substitut": 6, "case": 6, "endcas": 6, "pretend": 6, "usual": 6, "synth": 6, "sim": 6, "mismatch": 6, "happen": 6, "posedg": 6, "particular": 6, "v": 6, "shenanigan": 6, "also": 6, "uim_o": 6, "iob_o": 6, "place": 6, "implement": 6, "tristat": 6, "conjunct": 6, "except": 6, "associ": 6, "suppos": 6, "unset": 6, "being": 6, "regardless": 6, "xl": 6, "addit": 6, "thing": 6, "resistor": 6, "disabl": 6, "pre": 6, "driven": 6, "g": 6, "gclk0": 6, "gclk1": 6, "gclk2": 6, "goe0": 6, "goe1": 6, "goe2": 6, "goe3": 6, "vari": 6, "similarli": 6, "doe": 6, "readabl": 6, "read_prot_": 6, "b": 6, "eras": 6, "mark": 6, "fulli": 6, "boot": 6, "due": 6, "after": 6}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"project": 0, "combin": 0, "content": [0, 3], "bitstream": [1, 2], "structur": [1, 2, 6], "xc9500": [1, 3, 5, 6], "jed": [1, 2], "format": [1, 2], "map": [1, 2], "fuse": [1, 2, 5, 6], "product": [1, 2, 6], "term": [1, 2, 6], "macrocel": [1, 2, 6], "fb": [1, 2, 6], "input": [1, 2, 6], "per": [1, 2], "bit": [1, 2], "global": [1, 2, 6], "buffer": [1, 6], "enabl": 1, "protect": [1, 2], "uim": [1, 6], "wire": 1, "AND": 1, "xc9500xl": [2, 3, 5, 6], "xv": [2, 5, 6], "done": 2, "xc9500xv": 3, "introduct": 4, "devic": [4, 6], "packag": 4, "jtag": 5, "interfac": 5, "ir": 5, "todo": [5, 6], "boundari": 5, "scan": 5, "regist": 5, "isp": 5, "instruct": 5, "dr": 5, "enter": 5, "exit": 5, "mode": 5, "eras": 5, "program": 5, "read": 5, "blank": 5, "check": 5, "sequenc": 5, "overview": 6, "pt": 6, "import": 6, "export": 6, "sum": 6, "xor": 6, "gate": 6, "flip": 6, "flop": 6, "output": 6, "configur": 6, "pull": 6, "up": 6, "bu": 6, "keeper": 6, "network": 6, "misc": 6}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx": 60}, "alltitles": {"Project Combine": [[0, "project-combine"]], "Contents:": [[0, null], [3, null]], "Bitstream structure - XC9500": [[1, "bitstream-structure-xc9500"]], "JED format mapping": [[1, "jed-format-mapping"], [2, "jed-format-mapping"]], "Fuses \u2014 product terms": [[1, "fuses-product-terms"], [2, "fuses-product-terms"]], "Fuses \u2014 macrocells": [[1, "fuses-macrocells"], [2, "fuses-macrocells"]], "Fuses \u2014 FB inputs": [[1, "fuses-fb-inputs"], [2, "fuses-fb-inputs"]], "Fuses \u2014 per-FB bits and globals": [[1, "fuses-per-fb-bits-and-globals"], [2, "fuses-per-fb-bits-and-globals"]], "Fuses \u2014 input buffer enable": [[1, "fuses-input-buffer-enable"]], "Fuses \u2014 protection bits": [[1, "fuses-protection-bits"]], "Fuses \u2014 UIM wire-AND": [[1, "fuses-uim-wire-and"]], "Bitstream structure \u2014 XC9500XL/XV": [[2, "bitstream-structure-xc9500xl-xv"]], "Fuses \u2014 protection bits, DONE": [[2, "fuses-protection-bits-done"]], "XC9500, XC9500XL, XC9500XV": [[3, "xc9500-xc9500xl-xc9500xv"]], "Introduction": [[4, "introduction"]], "Devices": [[4, "devices"]], "Packages": [[4, "packages"]], "JTAG interface": [[5, "jtag-interface"]], "IR": [[5, "ir"]], "Todo": [[5, "id1"], [5, "id2"], [5, "id3"], [5, "id4"], [5, "id5"], [5, "id6"], [5, "id7"], [5, "id8"], [5, "id9"], [6, "id1"], [6, "id2"], [6, "id3"], [6, "id4"], [6, "id5"], [6, "id6"], [6, "id7"], [6, "id8"], [6, "id9"], [6, "id10"], [6, "id11"], [6, "id12"]], "Boundary scan register": [[5, "boundary-scan-register"]], "ISP instructions": [[5, "isp-instructions"]], "ISP DR registers \u2014 XC9500": [[5, "isp-dr-registers-xc9500"]], "ISP DR registers \u2014 XC9500XL/XV": [[5, "isp-dr-registers-xc9500xl-xv"]], "Entering and exiting ISP mode": [[5, "entering-and-exiting-isp-mode"]], "Erasing fuses": [[5, "erasing-fuses"]], "Programming fuses": [[5, "programming-fuses"]], "Reading fuses": [[5, "reading-fuses"]], "Blank check": [[5, "blank-check"]], "Programming sequence": [[5, "programming-sequence"]], "Device structure": [[6, "device-structure"]], "Overview": [[6, "overview"]], "UIM and FB inputs \u2014 XC9500": [[6, "uim-and-fb-inputs-xc9500"]], "UIM and FB inputs \u2014 XC9500XL/XV": [[6, "uim-and-fb-inputs-xc9500xl-xv"]], "FB global fuses": [[6, "fb-global-fuses"]], "Product terms": [[6, "product-terms"]], "PT import/export": [[6, "pt-import-export"]], "Sum term, XOR gate": [[6, "sum-term-xor-gate"]], "Flip-flop": [[6, "flip-flop"]], "Macrocell output \u2014 XC9500": [[6, "macrocell-output-xc9500"]], "Macrocell output \u2014 XC9500XL/XV": [[6, "macrocell-output-xc9500xl-xv"]], "Input/output buffer": [[6, "input-output-buffer"]], "Configuration pull-ups": [[6, "configuration-pull-ups"]], "XC9500XL/XV bus keeper": [[6, "xc9500xl-xv-bus-keeper"]], "Global networks \u2014 XC9500": [[6, "global-networks-xc9500"]], "Global networks \u2014 XC9500XL/XV": [[6, "global-networks-xc9500xl-xv"]], "Misc configuration": [[6, "misc-configuration"]]}, "indexentries": {}}) \ No newline at end of file diff --git a/xc9500/bitstream-xc9500.html b/xc9500/bitstream-xc9500.html new file mode 100644 index 00000000..c84650cf --- /dev/null +++ b/xc9500/bitstream-xc9500.html @@ -0,0 +1,543 @@ + + + + + + + + Bitstream structure - XC9500 — Project Combine documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Bitstream structure - XC9500

+

On a high level, the whole bitstream is split into “areas”. Each FB +of the device corresponds two areas, one of which contains the UIM wire-AND +configuration, and the other (main area) contains everything else.

+

The main area of a FB is made of 72 “rows”. Each row is made of 15 “columns”. +Each column is made of 6 or 8 bits: columns 0-8 are made of 8 bits, while +columns 9-14 are made of 6 bits.

+

The low 6 bits of every column are used to store product term masks, and +the high 2 bits of columns 0-8 are used to store everything else.

+

The UIM wire-AND area of a FB is, in turn, made of “subareas”, one for each +FB of the device. Each subarea is in turn made of 18 rows. Each row +is made of 5 columns. Column 0 is made of 8 bits, while columns 1-4 are made +of 7 bits, making for 36 total bits per row.

+

When programmed or read via JTAG, the bitstream is transmitted as bytes, +which are 6-8 bits long. Each byte of the bitstream has its address. +Not all addresses are valid, and valid addresses are not contiguous. +Address is 17 bits long, and is split to several fields:

+
    +
  • bits 13-16: FB index

  • +
  • bit 12: area kind

    +
      +
    • 0: main FB config

    • +
    • 1: UIM wire-AND config

    • +
    +
  • +
  • for main FB config area:

    +
      +
    • bits 5-11: row

    • +
    • bits 3-4: column / 5

    • +
    • bits 0-2: column % 5

    • +
    +
  • +
  • for UIM wire-AND config area:

    +
      +
    • bits 8-11: subarea (source FB index)

    • +
    • bits 3-7: row

    • +
    • bits 0-2: column

    • +
    +
  • +
+

The unprogrammed state of a bit on XC9500 is 1. +The programmed state is 0. Thus, whenever a boolean fuse is mentioned +in the documentation, the “true” value is actually represented as 0 +in the bitstream. This includes the USERCODE bits.

+
+

JED format mapping

+

In the JED format, all fuses of the device are simply concatenated in order, +skipping over invalid addresses. The bytes are not padded to 8 bits, but +have their native size. Thus, converting from JED fuse index to device +address involves some complex calculations:

+
main_row_bits = 8 * 9 + 6 * 6
+uim_row_bits = 8 + 7 * 4
+main_area_bits = main_row_bits * 72
+uim_subarea_bits = uim_row_bits * 18
+uim_area_bits = uim_subarea_bits * device.num_fbs
+fb_bits = main_area_bits + uim_area_bits
+total_bits = fb_bits * device.num_fbs
+
+def jed_to_jtag(fuse):
+    fb = fuse // fb_bits
+    fuse %= fb_bits
+    if fuse < main_area_bits:
+        row = fuse // main_row_bits
+        fuse %= main_row_bits
+        if fuse < 8 * 9:
+            column = fuse // 8
+            bit = fuse % 8
+        else:
+            fuse -= 8 * 9
+            column = 9 + fuse // 6
+            bit = fuse % 6
+        return (
+            fb << 13 |
+            0 << 12 |
+            row << 5 |
+            (column // 5) << 3 |
+            (column % 5)
+        ), bit
+    else:
+        fuse -= main_area_bits
+        subarea = fuse // uim_subarea_bits
+        fuse %= uim_subarea_bits
+        row = fuse // uim_row_bits
+        fuse %= uim_row_bits
+        if fuse < 8:
+            column = 0
+            bit = fuse
+        else:
+            fuse -= 8
+            column = 1 + fuse // 7
+            bit = fuse % 7
+        return (
+            fb << 13 |
+            1 << 12 |
+            subarea << 8 |
+            row << 3 |
+            column
+        ), bit
+
+def jtag_to_jed(addr, bit):
+    fb = addr >> 13 & 0xf
+    assert fb < device.num_fbs
+    if addr & (1 << 12):
+        row = addr >> 5 & 0x7f
+        assert row < 72
+        col_hi = addr >> 3 & 3
+        assert col_hi < 3
+        col_lo = addr & 7
+        assert col_lo < 5
+        column = col_hi * 5 + col_lo
+        if column < 9:
+            cfuse = column * 8 + bit
+        else:
+            cfuse = 8 * 8 + (column - 9) * 6 + bit
+        return fb * fb_bits + row * main_row_bits + cfuse
+    else:
+        subarea = addr >> 8 & 0xf
+        assert subarea < device.num_fbs
+        row = addr >> 3 & 0x1f
+        assert row < 18
+        column = addr & 7
+        assert column < 5
+        if column == 0:
+            cfuse = bit
+        else:
+            cfuse = 8 + (column - 1) * 7 + bit
+        return fb * fb_bits + main_area_bits + subarea * uim_subarea_bits + row * uim_row_bits + cfuse
+
+
+
+
+

Fuses — product terms

+

The product term masks are stored in bits 0-5 of every column and every row of the main area. +The formulas are as follows:

+
    +
  1. FB[i].MC[j].PT[k].IM[l].P is stored at:

    +
      +
    • row: l * 2

    • +
    • column: k + (j % 3) * 5

    • +
    • bit: j // 3

    • +
    +
  2. +
  3. FB[i].MC[j].PT[k].IM[l].N is stored at:

    +
      +
    • row: l * 2

    • +
    • column: k + (j % 3) * 5

    • +
    • bit: j // 3

    • +
    +
  4. +
+
+
+

Fuses — macrocells

+

Per-MC config fuses (that are not product term masks) are stored in bits 6-7 of +columns 0-8 of rows 12-54 of the main area. The formulas are as follows:

+
    +
  • row: corresponds to fuse function

  • +
  • column: mc_idx % 9

  • +
  • bit: 6 + mc_idx // 9

  • +
+

The row is:

+
    +
  • 12: PT[0].ALLOC bit 0

  • +
  • 13: PT[0].ALLOC bit 1

  • +
  • 14: PT[1].ALLOC bit 0

  • +
  • 15: PT[1].ALLOC bit 1

  • +
  • 16: PT[2].ALLOC bit 0

  • +
  • 17: PT[2].ALLOC bit 1

  • +
  • 18: PT[3].ALLOC bit 0

  • +
  • 19: PT[3].ALLOC bit 1

  • +
  • 20: PT[4].ALLOC bit 0

  • +
  • 21: PT[5].ALLOC bit 1

  • +
  • 22: INV

  • +
  • 23: IMPORT_UP_ALLOC

  • +
  • 24: IMPORT_DOWN_ALLOC

  • +
  • 25: EXPORT_DIR

  • +
  • 26: SUM_HP

  • +
  • 27: IOB_OE_MUX bit 0

  • +
  • 28: IOB_OE_MUX bit 1

  • +
  • 29: OE_MUX bit 0

  • +
  • 30: OE_MUX bit 1

  • +
  • 31: OE_MUX bit 2

  • +
  • 32-34: unused?

  • +
  • 35: OUT_MUX

  • +
  • 36: CLK_MUX bit 0

  • +
  • 37: CLK_MUX bit 1

  • +
  • 38-39: unused

  • +
  • 40: REG_MODE

  • +
  • 41: RST_MUX

  • +
  • 42: SET_MUX

  • +
  • 43: INIT

  • +
  • 44: UIM_OE_MUX bit 0

  • +
  • 45: UIM_OE_MUX bit 1

  • +
  • 46: UIM_OUT_INV

  • +
  • 47: unused

  • +
  • 48: GND

  • +
  • 49: SLEW

  • +
  • 50: PT[0].HP

  • +
  • 51: PT[1].HP

  • +
  • 52: PT[2].HP

  • +
  • 53: PT[3].HP

  • +
  • 54: PT[4].HP

  • +
+

The fuse combination assignments are:

+
    +
  • PT[*].ALLOC:

    +
      +
    • 11: NONE

    • +
    • 10: OR_MAIN

    • +
    • 01: OR_EXPORT

    • +
    • 00: SPECIAL

    • +
    +
  • +
  • IMPORT_*_ALLOC:

    +
      +
    • 1: OR_EXPORT

    • +
    • 0: OR_MAIN

    • +
    +
  • +
  • EXPORT_DIR:

    +
      +
    • 1: UP

    • +
    • 0: DOWN

    • +
    +
  • +
  • IOB_OE_MUX:

    +
      +
    • 11: GND

    • +
    • 10: OE_MUX

    • +
    • 01: VCC

    • +
    +
  • +
  • OUT_MUX:

    +
    +
      +
    • 1: COMB

    • +
    • 0: FF

    • +
    +
    +
  • +
  • OE_MUX:

    +
    +
      +
    • 111: PT

    • +
    • 110: FOE0

    • +
    • 101: FOE1

    • +
    • 100: FOE2

    • +
    • 011: FOE3

    • +
    +
    +
  • +
  • CLK_MUX:

    +
      +
    • 11: FCLK1

    • +
    • 10: FCLK2

    • +
    • 01: FCLK0

    • +
    • 00: PT

    • +
    +
  • +
  • REG_MODE:

    +
      +
    • 1: DFF

    • +
    • 0: TFF

    • +
    +
  • +
  • RST_MUX, SET_MUX:

    +
      +
    • 1: PT

    • +
    • 0: FSR

    • +
    +
  • +
  • UIM_OE_MUX:

    +
      +
    • 11: OE_MUX

    • +
    • 10: GND

    • +
    • 01: VCC

    • +
    +
  • +
  • SLEW:

    +
      +
    • 1: SLOW

    • +
    • 0: FAST

    • +
    +
  • +
  • everything else:

    +
      +
    • 1: false

    • +
    • 0: true

    • +
    +
  • +
+
+
+

Fuses — FB inputs

+

The FB input mux configuraton is stored in rows 55-66, columns 0-8, bits 6-7. +The exact bit assignments are irregular and should be obtained from the database.

+
+
+

Fuses — per-FB bits and globals

+

Per-FB bits are stored in rows 67-68, columns 0-8, bits 6-7. The bits are (row, column, bit):

+
    +
  • (67, 0, 6): ENABLE

  • +
  • (67, 1, 6): EXPORT_ENABLE

  • +
  • (68, 6, 6): PULLUP_DISABLE

  • +
+

Global bits are stored in rows (0, 3, 4, 6, 7), columns 0-8, bits 6-7 of FB 0. The bits are (row, column, bit):

+
    +
  • (0, 1, 6): FSR_INV

  • +
  • (0, 2, 6): FCLK[0].INV

  • +
  • (0, 3, 6): FCLK[1].INV

  • +
  • (0, 4, 6): FCLK[2].INV

  • +
  • (0, 5, 6): FOE[0].INV

  • +
  • (0, 6, 6): FOE[1].INV

  • +
  • (0, 7, 6): FOE[2].INV

  • +
  • (0, 8, 6): FOE[3].INV

  • +
  • (3, 2, 6): FCLK[0].MUX bit 0

  • +
  • (3, 3, 6): FCLK[1].MUX bit 0

  • +
  • (3, 4, 6): FCLK[2].MUX bit 0

  • +
  • (3, 5, 6): FOE[0].MUX bit 0

  • +
  • (3, 6, 6): FOE[1].MUX bit 0

  • +
  • (3, 7, 6): FOE[2].MUX bit 0

  • +
  • (3, 8, 6): FOE[3].MUX bit 0

  • +
  • (4, 2, 6): FCLK[0].MUX bit 1

  • +
  • (4, 3, 6): FCLK[1].MUX bit 1

  • +
  • (4, 4, 6): FCLK[2].MUX bit 1

  • +
  • (4, 5, 6): FOE[0].MUX bit 1

  • +
  • (4, 6, 6): FOE[1].MUX bit 1

  • +
  • (4, 7, 6): FOE[2].MUX bit 1

  • +
  • (4, 8, 6): FOE[3].MUX bit 1

  • +
  • (6, i, j) for i < 8, j in (6, 7): USERCODE bit 16 + (7 - i) * 2 + (j - 6)

  • +
  • (7, i, j) for i < 8, j in (6, 7): USERCODE bit (7 - i) * 2 + (j - 6)

  • +
+

The fuse combination assignments are:

+
    +
  • FCLK[0].MUX:

    +
      +
    • 11: NONE

    • +
    • 10: GCLK[1]

    • +
    • 01: GCLK[0]

    • +
    +
  • +
  • FCLK[1].MUX:

    +
      +
    • 11: NONE

    • +
    • 10: GCLK[2]

    • +
    • 01: GCLK[1]

    • +
    +
  • +
  • FCLK[2].MUX:

    +
      +
    • 11: NONE

    • +
    • 10: GCLK[0]

    • +
    • 01: GCLK[2]

    • +
    +
  • +
  • FOE[0].MUX (small device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[1]

    • +
    • 01: GOE[0]

    • +
    +
  • +
  • FOE[1].MUX (small device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[0]

    • +
    • 01: GOE[1]

    • +
    +
  • +
  • FOE[0].MUX (large device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[1]

    • +
    • 01: GOE[0]

    • +
    +
  • +
  • FOE[1].MUX (large device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[2]

    • +
    • 01: GOE[1]

    • +
    +
  • +
  • FOE[2].MUX (large device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[3]

    • +
    • 01: GOE[2]

    • +
    +
  • +
  • FOE[3].MUX (large device):

    +
      +
    • 11: NONE

    • +
    • 10: GOE[0]

    • +
    • 01: GOE[3]

    • +
    +
  • +
  • USERCODE: each bit stored inverted

  • +
  • everything else:

    +
      +
    • 1: false

    • +
    • 0: true

    • +
    +
  • +
+
+
+

Fuses — input buffer enable

+

On XC95288, the IBUF_ENABLE fuses are stored in rows (1, 2, 5, 8, 9), +columns 0-8, bits 6-7 of FBs (0, 1, 14, 15) in an irregular manner. Each +fuse is duplicated twice: once in FBs (0, 1) and once in FBs (14, 15). +The purpose of this duplication is unknown. Consult the database for exact +bit assignments.

+
+
+

Fuses — protection bits

+

The protection bits are stored as follows (row, column, bit) in every FB:

+
    +
  • (11, 3, 6): READ_PROT_A

  • +
  • (68, 3, 6): READ_PROT_B

  • +
  • (68, 0, 6): WRITE_PROT

  • +
+
+
+

Fuses — UIM wire-AND

+

The FB[i].IM[j].UIM.FB[k].MC[l] fuse is stored at:

+
+
    +
  • subarea: k

  • +
  • row: l

  • +
  • column: j % 5

  • +
  • bit: j // 5

  • +
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/xc9500/bitstream-xc9500xl.html b/xc9500/bitstream-xc9500xl.html new file mode 100644 index 00000000..33391a09 --- /dev/null +++ b/xc9500/bitstream-xc9500xl.html @@ -0,0 +1,385 @@ + + + + + + + + Bitstream structure — XC9500XL/XV — Project Combine documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Bitstream structure — XC9500XL/XV

+

The main differences from XC9500 are:

+
    +
  1. The UIM wire-AND area is completely gone, only the main areas exist.

  2. +
  3. The main area has 108 rows per FB instead of 72.

  4. +
  5. Unprogrammed fuse state is 0, programmed fuse state is 1. +Thus, the sense of every bitstream bit is inverted from the XC9500 version.

  6. +
  7. While in XC9500 all areas are loaded sequentially, in XC9500XL/XV the areas +are loaded in parallel. Thus, the JTAG unit is not a byte, but a word of +size 8 * num_fbs. Likewise, the bytes for each FB are interleaved +in the JED format.

  8. +
+

On a high level, the whole bitstream is split into “areas”. Each FB +of the device corresponds to one area.

+

Each area is made of 108 “rows”. Each row is made of 15 “columns”. +Each column is made of 6 or 8 bits: columns 0-8 are made of 8 bits, while +columns 9-14 are made of 6 bits.

+

The low 6 bits of every column are used to store product term masks, and +the high 2 bits of columns 0-8 are used to store everything else.

+

When programmed or read via JTAG, the bitstream is transmitted as words. +Each word is 8 bits per FB. Each word of the bitstream has its address. +Not all addresses are valid, and valid addresses are not contiguous. +Address is 12 bits long, and is split to several fields:

+
    +
  • bits 5-11: row

  • +
  • bits 3-4: column / 5

  • +
  • bits 0-2: column % 5

  • +
+

The unprogrammed state of a bit on XC9500XL/XV is 0. +The programmed state is 1. Thus, whenever a boolean fuse is mentioned +in the documentation, the “true” value is actually represented as 1 +in the bitstream.

+
+

JED format mapping

+

In the JED format, all fuses of the device are simply concatenated in order, +skipping over invalid addresses. The bytes are not padded to 8 bits, but +have their native size. Thus, converting from JED fuse index to device +address involves some complex calculations:

+
row_bits = (8 * 9 + 6 * 6) * device.num_fbs
+total_bits = row_bits * 108
+
+def jed_to_jtag(fuse):
+    row = fuse // row_bits
+    fuse %= row_bits
+    if fuse < 8 * 9 * device.num_fbs:
+        column = fuse // (8 * device.num_fbs)
+        fuse %= (8 * device.num_fbs)
+        fb = fuse // 8
+        bit = fuse % 8
+    else:
+        fuse -= 8 * 9 * device.num_fbs
+        column = 9 + fuse // (6 * device.num_fbs)
+        fuse %= (6 * device.num_fbs)
+        fb = fuse // 6
+        bit = fuse % 6
+    return (
+        row << 5 |
+        (column // 5) << 3 |
+        (column % 5)
+    ), (fb * 8 + bit)
+
+def jtag_to_jed(addr, bit):
+    fb = bit // 8
+    bit %= 8
+    row = addr >> 5 & 0x7f
+    assert row < 108
+    col_hi = addr >> 3 & 3
+    assert col_hi < 3
+    col_lo = addr & 7
+    assert col_lo < 5
+    column = col_hi * 5 + col_lo
+    if column < 9:
+        cfuse = column * 8 * device.num_fbs + fb * 8 + bit
+    else:
+        cfuse = 8 * 8 + (column - 9) * 6 * device.num_fbs + fb * 6 + bit
+    return row * row_bits + cfuse
+
+
+
+
+

Fuses — product terms

+

The product term masks are stored in bits 0-5 of every column and every row of the main area. +The formulas are as follows (unchanged from XC9500, but now with more rows):

+
    +
  1. FB[i].MC[j].PT[k].IM[l].P is stored at:

    +
      +
    • row: l * 2

    • +
    • column: k + (j % 3) * 5

    • +
    • bit: j // 3

    • +
    +
  2. +
  3. FB[i].MC[j].PT[k].IM[l].N is stored at:

    +
      +
    • row: l * 2

    • +
    • column: k + (j % 3) * 5

    • +
    • bit: j // 3

    • +
    +
  4. +
+
+
+

Fuses — macrocells

+

Per-MC config fuses (that are not product term masks) are stored in bits 6-7 of +columns 0-8 of rows 12-49 of the main area. The formulas are as follows:

+
    +
  • row: corresponds to fuse function

  • +
  • column: mc_idx % 9

  • +
  • bit: 6 + mc_idx // 9

  • +
+

The row is:

+
    +
  • 12: PT[0].ALLOC bit 0

  • +
  • 13: PT[0].ALLOC bit 1

  • +
  • 14: PT[1].ALLOC bit 0

  • +
  • 15: PT[1].ALLOC bit 1

  • +
  • 16: PT[2].ALLOC bit 0

  • +
  • 17: PT[2].ALLOC bit 1

  • +
  • 18: PT[3].ALLOC bit 0

  • +
  • 19: PT[3].ALLOC bit 1

  • +
  • 20: PT[4].ALLOC bit 0

  • +
  • 21: PT[5].ALLOC bit 1

  • +
  • 22: INV

  • +
  • 23: IMPORT_UP_ALLOC

  • +
  • 24: IMPORT_DOWN_ALLOC

  • +
  • 25: EXPORT_DIR

  • +
  • 26: SUM_HP

  • +
  • 27: OE_MUX bit 0

  • +
  • 28: OE_MUX bit 1

  • +
  • 29: OE_MUX bit 2

  • +
  • 30: OE_INV

  • +
  • 31: unused

  • +
  • 32: OUT_MUX

  • +
  • 33: CLK_MUX bit 0

  • +
  • 34: CLK_MUX bit 1

  • +
  • 35: CLK_INV

  • +
  • 36: CE_MUX bit 0

  • +
  • 37: CE_MUX bit 1

  • +
  • 38: unused

  • +
  • 39: REG_MODE

  • +
  • 40: RST_MUX

  • +
  • 41: SET_MUX

  • +
  • 42: INIT

  • +
  • 43: GND

  • +
  • 44: SLEW

  • +
  • 45: PT[0].HP

  • +
  • 46: PT[1].HP

  • +
  • 47: PT[2].HP

  • +
  • 48: PT[3].HP

  • +
  • 49: PT[4].HP

  • +
+

The fuse combination assignments are:

+
    +
  • PT[*].ALLOC:

    +
      +
    • 00: NONE

    • +
    • 01: OR_MAIN

    • +
    • 10: OR_EXPORT

    • +
    • 11: SPECIAL

    • +
    +
  • +
  • IMPORT_*_ALLOC:

    +
      +
    • 0: OR_EXPORT

    • +
    • 1: OR_MAIN

    • +
    +
  • +
  • EXPORT_DIR:

    +
      +
    • 0: UP

    • +
    • 1: DOWN

    • +
    +
  • +
  • OUT_MUX:

    +
    +
      +
    • 0: COMB

    • +
    • 1: FF

    • +
    +
    +
  • +
  • CLK_MUX:

    +
      +
    • 00: FCLK1

    • +
    • 01: FCLK0

    • +
    • 10: FCLK2

    • +
    • 11: PT

    • +
    +
  • +
  • CE_MUX:

    +
      +
    • 00: NONE

    • +
    • 01: PT2

    • +
    • 10: PT3

    • +
    +
  • +
  • REG_MODE:

    +
      +
    • 0: DFF

    • +
    • 1: TFF

    • +
    +
  • +
  • RST_MUX, SET_MUX:

    +
      +
    • 0: PT

    • +
    • 1: FSR

    • +
    +
  • +
  • SLEW:

    +
      +
    • 0: SLOW

    • +
    • 1: FAST

    • +
    +
  • +
  • everything else:

    +
      +
    • 0: false

    • +
    • 1: true

    • +
    +
  • +
+
+
+

Fuses — FB inputs

+

The FB input mux configuraton is stored in rows 50-76, columns 0-8, bits 6-7. +FB[i].IM[j].MUX has 9 bits and is stored at the following coordinates:

+
    +
  • row: 50 + j % 27

  • +
  • column: mux fuse index (0-8)

  • +
  • bit: 6 if j < 27, 7 otherwise

  • +
+

The exact bit assignments are irregular and should be obtained from the database.

+
+
+

Fuses — per-FB bits and globals

+

Per-FB bits are stored in row 78, columns 0-8, bits 6-7. The bits are (row, column, bit):

+
    +
  • (78, 0, 6): ENABLE

  • +
  • (78, 1, 6): EXPORT_ENABLE

  • +
  • (78, 6, 6): PULLUP_DISABLE

  • +
+

Global bits are stored in rows (2, 6, 7), columns 0-8, bits 6-7 of FB 0. The bits are (row, column, bit):

+
    +
  • (2, 0, 6): FSR_INV

  • +
  • (2, 1, 6): FCLK[0].EN

  • +
  • (2, 2, 6): FCLK[1].EN

  • +
  • (2, 3, 6): FCLK[2].EN

  • +
  • (2, 4, 6): FOE[0].EN

  • +
  • (2, 5, 6): FOE[1].EN

  • +
  • (2, 6, 6): FOE[2].EN

  • +
  • (2, 7, 6): FOE[3].EN

  • +
  • (2, 8, 6): KEEPER

  • +
  • (6, i, j) for i < 8, j in (6, 7): USERCODE bit 16 + (7 - i) * 2 + (j - 6)

  • +
  • (7, i, j) for i < 8, j in (6, 7): USERCODE bit (7 - i) * 2 + (j - 6)

  • +
+

The fuse combination assignments are:

+
    +
  • USERCODE: each bit stored directly

  • +
  • everything else:

    +
      +
    • 0: false

    • +
    • 1: true

    • +
    +
  • +
+
+
+

Fuses — protection bits, DONE

+

The protection bits are stored as follows (row, column, bit) in every FB:

+
    +
  • (11, 0, 6): WRITE_PROT

  • +
  • (11, 3, 6): READ_PROT

  • +
+

The DONE bit is stored only once, in FB 0:

+
    +
  • (11, 6, 6): DONE

  • +
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/xc9500/index.html b/xc9500/index.html new file mode 100644 index 00000000..39cedc49 --- /dev/null +++ b/xc9500/index.html @@ -0,0 +1,162 @@ + + + + + + + + XC9500, XC9500XL, XC9500XV — Project Combine documentation + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xc9500/intro.html b/xc9500/intro.html new file mode 100644 index 00000000..dbe6eb21 --- /dev/null +++ b/xc9500/intro.html @@ -0,0 +1,607 @@ + + + + + + + + Introduction — Project Combine documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Introduction

+

XC9500 is a family of flash-based CPLDs manufactured by Xilinx. It is a derivative of the earlier XC7200 and XC7300 +EPLD families. It comes in three variants:

+
    +
  1. XC9500: 5V core logic, 3.3V or 5V I/O, original version.

  2. +
  3. XC9500XL: 3.3V core logic, 2.5V or 3.3V I/O (5V tolerant), with some functional changes from XC9500:

    +
      +
    • UIM no longer has wired-AND functionality

    • +
    • FFs have clock enable function

    • +
    • 54 (instead of 36) UIM inputs per function block

    • +
    • FF has configurable clock polarity

    • +
    • FOE/FCLK multiplexers and inversion have been removed

    • +
    • optional weak bus keeper can be configured for all pins

    • +
    +
  4. +
  5. XC9500XV: 2.5V core logic, 1.8V, 2.5V, or 3.3V I/O, with minor functional changes from XC9500XL:

    +
      +
    • larger devices have two I/O banks with separate VCCIO

    • +
    • the bitstream now contains a DONE bit tied to ISC_DONE, preventing problems with partially configured devices

    • +
    +
  6. +
+
+

Devices

+

The following devices exist:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Device

Variant

Function Blocks

XC9536

XC9500

2

XC9572

XC9500

4

XC95108

XC9500

6

XC95144

XC9500

8

XC95216

XC9500

12

XC95288

XC9500

16

XC9536XL

XC9500XL

2

XC9572XL

XC9500XL

4

XC95144XL

XC9500XL

8

XC95288XL

XC9500XL

16

XA9536XL

XC9500XL

2

XA9572XL

XC9500XL

4

XA95144XL

XC9500XL

8

XC9536XV

XC9500XV

2

XC9572XV

XC9500XV

4

XC95144XV

XC9500XV

8

XC95288XV

XC9500XV

16

+

The parts starting with XA are automotive versions. They are functionally completely identical to corresponding XC versions.

+
+
+

Packages

+

The devices come in the following packages:

+
    +
  • PLCC:

    +
      +
    • PC44 (JEDEC MO-047)

    • +
    • PC84 (JEDEC MO-047)

    • +
    +
  • +
  • QFP:

    +
      +
    • very thin QFP (1mm thickness):

      +
        +
      • VQ44 (0.8mm pitch; JEDEC MS-026-ACB)

      • +
      • VQ64 (0.5mm pitch; JEDEC MS-026-ACD)

      • +
      +
    • +
    • thin QFP (1.4mm thickness):

      +
        +
      • TQ100 (0.5mm pitch; JEDEC MS-026-BED)

      • +
      • TQ144 (0.5mm pitch; JEDEC MS-026-BFB)

      • +
      +
    • +
    • plastic QFP:

      +
        +
      • PQ100 (2.7mm thickness, non-square, 30×20 pins, 0.65mm pitch; JEDEC MS-022-GC1)

      • +
      • PQ160 (3.4mm thickness, 0.65mm pitch; JEDEC MS-022-DD1)

      • +
      • PQ208 (3.4mm thickness, 0.5mm pitch; JEDEC MS-029-FA-1)

      • +
      +
    • +
    • platic QFP with heat sink:

      +
        +
      • HQ208 (same footprint as PQ208)

      • +
      +
    • +
    +
  • +
  • BGA:

    +
      +
    • standard BGA (1.27mm pitch):

      +
        +
      • BG256 (JEDEC MS-034-BAL-2)

      • +
      • BG352

      • +
      +
    • +
    • fine-pitch BGA (1mm pitch):

      +
        +
      • FG256

      • +
      +
    • +
    • chip-scale BGA (0.8mm pitch):

      +
        +
      • CS48

      • +
      • CS144 (JEDEC MO-216-BAG-2)

      • +
      • CS280 (JEDEC MO-216-BAL-1)

      • +
      +
    • +
    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Device

PC44

PC84

VQ44

VQ64

TQ100

TQ144

PQ100

PQ160

PQ208

HQ208

BG256

BG352

FG256

CS48

CS144

CS280

XC9536

X

X

X

XC9572

X

X

X

X

XC95108

X

X

X

X

XC95144

X

X

X

XC95216

X

X

X

XC95288

X

X

XC9536XL

X

X

X

X

XC9572XL

X

X

X

X

X

XC95144XL

X

X

X

XC95288XL

X

X

X

X

X

XA9536XL

X

XA9572XL

X

X

X

XA95144XL

X

XC9536XV

X

X

X

XC9572XV

X

X

X

X

XC95144XV

X

X

X

XC95288XV

X

X

X

X

+

Pin compatibility is maintained across all 3 variants of the XC9500 family within a single package. +Additionally, devices in PQ208 and HQ208 packages are pin compatible with each other.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/xc9500/jtag.html b/xc9500/jtag.html new file mode 100644 index 00000000..586b549c --- /dev/null +++ b/xc9500/jtag.html @@ -0,0 +1,373 @@ + + + + + + + + JTAG interface — Project Combine documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

JTAG interface

+
+

IR

+

The IR is 8 bits long. The following instructions exist:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

IR

Instruction

Register

Notes

00000000

EXTEST

BOUNDARY

00000001

SAMPLE

BOUNDARY

00000010

INTEST

BOUNDARY

11100101

FBLANK

ISPADDRESS

XC9500XL/XV only

11101000

ISPEN

ISPENABLE

11101001

ISPENC

ISPENABLE

XC9500XL/XV only

11101010

FPGM

ISPCONFIGURATION

11101011

FPGMI

ISPDATA

11101100

FERASE

ISPCONFIGURATION

XC9500 only

11101100

FERASE

ISPADDRESS

XC9500XL/XV only

11101101

FBULK

ISPCONFIGURATION

XC9500 only

11101101

FBULK

ISPADDRESS

XC9500XL/XV only

11101110

FVFY

ISPCONFIGURATION

11101111

FVFYI

ISPDATA

11110000

ISPEX

BYPASS

11111010

CLAMP

BYPASS

XC9500XL/XV only

11111100

HIGHZ

BYPASS

11111101

USERCODE

USERCODE

11111110

IDCODE

IDCODE

11111111

BYPASS

BYPASS

+

The IR status is:

+
    +
  • bit 0: const 1

  • +
  • bit 1: const 0

  • +
  • bit 2: WRITE_PROT status

  • +
  • bit 3: READ_PROT status

  • +
  • bit 4: ISP mode enabled

  • +
  • bit 5: DONE status (XC9500XV only, const 0 on other devices)

  • +
  • bits 6-7: const 0

  • +
+
+

Todo

+

verify

+
+
+
+

Boundary scan register

+

The boundary scan register is 3 * 18 * num_fbs bits long, and consists of 3 bits for every MC +in the device: input, output, and output enable. Such bits are included even for MCs that do not +have a corresponding IOB.

+

The boundary register bit indices for FB[i].MC[j] are:

+
    +
  • input: (num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 2

  • +
  • output: (num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 1

  • +
  • output enable: (num_fbs - 1 - i) * 18 * 3 + (17 - j) * 3 + 0

  • +
+

All bits of the register are BC_1 type cells.

+
+

Todo

+

details on the cell connection, EXTEST, INTEST semantics

+
+
+
+

ISP instructions

+
+

ISP DR registers — XC9500

+

The following DR registers exist on XC9500:

+
    +
  1. ISPENABLE (16 bits): function and contents unclear

  2. +
  3. ISPCONFIGURATION (27 bits): used to load and store bitstream bytes

    +
      +
    • bit 0: valid bit

    • +
    • bit 1: strobe bit

    • +
    • bits 2-9: data byte

    • +
    • bits 10-26: address

    • +
    +
  4. +
  5. ISPDATA (10 bits): a subset of ISPCONFIGURATION used by instructions with autoincrementing address

    +
      +
    • bit 0: valid bit

    • +
    • bit 1: strobe bit

    • +
    • bits 2-9: data byte

    • +
    +
  6. +
+
+

Todo

+

ISPENABLE, describe valid & strobe

+
+
+
+

ISP DR registers — XC9500XL/XV

+

The following DR registers exist on XC9500XL/XV:

+
    +
  1. ISPENABLE (6 bits): function and contents unclear

  2. +
  3. ISPCONFIGURATION (18 + num_fbs * 8 bits): used to load and store bitstream words

    +
      +
    • bit 0: valid bit

    • +
    • bit 1: strobe bit

    • +
    • bits 2-(num_sbs * 8 + 1): data word

    • +
    • bits (num_fbs * 8 + 2)-(num_fbs * 8 + 17): address

    • +
    +
  4. +
  5. ISPDATA (2 + num_fbs * 8 bits): a subset of ISPCONFIGURATION used by instructions with autoincrementing address

    +
      +
    • bit 0: valid bit

    • +
    • bit 1: strobe bit

    • +
    • bits 2-(num_sbs * 8 + 1): data word

    • +
    +
  6. +
  7. ISPADDRESS (18 bits): a subset of ISPCONFIGURATION used by some instructions:

  8. +
+
+
    +
  • bit 0: valid bit

  • +
  • bit 1: strobe bit

  • +
  • bits 2-17: address

  • +
+
+
+
+

Entering and exiting ISP mode

+

Before any programming or readout can be done, the device needs to be put into ISP mode. +For that purpose, the ISPEN or ISPENC (XC9500XL/XV only) instructions can be used. +Both instructions use the ISPENABLE register, which is 16 bits on XC9500 +and 6 bits on XC9500XL/XV. Its meaning, if any, is unknown.

+

To enter ISP mode:

+
    +
  • shift ISPEN or ISPENC into IR

  • +
  • shift 0s into DR

  • +
  • go to Run-Test/Idle state for at least 1 clock

  • +
+

If the ISPEN instruction is used, all outputs will be put in high-Z with weak pull-ups while ISP mode is active. +If the ISPENC (“clamp” mode) instruction is used, all output and output enable signals will be snapshotted +and outputs will continue driving the last value while ISP mode is active.

+

To exit ISP mode:

+
    +
  • shift ISPEX into IR

  • +
  • go to Run-Test/Idle state for at least 1 clock

  • +
+

When ISP mode is exitted, the device will initialize itself and start normal operation.

+
+

Todo

+

verify, see if anything can be figured out about the DR

+
+
+
+

Erasing fuses

+
+

Todo

+

write me

+
+
+
+

Programming fuses

+
+

Todo

+

write me

+
+
+
+

Reading fuses

+
+

Todo

+

write me

+
+
+
+

Blank check

+
+

Todo

+

write me

+
+
+
+
+

Programming sequence

+
+

Todo

+

write me

+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/xc9500/structure.html b/xc9500/structure.html new file mode 100644 index 00000000..d2740f09 --- /dev/null +++ b/xc9500/structure.html @@ -0,0 +1,753 @@ + + + + + + + + Device structure — Project Combine documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Device structure

+
+

Overview

+

An XC9500 family device is made of:

+
    +
  • the UIM (universal interconnect matrix), which routes MC and IOB outputs to FB inputs

  • +
  • 2-16 FBs (function blocks), each of which has:

    +
      +
    • 36 (XC9500) or 54 (XC9500XL/XV) routable inputs from UIM

    • +
    • 18 MCs (macrocells), each of which has:

      +
        +
      • configurable low power / high performance mode

      • +
      • 5 PTs (product terms)

      • +
      • PT router, which can route PTs to:

        +
          +
        • the sum term for this MC

        • +
        • the sum term for export into neighbouring MCs

        • +
        • a special function (OE, RST, SET, CLK, CE, XOR depending on the PT)

        • +
        +
      • +
      • PT export/import logic for borrowing PTs between neighbouring MCs

      • +
      • a sum term

      • +
      • a dedicated XOR gate

      • +
      • optional inverter

      • +
      • a flip-flop, with:

        +
          +
        • configurable DFF or TFF function

        • +
        • configurable initial value

        • +
        • clock (freely invertible on XC9500XL/XV), routable from FCLK or PT

        • +
        • async reset, routable from FSR or PT

        • +
        • async set, routable from FSR or PT

        • +
        • (XC9500XL/XV only) clock enable, routable from PT

        • +
        +
      • +
      • a single output (selectable from combinatorial or FF output), routed to IOB and UIM

      • +
      • (XC9500 only) UIM output enable and inversion

      • +
      • IOB (input/output buffer) (on larger devices, not all macrocells have an IOB), with:

        +
          +
        • input buffer (routed to UIM)

        • +
        • output enable (freely invertible on XC9500XL/XV), routable from FOE or PT

        • +
        • configurable slew rate (fast or slow)

        • +
        • programmable ground

        • +
        +
      • +
      +
    • +
    +
  • +
  • global signals

    +
      +
    • 3 FCLK (fast clock) signals

      +
        +
      • (XC9500) freely invertible and routable from GCLK pins

      • +
      • (XC9500XL/XV) hardwired 1-1 to GCLK pins

      • +
      +
    • +
    • 1 FSR (fast set/reset) signal

      +
        +
      • freely invertible

      • +
      • always routed from GSR pin

      • +
      +
    • +
    • 2-4 FOE (fast output enable) signals

      +
        +
      • (XC9500) freely invertible and routable from GOE pins

      • +
      • (XC9500XL/XV) hardwired 1-1 to GOE pins

      • +
      +
    • +
    +
  • +
  • global pull-up enable (only meant to be used in unconfigured devices)

  • +
  • (XC9500XL/XV) global bus keeper enable

  • +
  • special global configuration bits

    +
      +
    • 32-bit standard JTAG USERCODE

    • +
    • read protection enable

    • +
    • write protection enable

    • +
    • (XC9500XV only) DONE bit

    • +
    +
  • +
+
+
+

UIM and FB inputs — XC9500

+

The core interconnect structure in XC9500 devices is the UIM, Universal Interconnect Matrix. +The name is quite appropriate, at least for internal signals: any FB input can be routed +to any MC output. More than that, any FB input can be routed to a wire-AND of an arbitrary +subset of MC outputs from the entire device. Together with the UIM OE functionality within +the MC, this can be used for emulated internal tri-state buses.

+

The name is, however, less appropriate when it comes to external signals: a given FB input +can only be routed to some subset of input signals from IOBs. The set of routable IOBs +depends on the FB input index and the device.

+

Additionally, on devices other than XC9536, some FB inputs can be routed to “fast feedback” +paths, which come straight from MC outputs within the same FB. This is functionally redundant +with the wire-AND path, but much faster.

+

Each FB has 36 inputs, which we call FB[i].IM[j]. Each FB input is controlled by two sets of fuses:

+
    +
  • mux fuses (FB[i].IM[j].MUX) select what is routed to the input. The combinations include:

    +
      +
    • EMPTY: the input is a constant ??? (for unused inputs)

    • +
    • UIM: the input is a wire-AND of MC outputs (and the second set of fuses is relevant)

    • +
    • FBK_MC{k}: the input is routed through fast feedback path from FB[i].MC[k].OUT

    • +
    • PAD_FB{k}_MC{l}: the input is routed from an input buffer FB[k].MC[l].IOB.I

    • +
    +

    The allowable combinations differ between inputs within a single FB, but don’t differ across +FBs within a single device. In other words, the set of allowed values for these fuses +depends only on the j coordinate, but not on i.

    +
  • +
  • wire-AND fuses (FB[i].IM[j].UIM.FB[k].MC[l]) select which MC outputs participate in the +wire-AND. If a given fuse is programmed, it means that FB[k].MC[l].OUT_UIM is included +in the product. These fuses are only relevant when the mux fuse set is set to UIM.

  • +
+
+

Todo

+

check EMPTY semantics

+
+
+

Todo

+

verify FBK doesn’t go through OE and inversion

+
+
+
+

UIM and FB inputs — XC9500XL/XV

+

The core interconnect structure in XC9500XL/XV devices is the UIM 2. This version of the UIM +is not really universal, and is much more of a classic CPLD design.

+

Each FB has 54 inputs, which we call FB[i].IM[j]. Each FB input is controlled by a set of fuses:

+
    +
  • mux fuses (FB[i].IM[j].MUX) select what is routed to the input. The combinations include:

    +
      +
    • EMPTY: the input is a constant ??? (for unused inputs)

    • +
    • FB{k}_MC{l}: the input is routed from the macrocell output FB[k].MC[l].OUT

    • +
    • PAD_FB{k}_MC{l}: the input is routed from the input buffer FB[k].MC[l].IOB.I

    • +
    +

    The allowable combinations differ between inputs within a single FB, but don’t differ across +FBs within a single device. In other words, the set of allowed values for these fuses +depends only on the j coordinate, but not on i.

    +
  • +
+
+

Todo

+

check EMPTY semantics

+
+
+
+

FB global fuses

+

Each function block has two fuses controlling the entire FB:

+
    +
  • FB[i].ENABLE: function block enable; needs to be programmed to use this function block

  • +
  • FB[i].EXPORT_ENABLE: function block PT export enable; needs to be programmed to use PT +import/export within this function block

  • +
+
+

Todo

+

determine what these do exactly

+
+
+
+

Product terms

+

Each function block has 90 product terms, 5 per macrocell. We call them FB[i].MC[j].PT[k]. +Each of the 5 PTs has a dedicated function, as follows:

+
    +
  • *.PT[0]: clock

  • +
  • *.PT[1]: output enable

  • +
  • *.PT[2]: async reset (or clock enable on XC9500XL/XV)

  • +
  • *.PT[3]: async set (or clock enable on XC9500XL/XV)

  • +
  • *.PT[4]: second XOR input

  • +
+

The inputs to all product terms within a FB are the same, and consist of all FB inputs, in both +true and inverted forms.

+

Each product term can be individually configured as low power or high performance. This affects propagation time.

+

Each product term can be routed to at most one of three destinations:

+
    +
  • OR_MAIN: input to the MC’s sum term

  • +
  • OR_EXPORT: input to the export OR gate

  • +
  • SPECIAL: used for the dedicated function

  • +
+

The fuses controlling a product term are:

+
    +
  • FB[i].MC[j].PT[k].IM[l].P: if programmed, FB[i].IM[l] is included in the product term (true polarity)

  • +
  • FB[i].MC[j].PT[k].IM[l].N: if programmed, ~FB[i].IM[l] is included in the product term (inverted polarity)

  • +
  • FB[i].MC[j].PT[k].HP: if programmed, the product term is in high performance mode; otherwise, it is in low power mode

  • +
  • FB[i].MC[j].PT[k].ALLOC: has one of four values:

    +
      +
    • EMPTY: product term is unused

    • +
    • OR_MAIN: product term is used for MC’s sum term; dedicated function wired to 0

    • +
    • OR_EXPORT product term is used for export sum term; dedicated function wired to 0

    • +
    • SPECIAL: product term is used for the dedicated function

    • +
    +
  • +
+

The product term’s corresponding dedicated function is called FB[i].MC[j].PT[k].SPECIAL. +It is equal to FB[i].MC[j].PT[k] if the dedicated function is enabled in ALLOC, 0 otherwise.

+
+

PT import/export

+

Product terms can be borrowed between neighbouring MCs within a FB. To this end, each MC has two outputs, +FB[i].MC[j].EXPORT_{UP|DOWN}, and two inputs, FB[i].MC[j].IMPORT_{UP|DOWN}. The “down” direction +corresponds to exporting PTs toward lower-numbered MCs (with a wraparound from 0 to 17), and the “up” +direction corresponds to exporting PTs towards higher-numbered MCs (with a wraparound from 17 to 0). +Accordingly, we have:

+
FB[i].MC[j].IMPORT_DOWN = FB[i].MC[(j + 1) % 18].EXPORT_DOWN;
+FB[i].MC[j].IMPORT_UP = FB[i].MC[(j - 1) % 18].EXPORT_UP;
+
+
+

A MC can only export product terms in one direction (up or down). +Product terms can be imported from both directions at once. +Imported terms from a given direction can be used for either the main sum term, or for further export, but not both at once.

+

PT import/export is controlled by the following per-MC fuses:

+
    +
  • FB[i].MC[j].EXPORT_DIR: one of:

    +
      +
    • DOWN: exports PTs downwards

    • +
    • UP: exports PTs upwards

    • +
    +
  • +
  • FB[i].MC[j].IMPORT_UP_ALLOC: one of:

    +
      +
    • OR_MAIN: includes PTs imported upwards in the main sum term

    • +
    • OR_EXPORT: includes PTs imported upwards in the export sum term

    • +
    +
  • +
  • FB[i].MC[j].IMPORT_DOWN_ALLOC: one of:

    +
      +
    • OR_MAIN: includes PTs imported downwards in the main sum term

    • +
    • OR_EXPORT: includes PTs imported downwards in the export sum term

    • +
    +
  • +
+

Additionally, the per-FB FB[i].EXPORT_ENABLE fuse needs to be set if any term within a FB is exported or imported.

+

Export works as follows:

+
FB[i].MC[j].EXPORT =
+    (FB[i].MC[j].IMPORT_UP_ALLOC == OR_EXPORT ? FB[i].MC[j].IMPORT_UP : 0) |
+    (FB[i].MC[j].IMPORT_DOWN_ALLOC == OR_EXPORT ? FB[i].MC[j].IMPORT_DOWN : 0) |
+    (FB[i].MC[j].PT[0].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[0] : 0) |
+    (FB[i].MC[j].PT[1].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[1] : 0) |
+    (FB[i].MC[j].PT[2].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[2] : 0) |
+    (FB[i].MC[j].PT[3].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[3] : 0) |
+    (FB[i].MC[j].PT[4].ALLOC == OR_EXPORT ? FB[i].MC[j].PT[4] : 0);
+
+FB[i].MC[j].EXPORT_UP = (FB[i].MC[j].EXPORT_DIR == UP ? FB[i].MC[j].EXPORT : 0);
+FB[i].MC[j].EXPORT_DOWN = (FB[i].MC[j].EXPORT_DIR == DOWN ? FB[i].MC[j].EXPORT : 0);
+
+
+
+

Todo

+

verify all of the above

+
+
+
+
+

Sum term, XOR gate

+

Each macrocell has a main sum term, which includes all product terms and imports routed towards it:

+
FB[i].MC[j].SUM =
+    (FB[i].MC[j].IMPORT_UP_ALLOC == OR_MAIN ? FB[i].MC[j].IMPORT_UP : 0) |
+    (FB[i].MC[j].IMPORT_DOWN_ALLOC == OR_MAIN ? FB[i].MC[j].IMPORT_DOWN : 0) |
+    (FB[i].MC[j].PT[0].ALLOC == OR_MAIN ? FB[i].MC[j].PT[0] : 0) |
+    (FB[i].MC[j].PT[1].ALLOC == OR_MAIN ? FB[i].MC[j].PT[1] : 0) |
+    (FB[i].MC[j].PT[2].ALLOC == OR_MAIN ? FB[i].MC[j].PT[2] : 0) |
+    (FB[i].MC[j].PT[3].ALLOC == OR_MAIN ? FB[i].MC[j].PT[3] : 0) |
+    (FB[i].MC[j].PT[4].ALLOC == OR_MAIN ? FB[i].MC[j].PT[4] : 0);
+
+
+

The sum term then goes through a XOR gate (whose other input is either 0 or a dedicated PT) and a programmable inverter:

+
FB[i].MC[j].XOR = FB[i].MC[j].SUM ^ FB[i].MC[j].PT[4].SPECIAL ^ FB[i].MC[j].INV;
+
+
+

The fuses involved are:

+
    +
  • FB[i].MC[j].SUM_HP: if programmed, the sum term is in high performance mode; otherwise, it’s in low power mode

  • +
  • FB[i].MC[j].INV: if programmed, the output of the XOR gate is further inverted

  • +
+
+
+

Flip-flop

+

Each macrocell includes a flip-flop. It has:

+
    +
  • configurable DFF or TFF function

  • +
  • D or T input connected to the (potentially inverted) XOR gate output

  • +
  • configurable initial value

  • +
  • clock (freely invertible on XC9500XL/XV), routable from FCLK or PT[0]

  • +
  • async reset, routable from FSR or PT[2]

  • +
  • async set, routable from FSR or PT[3]

  • +
  • (XC9500XL/XV only) clock enable, routable from PT[2] or PT[3]

  • +
+

The fuses involved are:

+
    +
  • FB[i].MC[j].CLK_MUX: selects CLK input

    +
      +
    • PT: product term 0 dedicated function

    • +
    • FCLK[0-2]: global FCLK[0-2] network

    • +
    +
  • +
  • FB[i].MC[j].CLK_INV: if programmed, the CLK input is inverted (ie. clock is negedge) (XC9500XL/XV only)

  • +
  • FB[i].MC[j].RST_MUX: selects RST input

    +
      +
    • PT: product term 2 dedicated function or 0; if PT 2 is used for clock enable, it will not be routed to RST (0 will be substituted)

    • +
    • FSR: global FSR network

    • +
    +
  • +
  • FB[i].MC[j].SET_MUX: selects SET input

    +
      +
    • PT: product term 3 dedicated function or 0; if PT 3 is used for clock enable, it will not be routed to SET (0 will be substituted)

    • +
    • FSR: global FSR network

    • +
    +
  • +
  • FB[i].MC[j].CE_MUX: selects CE input (XC9500XL/XV only)

    +
      +
    • NONE: const 1

    • +
    • PT2: product term 2 dedicated function

    • +
    • PT3: product term 3 dedicated function

    • +
    +
  • +
  • FB[i].MC[j].INIT: if programmed, the initial value of the FF is 1; otherwise, it is 0

  • +
  • FB[i].MC[j].REG_MODE: selects FF mode

    +
      +
    • DFF

    • +
    • TFF

    • +
    +
  • +
+

On XC9500, the FF works as follows:

+
case(FB[i].MC[j].CLK_MUX)
+PT: FB[i].MC[j].CLK = FB[i].MC[j].PT[0].SPECIAL;
+FCLK0: FB[i].MC[j].CLK = FCLK[0];
+FCLK1: FB[i].MC[j].CLK = FCLK[1];
+FCLK2: FB[i].MC[j].CLK = FCLK[2];
+endcase
+
+case(FB[i].MC[j].RST_MUX)
+PT: FB[i].MC[j].RST = FB[i].MC[j].PT[2].SPECIAL;
+FSR: FB[i].MC[j].RST = FSR;
+endcase
+
+case(FB[i].MC[j].SET_MUX)
+PT: FB[i].MC[j].SET = FB[i].MC[j].PT[3].SPECIAL;
+FSR: FB[i].MC[j].SET = FSR;
+endcase
+
+initial FB[i].MC[j].FF = FB[i].MC[j].INIT;
+
+// Pretend the usual synth/sim mismatch doesn't happen.
+always @(posedge FB[i].MC[j].CLK, posedge FB[i].MC[j].RST_MUX, posedge FB[i].MC[j].SET_MUX)
+    if (FB[i].MC[j].RST_MUX)
+        FB[i].MC[j].FF = 0;
+    else if (FB[i].MC[j].SET_MUX)
+        FB[i].MC[j].FF = 1;
+    else
+        FB[i].MC[j].FF = FB[i].MC[j].XOR;
+
+
+

On XC9500XL/XV, the FF works as follows:

+
case(FB[i].MC[j].CLK_MUX)
+PT: FB[i].MC[j].CLK = FB[i].MC[j].PT[0].SPECIAL ^ FB[i].MC[j].CLK_INV;
+FCLK0: FB[i].MC[j].CLK = FCLK[0] ^ FB[i].MC[j].CLK_INV;
+FCLK1: FB[i].MC[j].CLK = FCLK[1] ^ FB[i].MC[j].CLK_INV;
+FCLK2: FB[i].MC[j].CLK = FCLK[2] ^ FB[i].MC[j].CLK_INV;
+endcase
+
+case(FB[i].MC[j].RST_MUX)
+PT: FB[i].MC[j].RST = (FB[i].MC[j].CE_MUX == PT2 ? 0 : FB[i].MC[j].PT[2].SPECIAL);
+FSR: FB[i].MC[j].RST = FSR;
+endcase
+
+case(FB[i].MC[j].SET_MUX)
+PT: FB[i].MC[j].SET = (FB[i].MC[j].CE_MUX == PT3 ? 0 : FB[i].MC[j].PT[3].SPECIAL);
+FSR: FB[i].MC[j].SET = FSR;
+endcase
+
+case(FB[i].MC[j].CE_MUX)
+PT2: FB[i].MC[j].CE = FB[i].MC[j].PT[2].SPECIAL;
+PT3: FB[i].MC[j].CE = FB[i].MC[j].PT[3].SPECIAL;
+NONE: FB[i].MC[j].CE = 1;
+endcase
+
+initial FB[i].MC[j].FF = FB[i].MC[j].INIT;
+
+// Pretend the usual synth/sim mismatch doesn't happen.
+always @(posedge FB[i].MC[j].CLK, posedge FB[i].MC[j].RST_MUX, posedge FB[i].MC[j].SET_MUX)
+    if (FB[i].MC[j].RST_MUX)
+        FB[i].MC[j].FF = 0;
+    else if (FB[i].MC[j].SET_MUX)
+        FB[i].MC[j].FF = 1;
+    else if (FB[i].MC[j].CE)
+        FB[i].MC[j].FF = FB[i].MC[j].XOR;
+
+
+
+

Todo

+

verify (in particular, CE vs RST/SET shenanigans)

+
+
+
+

Macrocell output — XC9500

+

The output of the macrocell can be selected from combinatorial (XOR gate output) or registered (FF output):

+
FB[i].MC[j].OUT = (FB[i].MC[j].OUT_MUX == COMB ? FB[i].MC[j].XOR : FB[i].MC[j].FF);
+
+
+

The macrocell also has an output enable, which can be from a product term, or a global network. +It can be used for the IOB output buffer, for UIM output, or both:

+
case(FB[i].MC[j].OE_MUX)
+PT: FB[i].MC[j].OE = FB[i].MC[j].PT[1].SPECIAL;
+FOE0: FB[i].MC[j].OE = FOE[0];
+FOE1: FB[i].MC[j].OE = FOE[1];
+FOE2: FB[i].MC[j].OE = FOE[2];
+FOE3: FB[i].MC[j].OE = FOE[3];
+endcase
+
+case(FB[i].MC[j].UIM_OE_MUX)
+GND: FB[i].MC[j].UIM_OE = 0;
+VCC: FB[i].MC[j].UIM_OE = 1;
+OE_MUX: FB[i].MC[j].UIM_OE = FB[i].MC[j].OE;
+endcase
+
+case(FB[i].MC[j].IOB_OE_MUX)
+GND: FB[i].MC[j].IOB_OE = 0;
+VCC: FB[i].MC[j].IOB_OE = 1;
+OE_MUX: FB[i].MC[j].IOB_OE = FB[i].MC[j].OE;
+endcase
+
+
+

The output is routed to up to three places:

+
    +
  • this MC’s IOB (FB[i].MC[j].OUT)

  • +
  • this FB’s inputs via the feedback path (FB[i].MC[j].OUT)

  • +
  • the UIM (FB[i].MC[j].OUT_UIM)

  • +
+

The output to UIM additionally goes through (emulated) output enable logic, which can be used +to implement emulated on-chip tristate buses in conjunction with the UIM wire-AND logic:

+
FB[i].MC[j].OUT_UIM = FB[i].MC[j].UIM_OE ? FB[i].MC[j].OUT ^ FB[i].MC[j].UIM_OUT_INV : 1;
+
+
+

The fuses involved are:

+
    +
  • FB[i].MC[j].OUT_MUX: selects output mode

    +
      +
    • COMB: combinatorial, the output is connected to XOR gate output

    • +
    • FF: registered, the output is connected to FF output

    • +
    +
  • +
  • FB[i].MC[j].OE_MUX: selects output enable source

    +
      +
    • PT: product term 1 dedicated function or 0

    • +
    • FOE[0-3]: global FOE[0-3] network

    • +
    +
  • +
  • FB[i].MC[j].UIM_OE_MUX: selects output enable for UIM output

    +
      +
    • GND: const 0

    • +
    • VCC: const 1

    • +
    • OE_MUX: the input selected by the OE_MUX fuses

    • +
    +
  • +
  • FB[i].MC[j].IOB_OE_MUX: selects output enable for IOB output

    +
      +
    • GND: const 0

    • +
    • VCC: const 1

    • +
    • OE_MUX: the input selected by the OE_MUX fuses

    • +
    +
  • +
  • FB[i].MC[j].UIM_OUT_INV: if programmed, the output to UIM is inverted

  • +
+
+

Todo

+

verify all of the above (in particular, feedback path vs OE and UIM out)

+
+
+
+

Macrocell output — XC9500XL/XV

+

The output of the macrocell can be selected from combinatorial (XOR gate output) or registered (FF output):

+
FB[i].MC[j].OUT = (FB[i].MC[j].OUT_MUX == COMB ? FB[i].MC[j].XOR : FB[i].MC[j].FF);
+
+
+

The output is routed to the UIM and this MC’s IOB.

+

The macrocell also has an output enable, which can be from a product term, or a global network, and can +be freely inverted. It is used for the IOB output buffer:

+
case(FB[i].MC[j].OE_MUX)
+PT: FB[i].MC[j].IOB_OE = FB[i].MC[j].PT[1].SPECIAL ^ FB[i].MC[j].OE_INV;
+FOE0: FB[i].MC[j].IOB_OE = FOE[0] ^ FB[i].MC[j].OE_INV;
+FOE1: FB[i].MC[j].IOB_OE = FOE[1] ^ FB[i].MC[j].OE_INV;
+FOE2: FB[i].MC[j].IOB_OE = FOE[2] ^ FB[i].MC[j].OE_INV;
+FOE3: FB[i].MC[j].IOB_OE = FOE[3] ^ FB[i].MC[j].OE_INV;
+endcase
+
+
+

The fuses involved are:

+
    +
  • FB[i].MC[j].OUT_MUX: selects output mode

    +
      +
    • COMB: combinatorial, the output is connected to XOR gate output

    • +
    • FF: registered, the output is connected to FF output

    • +
    +
  • +
  • FB[i].MC[j].OE_MUX: selects output enable source

    +
      +
    • PT: product term 1 dedicated function or 0

    • +
    • FOE[0-3]: global FOE[0-3] network

    • +
    +
  • +
  • FB[i].MC[j].OE_INV: if programmed, the output enable is inverted

  • +
+
+
+

Input/output buffer

+

All I/O buffers (except dedicated JTAG pins) are associated with a macrocell. Not all MCs +have associated IOBs.

+

The output buffer is controlled by the FB[i].MC[j].OUT and FB[i].MC[j].IOB_OE signals of the macrocell. +If the pad is supposed to be input only, the OE signal should be programmed to be always 0:

+
    +
  • on XC9500, IOB_OE_MUX should be set to GND

  • +
  • on XC9500XL/XV, OE_MUX should be set to PT, OE_INV should be unset, and PT[1] should not be allocated to its dedicated function

  • +
+

Likewise, if the pad is supposed to be always-on output, the OE signal should be programmed to be always 1:

+
    +
  • on XC9500, IOB_OE_MUX should be set to VCC

  • +
  • on XC9500XL/XV, OE_MUX should be set to PT, OE_INV should be set, and PT[1] should not be allocated to its dedicated function

  • +
+

The output slew rate is programmable between two settings, “fast” and “slow”.

+

Instead of being connected to MC output, an IOB can also be a “programmed ground”, ie be set to always output a const 0 +regardless of the IOB_OE and OUT signals. In this case, IOB_OE should be 0.

+

The input buffer is connected to the FB[i].MC[j].IOB.I network. On all devices other than XC95288 (non-XL/XV), +it is directly connected to the UIM. On XC95288, there are additional enable fuses for this connection.

+

Each I/O buffer has the following fuses:

+
    +
  • FB[i].MC[j].GND: if programmed, this pin is “programmed ground” and will always output a const 0

  • +
  • FB[i].MC[j].SLEW: selects slew rate, one of:

    +
      +
    • SLOW

    • +
    • FAST

    • +
    +
  • +
  • FB[i].MC[j].IBUF_ENABLE (XC95288 only): when programmed, the input buffer is active and connected to UIM

  • +
+
+

Todo

+

figure out the IBUF_ENABLE thing

+
+
+
+

Configuration pull-ups

+

Before the device is configured, all IOBs are configured with a very weak pull-up +resistor (XC9500) or a bus keeper (XC9500XL/XV). To disable this pull-up, a per-FB fuse +is used which is set in the bitstream:

+
    +
  • FB[i].PULLUP_DISABLE: if programmed, disables the pre-configuration pull-ups / bus keepers for all IOBs in this FB

  • +
+
+
+

XC9500XL/XV bus keeper

+

The XC9500XL/XV have a weak bus keeper in each IOB. The keeper functionality can only be enabled +globally for all pads on the device, or not at all, via a global fuse:

+
    +
  • KEEPER: if programmed, the bus keeper is enabled on all IOBs

  • +
+
+
+

Global networks — XC9500

+

The device has several global networks for fast control signals. The networks are always driven by special pads +on the device (which can also be used as normal I/O). The networks are:

+
    +
  • FCLK[0-2]: clock

  • +
  • FSR: async set or reset

  • +
  • FOE[0-1] (XC9536, XC9572, XC95108) or FOE[0-3] (XC95144, XC95216, XC95288): output enable

  • +
+

The special pads are:

+
    +
  • GCLK[0-2]: clock

  • +
  • GSR: async set or reset

  • +
  • GOE[0-1] (XC9536, XC9572, XC95108) or GOE[0-3] (XC95144, XC95216, XC95288): output enable

  • +
+

The mapping of G* special pads to MCs depends on the device and, in at least one case, the package (!).

+

The allowed mappings are:

+
    +
  • FCLK0: GCLK0, GCLK1

  • +
  • FCLK1: GCLK1, GCLK2

  • +
  • FCLK2: GCLK2, GCLK0

  • +
  • FSR: GSR

  • +
  • FOE0 (XC9536, XC9572, XC95108): GOE0, GOE1

  • +
  • FOE1 (XC9536, XC9572, XC95108): GOE0, GOE1

  • +
  • FOE0 (XC95144, XC95216, XC95288): GOE0, GOE1

  • +
  • FOE1 (XC95144, XC95216, XC95288): GOE1, GOE2

  • +
  • FOE2 (XC95144, XC95216, XC95288): GOE2, GOE3

  • +
  • FOE3 (XC95144, XC95216, XC95288): GOE3, GOE0

  • +
+

Additionally, all networks can be inverted from their source pins.

+

The fuses involved are:

+
    +
  • FCLK[i].MUX: selects the input routed to FCLK[i]

    +
      +
    • NONE: const ???

    • +
    • GCLK[i]: the corresponding GCLK pad

    • +
    +
  • +
  • FOE[i].MUX: selects the input routed to FOE[i]

    +
      +
    • NONE: const ???

    • +
    • FOE[i]: the corresponding FOE pad

    • +
    +
  • +
  • FCLK[i].INV: if programmed, the GCLK pad is inverted before driving FCLK[i] network

  • +
  • FSR.INV: if programmed, the GSR pad is inverted before driving FSR network

  • +
  • FOE[i].INV: if programmed, the GOE pad is inverted before driving FOE[i] network

  • +
+
+

Todo

+

consts

+
+
+

Todo

+

no, really, what is it with the XC9572 GOE mapping varying between packages

+
+
+
+

Global networks — XC9500XL/XV

+

Global networks on XC9500XL/XV work similarly, except there are no muxes and no inversion (except for FSR). +Thus the GCLK[i] and GOE[i] pads are mapped 1-1 directly to FCLK[i] and FOE[i] networks, with only +an enable fuse.

+

The fuses involved are:

+
    +
  • FCLK[i].EN: if programmed, the given FCLK network is active and connected to the GCLK[i] pad

  • +
  • FOE[i].EN: if programmed, the given FOE network is active and connected to the GOE[i] pad

  • +
  • FSR.INV: if programmed, the GSR pad is inverted before driving FSR network

  • +
+

The FSR network is always enabled.

+
+

Todo

+

what does disabled network do

+
+
+
+

Misc configuration

+

The devices also include the following misc fuses:

+
    +
  • USERCODE: 32-bit fuse set, readable via the JTAG USERCODE instruction

  • +
  • FB[i].READ_PROT_{A|B} (XC9500): if programmed, the device is read protected

  • +
  • FB[i].READ_PROT (XC9500XL/XV): if programmed, the device is read protected

  • +
  • FB[i].WRITE_PROT: if programmed, the device is write protected (needs a special JTAG instruction sequence +to program/erase)

  • +
  • DONE (XC9500XV only): used to mark a fully programmed device; if programmed, the device will complete its +boot sequence and activate I/O buffers; otherwise, all output buffers will be disabled

  • +
+

Due to their special semantics, the protection fuses and the DONE fuse should be programmed last, after all other fuses in the bitstream.

+
+

Todo

+

exact semantics of protection fuses

+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file