CINXE.COM
Ken Shirriff's blog: 2024
<!DOCTYPE html> <html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='http://www.righto.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='http://www.righto.com/2024/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="http://www.righto.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Ken Shirriff's blog - RSS" href="http://www.righto.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="https://www.blogger.com/feeds/6264947694886887540/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://www.righto.com/2024/' property='og:url'/> <meta content='Ken Shirriff's blog' property='og:title'/> <meta content='Computer history, restoring vintage computers, IC reverse engineering, and whatever' property='og:description'/> <title>Ken Shirriff's blog: 2024</title> <style type='text/css'>@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtg2H68T.woff2)format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtE2H68T.woff2)format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtY2H68T.woff2)format('woff2');unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvto2H68T.woff2)format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvts2H68T.woff2)format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtU2Hw.woff2)format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#222222"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#222222"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="#eeeeee"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#f6fbf6" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #222222; background: #f6fbf6 none repeat scroll top left; padding: 0 40px 40px 40px; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #121fb3; } a:visited { text-decoration:none; color: #121fb3; } a:hover { text-decoration:underline; color: #1a00ff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent url(//www.blogblog.com/1kt/simple/body_gradient_tile_light.png) repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 40px rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 10px #333333; box-shadow: 0 0 40px rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 10px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: #f6fbf7 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 42px Play; color: #666666; text-shadow: 1px 2px 3px rgba(0, 0, 0, .2); } .Header h1 a { color: #666666; } .Header .description { font-size: 140%; color: #666666; } .header-inner .Header .titlewrapper { padding: 22px 30px; } .header-inner .Header .descriptionwrapper { padding: 0 30px; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #eeeeee; } .tabs-inner .section:first-child ul { margin-top: -0; border-top: 0 solid #eeeeee; border-left: 0 solid #eeeeee; border-right: 0 solid #eeeeee; } .tabs-inner .widget ul { background: #f5f5f5 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #eeeeee; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #999999; border-left: 1px solid #ffffff; border-right: 1px solid #eeeeee; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid #eeeeee; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid #eeeeee; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid #eeeeee; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: transparent; color: transparent; padding: inherit; letter-spacing: inherit; margin: inherit; } .main-inner { padding-top: 30px; padding-bottom: 30px; } .main-inner .column-center-inner { padding: 0 15px; } .main-inner .column-center-inner .section { margin: 0 15px; } .post { margin: 0 0 25px 0; } h3.post-title, .comments h4 { font: normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #ffffff; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #222222; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #f9f9f9; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid #eeeeee; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #ffffff; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #f9f9f9; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid #eeeeee; } .blog-pager { background: transparent none no-repeat scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 0 dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #222222; } .mobile-link-button { background-color: #121fb3; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #eeeeee; } .content-outer { max-width: 1400px !important; } /* fix header */ #header-inner { width: 100% !important; background-position: right !important; } .titlewrapper { padding: 11px 30px 0 !important; } .descriptionwrapper { margin-bottom: 0 !important; } .description { font-size: 120% !important; } /* suppress things */ .date-header { display: none; } #Attribution1 { display: none; } .post-author, .post-timestamp, .reaction-buttons { display: none; } /* h2: sidebar titles */ /* h3: post title */ .post-title , .entry-title { font-size: 180% !important; margin-top: 0 !important; } .entry-title a:link, .entry-title a:visited, .entry-title a:active{ color: #a03; } #main h2 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:140%; } #main h3 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:110%; } #main h4 { color:#333; margin-bottom:.5em; } #sidebar-right-1 a:link, #sidebar-right-1 a:visited, #sidebar-right-1 a:active { color: #666; } #sidebar-right-1 h2 { font-size: 100%; color: #666; } /* disable image box */ element.style { } table.chargers img { height: 18px; } table.chargers img { height: 18px; } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 0; background: #ffffff; border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* Special items */ a:link img.hilite, a:visited img.hilite { color: #fff; } a:hover img.hilite, a:hover img.hilite2 { color: #f66; } a:active img.hilite { color: #33c; } .hilite {cursor:zoom-in} pre {color:#000000;border:1px solid #000000;} pre.repl { background-color:#e0e0f0; font-size:120%;} pre.arc { background-color:#e0e0f0; font-size:120%;} pre.code { background-color:#e0f0e0; font-size:120%; white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;text-wrap:unrestricted;} code { font-size: 100%;} blockquote { font-size: 110%; background: transparent url("//static.righto.com/images/blockquote.gif") no-repeat 0 0; margin: 20px 0px; padding: 0px 40px;} div.cite {font-size: .8em;.; font-style: italic; color: #888; margin-bottom: 9px;} a.ref { color: gray;vertical-align: super; text-decoration: none; font-size:60%;margin-left: 2px;} a img.hilite { border: 1px solid; color: #888; z-index: 2; } a img.hilite2, a:active img.hilite2 { border: 1px solid; color: #f6fbf6; } table.chargers { border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: collapse; background-color: white; } table.chargers th.maker { padding-right: 5px; text-align: right; } table.chargers th { border-width: 1px; padding: 3px; border-style: inset; border-color: gray; background-color: white; text-align: center; } table.chargers img { height: 18px; } table.chargers td { text-align: center; border-width: 1px; padding: 2px 8px; border-style: inset; border-color: gray; background-color: white; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 750px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 750px; max-width: 750px; _width: 750px; } .main-inner .columns { padding-left: 0px; padding-right: 240px; } .main-inner .fauxcolumn-center-outer { left: 0px; right: 240px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0px") - parseInt("240px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0px; } .main-inner .fauxcolumn-right-outer { width: 240px; } .main-inner .column-left-outer { width: 0px; right: 100%; margin-left: -0px; } .main-inner .column-right-outer { width: 240px; margin-right: -240px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } --></style> <meta content='width=device-width, initial-scale=1.0, maximum-scale=12.0, minimum-scale=.25, user-scalable=yes' name='viewport'/> <meta content='mw8ww70r3jW0GzXY6j1d' name='follow_it-verification-code'/> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=6fd23a04-bc1a-4aed-b46d-611afb4481ef' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=6fd23a04-bc1a-4aed-b46d-611afb4481ef' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body class='loading'> <div class='navbar no-items section' id='navbar'> </div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner' style='background-image: url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-4KXwYe0lQ4HFzhAye9vvRlij2ZYvMbfPCnqEE__1o85Fjo3XgefxJQhWRdwR3EzNWNMWT3yMaj2QZaT9GazqQx3C6oWa3-hBNlRHG7f-Oib-lv1Wq_C2_A0rt8xZgs87iNqzRVKK7H0A/s800/background.jpg"); background-position: left; width: 550px; min-height: 105px; _height: 105px; background-repeat: no-repeat; '> <div class='titlewrapper' style='background: transparent'> <h1 class='title' style='background: transparent; border-width: 0px'> <a href='http://www.righto.com/'> Ken Shirriff's blog </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>Computer history, restoring vintage computers, IC reverse engineering, and whatever</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol'></div> <div class='tabs no-items section' id='crosscol-overflow'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://static.righto.com/images/pentium-fdiv/fdiv-bug-here-w500.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='639773237179033868' itemprop='postId'/> <a name='639773237179033868'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2024/12/this-die-photo-of-pentium-shows.html'>Intel's $475 million error: the silicon behind the Pentium division bug</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-639773237179033868' itemprop='description articleBody'> <p>In 1993, Intel released the high-performance Pentium processor, the start of the long-running Pentium line. The Pentium had many improvements over the previous processor, the Intel 486, including a faster floating-point division algorithm. A year later, Professor Nicely, a number theory professor, was researching reciprocals of twin prime numbers when he noticed a problem: his Pentium sometimes generated the wrong result when performing floating-point division. Intel considered this "an extremely minor technical problem", but much to Intel's surprise, the bug became a large media story. After weeks of criticism, mockery, and bad publicity, Intel agreed to replace everyone's faulty Pentium chips, costing the company $475 million.</p> <p>In this article, I discuss the Pentium's division algorithm, show exactly where the bug is on the Pentium chip, take a close look at the circuitry, and explain what went wrong. In brief, the division algorithm uses a lookup table. In 1994, Intel stated that the cause of the bug was that five entries were omitted from the table due to an error in a script. However, my analysis shows that 16 entries were omitted due to a mathematical mistake in the definition of the lookup table. Five of the missing entries trigger the bug— also called the FDIV bug after the floating-point division instruction "FDIV"—while 11 of the missing entries have no effect.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/fdiv-bug-here.jpg"><img alt="This die photo of the Pentium shows the location of the FDIV bug. Click this image (or any other) for a larger version." class="hilite" height="453" src="https://static.righto.com/images/pentium-fdiv/fdiv-bug-here-w500.jpg" title="This die photo of the Pentium shows the location of the FDIV bug. Click this image (or any other) for a larger version." width="500" /></a><div class="cite">This die photo of the Pentium shows the location of the FDIV bug. Click this image (or any other) for a larger version.</div></p> <p>Although Professor Nicely brought attention to the FDIV bug, he wasn't the first to find it. In May 1994, Intel's internal testing of the Pentium revealed that very rarely, floating-point division was slightly inaccurate.<span id="fnref:dham"><a class="ref" href="#fn:dham">1</a></span> Since only one in 9 billion values caused the problem, Intel's view was that the problem was trivial: "This doesn't even qualify as an errata." Nonetheless, Intel quietly revised the Pentium circuitry to fix the problem.</p> <p>A few months later, in October, Nicely noticed erroneous results in his prime number computations.<span id="fnref:prime"><a class="ref" href="#fn:prime">2</a></span> He soon determined that 1/824633702441 was wrong on three different Pentium computers, but his older computers gave the right answer. He called Intel tech support but was brushed off, so Nicely emailed a dozen computer magazines and individuals about the bug. One of the recipients was Andrew Schulman, author of "Undocumented DOS". He forwarded the email to Richard Smith, cofounder of a DOS software tools company. Smith posted the email on a Compuserve forum, a 1990s version of social media.</p> <p>A reporter for the journal <em>Electronic Engineering Times</em> spotted the Compuserve post and wrote about the Pentium bug in the November 7 issue: <a href="https://davefaq.com/Opinions/Stupid/Pentium.html">Intel fixes a Pentium FPU glitch</a>. In the article, Intel explained that the bug was in a component of the chip called a PLA (Programmable Logic Array) that acted as a lookup table for the division operation. Intel had fixed the bug in the latest Pentiums and would replace faulty processors for concerned customers.<span id="fnref:timeline"><a class="ref" href="#fn:timeline">3</a></span></p> <p>The problem might have quietly ended here, except that Intel decided to restrict which customers could get a replacement. If a customer couldn't convince an Intel engineer that they needed the accuracy, they couldn't get a fixed Pentium. Users were irate to be stuck with faulty chips so they took their complaints to online groups such as <a href="https://groups.google.com/g/comp.sys.intel/c/L1KDE1d_ZLA/m/7rydJksrVTcJ">comp.sys.intel</a>. The controversy spilled over into the offline world on November 22 when CNN reported on the bug. Public awareness of the Pentium bug took off as newspapers wrote about the bug and Intel became a punchline on talk shows.<span id="fnref:letterman"><a class="ref" href="#fn:letterman">4</a></span></p> <p>The situation became intolerable for Intel on December 12 when IBM announced that it was stopping shipments of Pentium computers.<span id="fnref:errata"><a class="ref" href="#fn:errata">5</a></span> On December 19, less than two months after Nicely first reported the bug, Intel gave in and announced that it would replace the flawed chips for all customers.<span id="fnref:apology"><a class="ref" href="#fn:apology">6</a></span> This recall cost Intel $475 million (over a billion dollars in current dollars).</p> <p>Meanwhile, engineers and mathematicians were analyzing the bug, including Tim Coe, an engineer who had designed floating-point units.<span id="fnref:coe"><a class="ref" href="#fn:coe">7</a></span> Remarkably, by studying the Pentium's bad divisions, Coe reverse-engineered the Pentium's division algorithm and determined why it went wrong. Coe and others wrote papers describing the mathematics behind the Pentium bug.<span id="fnref:papers"><a class="ref" href="#fn:papers">8</a></span> But until now, nobody has shown how the bug is implemented in the physical chip itself.</p> <h2>A quick explanation of floating point numbers</h2> <p>At this point, I'll review a few important things about floating point numbers. A binary number can have a fractional part, similar to a decimal number. For instance, the binary number 11.1001 has four digits after the binary point. (The binary point "." is similar to the decimal point, but for a binary number.) The first digit after the binary point represents 1/2, the second represents 1/4, and so forth. Thus, 11.1001 corresponds to 3 + 1/2 + 1/16 = 3.5625. A "fixed point" number such as this can express a fractional value, but its range is limited.</p> <p>Floating point numbers, on the other hand, include very large numbers such as 6.02×10<sup>23</sup> and very small numbers such as 1.055×10<sup>−34</sup>. In decimal, 6.02×10<sup>23</sup> has a significand (or mantissa) of 6.02, multiplied by a power of 10 with an exponent of 23. In binary, a floating point number is represented similarly, with a significand and exponent, except the significand is multiplied by a power of 2 rather than 10.</p> <p>Computers have used floating point since the early days of computing, especially for scientific computing. For many years, different computers used incompatible formats for floating point numbers. Eventually, a standard arose when Intel developed the 8087 floating point coprocessor chip for use with the 8086/8088 processor. The characteristics of this chip became a standard (IEEE 754) in 1985.<span id="fnref:ieee754"><a class="ref" href="#fn:ieee754">9</a></span> Subsequently, most computers, including the Pentium, implemented floating point numbers according to this standard. The result of a basic arithmetic operation is supposed to be accurate up to the last bit of the significand. Unfortunately, division on the Pentium was occasionally much, much worse.</p> <h2>How SRT division works</h2> <p>How does a computer perform division? The straightforward way is similar to grade-school long division, except in binary. That approach was used in the Intel 486 and earlier processors, but the process is slow, taking one clock cycle for each bit of the quotient. The Pentium uses a different approach called SRT,<span id="fnref:srt-history"><a class="ref" href="#fn:srt-history">10</a></span> performing division in base four. Thus, SRT generates two bits of the quotient per step, rather than one, so division is twice as fast. I'll explain SRT in a hand-waving manner with a base-10 example; rigorous explanations are available elsewhere.</p> <p>The diagram below shows base-10 long division, with the important parts named. The dividend is divided by the divisor, yielding the quotient. In each step of the long division algorithm, you generate one more digit of the quotient. Then you multiply the divisor (1535) by the quotient digit (2) and subtract this from the dividend, leaving a partial remainder. You multiply the partial remainder by 10 and then repeat the process, generating a quotient digit and partial remainder at each step. The diagram below stops after two quotient digits, but you can keep going to get as much accuracy as desired.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/srt-diagram1.jpg"><img alt="Base-10 division, naming the important parts." class="hilite" height="168" src="https://static.righto.com/images/pentium-fdiv/srt-diagram1-w300.jpg" title="Base-10 division, naming the important parts." width="300" /></a><div class="cite">Base-10 division, naming the important parts.</div></p> <p>Note that division is more difficult than multiplication since there is no easy way to determine each quotient digit. You have to estimate a quotient digit, multiply it by the divisor, and then check if the quotient digit is correct. For example, you have to check carefully to see if 1535 goes into 4578 two times or three times.</p> <p>The SRT algorithm makes it easier to select the quotient digit through an unusual approach: it allows negative digits in the quotient. With this change, the quotient digit does not need to be exact. If you pick a quotient digit that is a bit too large, you can use a negative number for the next digit: this will counteract the too-large digit since the next divisor will be added rather than subtracted.</p> <p>The example below shows how this works. Suppose you picked 3 instead of 2 as the first quotient digit. Since 3 is too big, the partial remainder is negative (-261). In normal division, you'd need to try again with a different quotient digit. But with SRT, you keep going, using a negative digit (-1) for the quotient digit in the next step. At the end, the quotient with positive and negative digits can be converted to the standard form: 3×10-1 = 29, the same quotient as before.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/srt-diagram2.jpg"><img alt="Base-10 division, using a negative quotient digit. The result is the same as the previous example." class="hilite" height="159" src="https://static.righto.com/images/pentium-fdiv/srt-diagram2-w300.jpg" title="Base-10 division, using a negative quotient digit. The result is the same as the previous example." width="300" /></a><div class="cite">Base-10 division, using a negative quotient digit. The result is the same as the previous example.</div></p> <p>One nice thing about the SRT algorithm is that since the quotient digit only needs to be close, a lookup table can be used to select the quotient digit. Specifically, the partial remainder and divisor can be truncated to a few digits, making the lookup table a practical size. In this example, you could truncate 1535 and 4578 to 15 and 45, the table says that 15 goes into 45 three times, and you can use 3 as your quotient digit.</p> <p>Instead of base 10, the Pentium uses the SRT algorithm in base 4: groups of two bits. As a result, division on the Pentium is twice as fast as standard binary division. With base-4 SRT, each quotient digit can be -2, -1, 0, 1, or 2. Multiplying by any of these values is very easy in hardware since multiplying by 2 can be done by a bit shift. Base-4 SRT does not require quotient digits of -3 or 3; this is convenient since multiplying by 3 is somewhat difficult. To summarize, base-4 SRT is twice as fast as regular binary division, but it requires more hardware: a lookup table, circuitry to add or subtract multiples of 1 or 2, and circuitry to convert the quotient to the standard form.</p> <h2>Structure of the Pentium's lookup table</h2> <p>The purpose of the SRT lookup table is to provide the quotient digit. That is, the table takes the partial remainder <em>p</em> and the divisor <em>d</em> as inputs and provides an appropriate quotient digit. The Pentium's lookup table is the cause of the division bug, as was explained in 1994. The table was missing five entries; if the SRT algorithm accesses one of these missing entries, it generates an incorrect result. In this section, I'll discuss the structure of the lookup table and explain what went wrong.</p> <p>The Pentium's lookup table contains 2048 entries, as shown below. The table has five regions corresponding to the quotient digits +2, +1, 0, -1, and -2. Moreover, the upper and lower regions of the table are unused (due to the mathematics of SRT). The unused entries were filled with 0, which turns out to be very important. In particular, the five red entries need to contain +2 but were erroneously filled with 0.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/table-labeled.jpg"><img alt="The 2048-entry lookup table used in the Pentium for division. The divisor is along the X-axis, from 1 to 2. The partial remainder is along the Y-axis, from -8 to 8. Click for a larger version." class="hilite" height="716" src="https://static.righto.com/images/pentium-fdiv/table-labeled-w250.jpg" title="The 2048-entry lookup table used in the Pentium for division. The divisor is along the X-axis, from 1 to 2. The partial remainder is along the Y-axis, from -8 to 8. Click for a larger version." width="250" /></a><div class="cite">The 2048-entry lookup table used in the Pentium for division. The divisor is along the X-axis, from 1 to 2. The partial remainder is along the Y-axis, from -8 to 8. Click for a larger version.</div></p> <p>When the SRT algorithm uses the table, the partial remainder <em>p</em> and the divisor <em>d</em> are inputs. The divisor (scaled to fall between 1 and 2) provides the X coordinate into the table, while the partial remainder (between -8 and 8) provides the Y coordinate. The details of the table coordinates will be important, so I'll go into some detail. To select a cell, the divisor (X-axis) is truncated to a 5-bit binary value 1.dddd. (Since the first digit of the divisor is always 1, it is ignored for the table lookup.) The partial remainder (Y-axis) is truncated to a 7-bit signed binary value pppp.ppp. The 11 bits indexing into the table result in a table with 2<sup>11</sup> (2048) entries. The partial remainder is expressed in 2's complement, so values 0000.000 to 0111.111 are non-negative values from 0 to (almost) 8, while values 1000.000 to 1111.111 are negative values from -8 to (almost) 0. (To see the binary coordinates for the table, click on the image and zoom in.)</p> <h2>The lookup table is implemented in a Programmable Logic Array (PLA)</h2> <p>In this section, I'll explain how the lookup table is implemented in hardware in the Pentium. The lookup table has 2048 entries so it could be stored in a ROM with 2048 two-bit outputs.<span id="fnref:dimensions"><a class="ref" href="#fn:dimensions">11</a></span> (The sign is not explicitly stored in the table because the quotient digit sign is the same as the partial remainder sign.) However, because the table is highly structured (and largely empty), the table can be stored more compactly in a structure called a Programmable Logic Array (PLA).<span id="fnref:intel-pla"><a class="ref" href="#fn:intel-pla">12</a></span> By using a PLA, the Pentium stored the table in just 112 rows rather than 2048 rows, saving an enormous amount of space. Even so, the PLA is large enough on the chip that it is visible to the naked eye, if you squint a bit.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-zoom.jpg"><img alt="Zooming in on the PLA and associated circuitry on the Pentium die." class="hilite" height="514" src="https://static.righto.com/images/pentium-fdiv/pla-zoom-w600.jpg" title="Zooming in on the PLA and associated circuitry on the Pentium die." width="600" /></a><div class="cite">Zooming in on the PLA and associated circuitry on the Pentium die.</div></p> <p>The idea of a PLA is to provide a dense and flexible way of implementing arbitrary logic functions. Any Boolean logic function can be expressed as a "sum-of-products", a collection of AND terms (products) that are OR'd together (summed). A PLA has a block of circuitry called the AND plane that generates the desired sum terms. The outputs of the AND plane are fed into a second block, the OR plane, which ORs the terms together. The AND plane and the OR plane are organized as grids. Each gridpoint can either have a transistor or not, defining the logic functions. The point is that by putting the appropriate pattern of transistors in the grids, you can create any function. For the division PLA, there are has 22 inputs (the 11 bits from the divisor and partial remainder indices, along with their complements) and two outputs, as shown below.<span id="fnref:pla"><a class="ref" href="#fn:pla">13</a></span></p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-structure.jpg"><img alt="A simplified diagram of the division PLA." class="hilite" height="317" src="https://static.righto.com/images/pentium-fdiv/pla-structure-w400.jpg" title="A simplified diagram of the division PLA." width="400" /></a><div class="cite">A simplified diagram of the division PLA.</div></p> <p>A PLA is more compact than a ROM if the structure of the function allows it to be expressed with a small number of terms.<span id="fnref:rom"><a class="ref" href="#fn:rom">14</a></span> One difficulty with a PLA is figuring out how to express the function with the minimum number of terms to make the PLA as small as possible. It turns out that this problem is NP-complete in general. Intel used a program called Espresso to generate compact PLAs using heuristics.<span id="fnref:espresso"><a class="ref" href="#fn:espresso">15</a></span></p> <p>The diagram below shows the division PLA in the Pentium. The PLA has 120 rows, split into two 60-row parts with support circuitry in the middle.<span id="fnref:split"><a class="ref" href="#fn:split">16</a></span> The 11 table input bits go into the AND plane drivers in the middle, which produce the 22 inputs to the PLA (each table input and its complement). The outputs from the AND plane transistors go through output buffers and are fed into the OR plane. The outputs from the OR plane go through additional buffers and logic in the center, producing two output bits, indicating a ±1 or ±2 quotient. The image below shows the updated PLA that fixes the bug; the faulty PLA looks similar except the transistor pattern is different. In particular, the updated PLA has 46 unused rows at the bottom while the original, faulty PLA has 8 unused rows.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-labeled.jpg"><img alt="The division PLA with the metal layers removed to show the silicon. This image shows the PLA in the updated Pentium, since that photo came out better." class="hilite" height="802" src="https://static.righto.com/images/pentium-fdiv/pla-labeled-w450.jpg" title="The division PLA with the metal layers removed to show the silicon. This image shows the PLA in the updated Pentium, since that photo came out better." width="450" /></a><div class="cite">The division PLA with the metal layers removed to show the silicon. This image shows the PLA in the updated Pentium, since that photo came out better.</div></p> <p>The image below shows part of the AND plane of the PLA. At each point in the grid, a transistor can be present or absent. The pattern of transistors in a row determines the logic term for that row. The vertical doped silicon lines (green) are connected to ground. The vertical polysilicon lines (red) are driven with the input bit pattern. If a polysilicon line crosses doped silicon, it forms a transistor (orange) that will pull that row to ground when activated.<span id="fnref:demorgan"><a class="ref" href="#fn:demorgan">17</a></span> A metal line connects all the transistor rows in a row to produce the output; most of the metal has been removed, but some metal lines are visible at the right.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-silicon-right.jpg"><img alt="Part of the AND plane in the fixed Pentium. I colored the first silicon and polysilicon lines green and red respectively." class="hilite" height="430" src="https://static.righto.com/images/pentium-fdiv/pla-silicon-right-w600.jpg" title="Part of the AND plane in the fixed Pentium. I colored the first silicon and polysilicon lines green and red respectively." width="600" /></a><div class="cite">Part of the AND plane in the fixed Pentium. I colored the first silicon and polysilicon lines green and red respectively.</div></p> <p>By carefully examining the PLA under a microscope, I extracted the pattern of transistors in the PLA grid. (This was somewhat tedious.) From the transistor pattern, I could determine the equations for each PLA row, and then generate the contents of the lookup table. Note that the transistors in the PLA don't directly map to the table contents (unlike a ROM). Thus, there is no specific place for transistors corresponding to the 5 missing table entries.</p> <p>The left-hand side of the PLA implements the OR planes (below). The OR plane determines if the row output produces a quotient of 1 or 2. The OR plane is oriented 90° relative to the AND plane: the inputs are horizontal polysilicon lines (red) while the output lines are vertical. As before, a transistor (orange) is formed where polysilicon crosses doped silicon. Curiously, each OR plane has four outputs, even though the PLA itself has two outputs.<span id="fnref:outputs"><a class="ref" href="#fn:outputs">18</a></span></p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-lhs.jpg"><img alt="Part of the OR plane of the division PLA. I removed the metal layers to show the underlying silicon and polysilicon. I drew lines for ground and outputs, showing where the metal lines were." class="hilite" height="488" src="https://static.righto.com/images/pentium-fdiv/pla-lhs-w450.jpg" title="Part of the OR plane of the division PLA. I removed the metal layers to show the underlying silicon and polysilicon. I drew lines for ground and outputs, showing where the metal lines were." width="450" /></a><div class="cite">Part of the OR plane of the division PLA. I removed the metal layers to show the underlying silicon and polysilicon. I drew lines for ground and outputs, showing where the metal lines were.</div></p> <p>Next, I'll show exactly how the AND plane produces a term. For the division table, the inputs are the 7 partial remainder bits and 4 divisor bits, as explained earlier. I'll call the partial remainder bits p<sub>6</sub>p<sub>5</sub>p<sub>4</sub>p<sub>3</sub>.p<sub>2</sub>p<sub>1</sub>p<sub>0</sub> and the divisor bits 1.d<sub>3</sub>d<sub>2</sub>d<sub>1</sub>d<sub>0</sub>. These 11 bits and their complements are fed vertically into the PLA as shown at the top of the diagram below. These lines are polysilicon, so they will form transistor gates, turning on the corresponding transistor when activated. The arrows at the bottom point to nine transistors in the first row. (It's tricky to tell if the polysilicon line passes next to doped silicon or over the silicon, so the transistors aren't always obvious.) Looking at the transistors and their inputs shows that the first term in the PLA is generated by p<sub>0</sub>p<sub>1</sub>p<sub>2</sub>p<sub>3</sub>p<sub>4</sub>'p<sub>5</sub>p<sub>6</sub>d<sub>1</sub>d<sub>2</sub>.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-top-labeled.jpg"><img alt="The first row of the division PLA in a faulty Pentium." class="hilite" height="175" src="https://static.righto.com/images/pentium-fdiv/pla-top-labeled-w500.jpg" title="The first row of the division PLA in a faulty Pentium." width="500" /></a><div class="cite">The first row of the division PLA in a faulty Pentium.</div></p> <p>The diagram below is a closeup of the lookup table, showing how this PLA row assigns the value 1 to four table cells (dark blue). You can think of each term of the PLA as pattern-matching to a binary pattern that can include "don't care" values. The first PLA term (above) matches the pattern P=110.1111, D=x11x, where the "don't care" x values can be either 0 or 1. Since one PLA row can implement multiple table cells, the PLA is more efficient than a ROM; the PLA uses 112 rows, while a ROM would require 2048 rows.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-entry-diagram.jpg"><img alt="The first entry in the PLA assigns the value 1 to the four dark blue cells." class="hilite" height="242" src="https://static.righto.com/images/pentium-fdiv/pla-entry-diagram-w400.jpg" title="The first entry in the PLA assigns the value 1 to the four dark blue cells." width="400" /></a><div class="cite">The first entry in the PLA assigns the value 1 to the four dark blue cells.</div></p> <p>Geometrically, you can think of each PLA term (row) as covering a rectangle or rectangles in the table. However, the rectangle can't be arbitrary, but must be aligned on a bit boundary. Note that each "bump" in the table boundary (magenta) requires a separate rectangle and thus a separate PLA row. (This will be important later.)</p> <p>One PLA row can generate a large rectangle, filling in many table cells at once, if the region happens to be aligned nicely. For instance, the third term in the PLA matches d=xxxx, p=11101xx. This single PLA row efficiently fills in 64 table cells as shown below, replacing the 64 rows that would be required in a ROM.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-entry-diagram2.jpg"><img alt="The third entry in the PLA assigns the value 1 to the 64 dark blue cells." class="hilite" height="238" src="https://static.righto.com/images/pentium-fdiv/pla-entry-diagram2-w400.jpg" title="The third entry in the PLA assigns the value 1 to the 64 dark blue cells." width="400" /></a><div class="cite">The third entry in the PLA assigns the value 1 to the 64 dark blue cells.</div></p> <p>To summarize, the pattern of transistors in the PLA implements a set of equations, which define the contents of the table, setting the quotient to 1 or 2 as appropriate. Although the table has 2048 entries, the PLA represents the contents in just 112 rows. By carefully examining the transistor pattern, I determined the table contents in a faulty Pentium and a fixed Pentium.</p> <h2>The mathematical bounds of the lookup table</h2> <p>As shown earlier, the lookup table has regions corresponding to quotient digits of +2, +1, 0, -1, and -2. These regions have irregular, slanted shapes, defined by mathematical bounds. In this section, I'll explain these mathematical bounds since they are critical to understanding how the Pentium bug occurred.</p> <p>The essential step of the division algorithm is to divide the partial remainder <em>p</em> by the divisor <em>d</em> to get the quotient digit. The following diagram shows how <em>p/d</em> determines the quotient digit. The ratio <em>p/d</em> will define a point on the line at the top. (The point will be in the range [-8/3, 8/3] for mathematical reasons.) The point will fall into one of the five lines below, defining the quotient digit <em>q</em>. However, the five quotient regions overlap; if <em>p/d</em> is in one of the green segments, there are two possible quotient digits. The next part of the diagram illustrates how subtracting <em>q*d</em> from the partial remainder <em>p</em> shifts <em>p/d</em> into the middle, between -2/3 and 2/3. Finally, the result is multiplied by 4 (shifted left by two bits), expanding<span id="fnref:chaos"><a class="ref" href="#fn:chaos">19</a></span> the interval back to [-8/3, 8/3], which is the same size as the original interval. The 8/3 bound may seem arbitrary, but the motivation is that it ensures that the new interval is the same size as the original interval, so the process can be repeated. (The bounds are all thirds for algebraic reasons; the value 3 comes from base 4 minus 1.<span id="fnref:bound"><a class="ref" href="#fn:bound">20</a></span>)</p> <p><a href="https://static.righto.com/images/pentium-fdiv/intervals.jpg"><img alt="The input to a division step is processed, yielding the input to the next step." class="hilite" height="335" src="https://static.righto.com/images/pentium-fdiv/intervals-w550.jpg" title="The input to a division step is processed, yielding the input to the next step." width="550" /></a><div class="cite">The input to a division step is processed, yielding the input to the next step.</div></p> <p>Note that the SRT algorithm has some redundancy, but cannot handle <em>q</em> values that are "too wrong". Specifically, if <em>p/d</em> is in a green region, then either of two <em>q</em> values can be selected. However, the algorithm cannot recover from a bad <em>q</em> value in general. The relevant case is that if <em>q</em> is supposed to be 2 but 0 is selected, the next partial remainder will be outside the interval and the algorithm can't recover. This is what causes the FDIV bug.</p> <p>The diagram below shows the structure of the SRT lookup table (also called the P-D table since the axes are <em>p</em> and <em>d</em>). Each bound in the diagram above turns into a line in the table. For instance, the green segment above with <em>p/d</em> between 4/3 and 5/3 turns into a green region in the table below with <em>4/3 d ≤ p ≤ 5/3 d</em>. These slanted lines show the regions in which a particular quotient digit <em>q</em> can be used.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pd-table.jpg"><img alt="The P-D table specifies the quotient digit for a partial remainder (Y-axis) and divisor (X-axis)." class="hilite" height="686" src="https://static.righto.com/images/pentium-fdiv/pd-table-w350.jpg" title="The P-D table specifies the quotient digit for a partial remainder (Y-axis) and divisor (X-axis)." width="350" /></a><div class="cite">The P-D table specifies the quotient digit for a partial remainder (Y-axis) and divisor (X-axis).</div></p> <p>The lookup table in the Pentium is based on the above table, quantized with a <em>q</em> value in each cell. However, there is one more constraint to discuss.</p> <h2>Carry-save and carry-lookahead adders</h2> <p>The Pentium's division circuitry uses a special circuit to perform addition and subtraction efficiently: the carry-save adder. One consequence of this adder is that each access to the lookup table may go to the cell just below the "right" cell. This is expected and should be fine, but in very rare and complicated circumstances, this behavior causes an access to one of the Pentium's five missing cells, triggering the division bug. In this section, I'll discuss why the division circuitry uses a carry-save adder, how the carry-save adder works, and how the carry-save adder triggers the FDIV bug.</p> <p>The problem with addition is that carries make addition slow. Consider calculating 99999+1 by hand. You'll start with 9+1=10, then carry the one, generating another carry, which generates another carry, and so forth, until you go through all the digits. Computer addition has the same problem. If you're adding, say, two 64-bit numbers, the low-order bits can generate a carry that then propagates through all 64 bits. The time for the carry signal to go through 64 layers of circuitry is significant and can limit CPU performance. As a result, CPUs use special circuits to make addition faster.</p> <p>The Pentium's division circuitry uses an unusual adder circuit called a carry-save adder to add (or subtract) the divisor and the partial remainder. A carry-save adder speeds up addition if you are performing a bunch of additions, as happens during division. The idea is that instead of adding a carry to each digit as it happens, you hold onto the carries in a separate word. As a decimal example, 499+222 would be 611 with carries 011; you don't carry the one to the second digit, but hold onto it. The next time you do an addition, you add in the carries you saved previously, and again save any new carries. The advantage of the carry-save adder is that the sum and carry at each digit position can be computed in parallel, which is fast. The disadvantage is that you need to do a slow addition at the end of the sequence of additions to add in the remaining carries to get the final answer. But if you're performing multiple additions (as for division), the carry-save adder is faster overall.</p> <p>The carry-save adder creates a problem for the lookup table. We need to use the partial remainder as an index into the lookup table. But the carry-save adder splits the partial remainder into two parts: the sum bits and the carry bits. To get the table index, we need to add the sum bits and carry bits together. Since this addition needs to happen for every step of the division, it seems like we're back to using a slow adder and the carry-save adder has just made things worse.</p> <p>The trick is that we only need 7 bits of the partial remainder for the table index, so we can use a different type of adder—a carry-lookahead adder—that calculates each carry in parallel using brute force logic. The logic in a carry-lookahead adder gets more and more complex for each bit so a carry-lookahead adder is impractical for large words, but it is practical for a 7-bit value.</p> <p>The photo below shows the carry-lookahead adder used by the divider. Curiously, the adder is an 8-bit adder but only 7 bits are used; perhaps the 8-bit adder was a standard logic block at Intel.<span id="fnref:8bit"><a class="ref" href="#fn:8bit">21</a></span> I'll just give a quick summary of the adder here, and leave the details for another post. At the top, logic gates compute signals in parallel for each of the 8 pairs of inputs: sum, carry generate, and carry propagate. Next, the complex carry-lookahead logic determines in parallel if there will be a carry at each position. Finally, XOR gates apply the carry to each bit. The circuitry in the middle is used for testing; see the footnote.<span id="fnref:testing"><a class="ref" href="#fn:testing">22</a></span> At the bottom, the drivers amplify control signals for various parts of the adder and send the PLA output to other parts of the chip.<span id="fnref:bicmos"><a class="ref" href="#fn:bicmos">23</a></span> By counting the blocks of repeated circuitry, you can see which blocks are 8 bits wide, 11, bits wide, and so forth. The carry-lookahead logic is different for each bit, so there is no repeated structure.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/adder-silicon.jpg"><img alt="The carry-lookahead adder that feeds the lookup table. This block of circuitry is just above the PLA on the die. I removed the metal layers, so this photo shows the doped silicon (dark) and the polysilicon (faint gray)." class="hilite" height="859" src="https://static.righto.com/images/pentium-fdiv/adder-silicon-w600.jpg" title="The carry-lookahead adder that feeds the lookup table. This block of circuitry is just above the PLA on the die. I removed the metal layers, so this photo shows the doped silicon (dark) and the polysilicon (faint gray)." width="600" /></a><div class="cite">The carry-lookahead adder that feeds the lookup table. This block of circuitry is just above the PLA on the die. I removed the metal layers, so this photo shows the doped silicon (dark) and the polysilicon (faint gray).</div></p> <p>The carry-save and carry-lookahead adders may seem like implementation trivia, but they are a critical part of the FDIV bug because they change the constraints on the table. The cause is that the partial remainder is 64 bits,<span id="fnref:64-bits"><a class="ref" href="#fn:64-bits">24</a></span> but the adder that computes the table index is 7 bits. Since the rest of the bits are truncated before the sum, the partial remainder sum for the table index can be slightly lower than the real partial remainder. Specifically, the table index can be one cell lower than the correct cell, an offset of 1/8. Recall the earlier diagram with diagonal lines separating the regions. Some (but not all) of these lines must be shifted down by 1/8 to account for the carry-save effect, but Intel made the wrong adjustment, which is the root cause of the FDIV error. (This effect was well-known at the time and mentioned in papers on SRT division, so Intel shouldn't have gotten it wrong.)</p> <p>An interesting thing about the FDIV bug is how extremely rare it is. With 5 bad table entries out of 2048, you'd expect erroneous divides to be very common. However, for complicated mathematical reasons involving the carry-save adder the missing table entries are almost never encountered: only about 1 in 9 billion random divisions will encounter a problem. To hit a missing table entry, you need an "unlucky" result from the carry-save adder multiple times in a row, making the odds similar to winning the lottery, if the lottery prize were a division error.<span id="fnref:heatmaps"><a class="ref" href="#fn:heatmaps">25</a></span></p> <h2>What went wrong in the lookup table</h2> <p>I consider the diagram below to be the "smoking gun" that explains how the FDIV bug happens: the top magenta line should be above the sloping black line, but it crosses the black line repeatedly. The magenta line carefully stays above the gray line, but that's the wrong line. In other words, Intel picked the wrong bounds line when defining the +2 region of the table. In this section, I'll explain why that causes the bug.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/bounds2.jpg"><img alt="The top half of the lookup table, explaining the root of the FDIV bug." class="hilite" height="469" src="https://static.righto.com/images/pentium-fdiv/bounds2-w500.jpg" title="The top half of the lookup table, explaining the root of the FDIV bug." width="500" /></a><div class="cite">The top half of the lookup table, explaining the root of the FDIV bug.</div></p> <p>The diagram is colored according to the quotient values stored in the Pentium's lookup table: yellow is +2, blue is +1, and white is 0, with magenta lines showing the boundaries between different values. The diagonal black lines are the mathematical constraints on the table, defining the region that must be +2, the region that can be +1 or +2, the region that must be +1, and so forth. For the table to be correct, each cell value in the table must satisfy these constraints. The middle magenta line is valid: it remains between the two black lines (the redundant +1 or +2 region), so all the cells that need to be +1 are +1 and all the cells that need to be +2 are +2, as required. Likewise, the bottom magenta line remains between the black lines. However, the top magenta line is faulty: it must remain above the top black line, but it crosses the black line. The consequence is that some cells that need to be +2 end up holding 0: these are the missing cells that caused the FDIV bug.</p> <p>Note that the top magenta line stays above the diagonal gray line while following it as closely as possible. If the gray line were the correct line, the table would be perfect. Unfortunately, Intel picked the wrong constraint line for the table's upper bound when the table was generated.<span id="fnref:bounds"><a class="ref" href="#fn:bounds">26</a></span></p> <p>But why are some diagonal lines lowered by 1/8 and other lines are not lowered? As explained in the previous section, as a consequence of the carry-save adder truncation, the table lookup may end up one cell lower than the actual <em>p</em> value would indicate, i.e. the <em>p</em> value for the table index is 1/8 lower than that actual value. Thus, both the correct cell and the cell below must satisfy the SRT constraints. Thus, the line moves down if that makes the constraints stricter but does not move down if that would expand the redundant area. In particular, the top line must not be move down, but clearly Intel moved the line down and generated the faulty lookup table.</p> <!-- Next, let's look at the design and manufacturing steps between the table and the chip. The lookup table is defined mathematically by the sloping lines that separate its regions. The 2048 cells of the table were assigned according to these lines. Next, the table was processed to form the optimized set of PLA entries using the Espresso tool. These entries were loaded into the Pentium's RTL model as well as the layout representation. The layout representation defined the physical layout of the transistors and wiring on the chip. The layout was used to create masks, which were then used to fabricate the integrated circuits. I don't know all the details of Intel's design automation software, so my list of steps is slightly speculative. --> <p>Intel, however, has a different explanation for the bug. The Intel white paper states that the problem was in a script that downloaded the table into a PLA: an error caused the script to omit a few entries from the PLA.<span id="fnref:script"><a class="ref" href="#fn:script">27</a></span> I don't believe this explanation: the missing terms match a mathematical error, not a copying error. I suspect that Intel's statement is technically true but misleading: they ran a C program (which they called a script) to generate the table but the program had a mathematical error in the bounds.</p> <p>In his book "The Pentium Chronicles", Robert Colwell, architect of the Pentium Pro, provides a different explanation of the FDIV bug. Colwell claims that the Pentium design originally used the same lookup table as the 486, but shortly before release, the engineers were pressured by management to shrink the circuitry to save die space. The engineers optimized the table to make it smaller and had a proof that the optimization would work. Unfortunately, the proof was faulty, but the testers trusted the engineers and didn't test the modification thoroughly, causing the Pentium to be released with the bug. The problem with this explanation is that the Pentium was designed from the start with a completely different division algorithm from the 486: the Pentium uses radix-4 SRT, while the 486 uses standard binary division. Since the 486 doesn't have a lookup table, the story falls apart. Moreover, the PLA could trivially have been made smaller by removing the 8 unused rows, so the engineers clearly weren't trying to shrink it. My suspicion is that since Colwell developed the Pentium Pro in Oregon but the original Pentium was developed in California, Colwell didn't get firsthand information on the Pentium problems.</p> <h2>How Intel fixed the bug</h2> <p>Intel's fix for the bug was straightforward but also surprising. You'd expect that Intel added the five missing table values to the PLA, and this is what was reported at the time. The <a href="https://www.nytimes.com/1994/11/24/business/company-news-flaw-undermines-accuracy-of-pentium-chips.html">New York Times</a> wrote that Intel fixed the flaw by adding several dozen transistors to the chip. <a href="https://davefaq.com/Opinions/Stupid/Pentium.html">EE Times</a> wrote that "The fix entailed adding terms, or additional gate-sequences, to the PLA."</p> <p>However, the updated PLA (below) shows something entirely different. The updated PLA is exactly the same size as the original PLA. However, about 1/3 of the terms were <em>removed</em> from the PLA, eliminating hundreds of transistors. Only 74 of the PLA's 120 rows are used, and the rest are left empty. (The original PLA had 8 empty rows.) How could removing terms from the PLA fix the problem?</p> <p><a href="https://static.righto.com/images/pentium-fdiv/new-pla.jpg"><img alt="The updated PLA has 46 unused rows." class="hilite" height="735" src="https://static.righto.com/images/pentium-fdiv/new-pla-w300.jpg" title="The updated PLA has 46 unused rows." width="300" /></a><div class="cite">The updated PLA has 46 unused rows.</div></p> <p>The explanation is that Intel didn't just fill in the five missing table entries with the correct value of 2. Instead, Intel filled <em>all</em> the unused table entries with 2, as shown below. This has two effects. First, it eliminates any possibility of hitting a mistakenly-empty entry. Second, it makes the PLA equations much simpler. You might think that more entries in the table would make the PLA larger, but the number of PLA terms depends on the structure of the data. By filling the unused cells with 2, the jagged borders between the unused regions (white) and the "2" regions (yellow) disappear. As explained earlier, a large rectangle can be covered by a single PLA term, but a jagged border requires a lot of terms. Thus, the updated PLA is about 1/3 smaller than the original, flawed PLA. One consequence is that the terms in the new PLA are completely different from the terms in the old PLA so one can't point to the specific transistors that fixed the bug.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/old-vs-new.jpg"><img alt="Comparison of the faulty lookup table (left) and the corrected lookup table (right)." class="hilite" height="546" src="https://static.righto.com/images/pentium-fdiv/old-vs-new-w400.jpg" title="Comparison of the faulty lookup table (left) and the corrected lookup table (right)." width="400" /></a><div class="cite">Comparison of the faulty lookup table (left) and the corrected lookup table (right).</div></p> <p>The image below shows the first 14 rows of the faulty PLA and the first 14 rows of the fixed PLA. As you can see, the transistor pattern (and thus the PLA terms) are entirely different. The doped silicon is darkened in the second image due to differences in how I processed the dies to remove the metal layers.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/comparison.jpg"><img alt="Top of the faulty PLA (left) and the fixed PLA (right). The metal layers were removed to show the silicon of the transistors. (Click for a larger image.)" class="hilite" height="301" src="https://static.righto.com/images/pentium-fdiv/comparison-w700.jpg" title="Top of the faulty PLA (left) and the fixed PLA (right). The metal layers were removed to show the silicon of the transistors. (Click for a larger image.)" width="700" /></a><div class="cite">Top of the faulty PLA (left) and the fixed PLA (right). The metal layers were removed to show the silicon of the transistors. (Click for a larger image.)</div></p> <h2>Impact of the FDIV bug</h2> <p>How important is the Pentium bug? This became a highly controversial topic. A failure of a random division operation is very rare: about one in 9 billion values will trigger the bug. Moreover, an erroneous division is still mostly accurate: the error is usually in the 9th or 10th decimal digit, with rare worst-case error in the 4th significant digit. Intel's <a href="https://www.ardent-tool.com/CPU/Intel/fdiv/white11.pdf">whitepaper</a> claimed that a typical user would encounter a problem once every 27,000 years, insignificant compared to other sources of error such as DRAM bit flips. Intel said: "Our overall conclusion is that the flaw in the floating point unit of the Pentium processor is of no concern to the vast majority of users. A few users of applications in the scientific/engineering and financial engineering fields may need to employ either an updated processor without the flaw or a software workaround."</p> <p>However, IBM performed their own analysis,<span id="fnref:ibm"><a class="ref" href="#fn:ibm">29</a></span> suggesting that the problem could hit customers every few days, and IBM suspended Pentium sales. (Coincidentally, IBM had a competing processor, the PowerPC.) The battle made it to major newspapers; the Los Angeles Times split the difference with <a href="https://www.latimes.com/archives/la-xpm-1994-12-17-fi-9948-story.html">Study Finds Both IBM, Intel Off on Error Rate</a>. Intel soon gave in and agreed to replace all the Pentiums, making the issue moot.</p> <p>I mostly agree with Intel's analysis. It appears that only one person (Professor Nicely) noticed the bug in actual use.<span id="fnref:legends"><a class="ref" href="#fn:legends">28</a></span> The IBM analysis seems contrived to hit numbers that trigger the error. Most people would never hit the bug and even if they hit it, a small degradation in floating-point accuracy is unlikely to matter to most people. Looking at society as a whole, replacing the Pentiums was a huge expense for minimal gain. On the other hand, it's reasonable for customers to expect an accurate processor.</p> <p>Note that the Pentium bug is deterministic: if you use a specific divisor and dividend that trigger the problem, you will get the wrong answer 100% of the time. Pentium engineer Ken Shoemaker suggested that the outcry over the bug was because it was so easy for customers to reproduce. It was hard for Intel to argue that customers would never encounter the bug when customers could trivially see the bug on their own computer, even if the situation was artificial.</p> <h2>Conclusions</h2> <p>The FDIV bug is one of the most famous processor bugs. By examining the die, it is possible to see exactly where it is on the chip. But Intel has had other important bugs. Some early 386 processors had a 32-bit multiply problem. Unlike the deterministic FDIV bug, the 386 would unpredictably produce the wrong results under particular temperature/voltage/frequency conditions. The underlying issue was a layout problem that didn't provide enough electrical margin to handle the worst-case situation. Intel sold the faulty chips but restricted them to the 16-bit market; bad chips were labeled "16 BIT S/W ONLY", while the good processors were marked with a double sigma. Although Intel had to suffer through embarrassing headlines such as <a href="https://archive.org/details/bub_gb_mDsEAAAAMBAJ/page/n5/mode/1up?view=theater">Some 386 Systems Won't Run 32-Bit Software, Intel Says</a>, the bug was soon forgotten.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/steppings.jpg"><img alt="Bad and good versions of the 386. Note the labels on the bottom line. Photos (L), (R) by Thomas Nguyen, (CC BY-SA 4.0)" class="hilite" height="205" src="https://static.righto.com/images/pentium-fdiv/steppings-w400.jpg" title="Bad and good versions of the 386. Note the labels on the bottom line. Photos (L), (R) by Thomas Nguyen, (CC BY-SA 4.0)" width="400" /></a><div class="cite">Bad and good versions of the 386. Note the labels on the bottom line. Photos (<a href="https://commons.wikimedia.org/wiki/File:Intel_A80386-16_16_bit_SW_Only.jpg">L</a>), (<a href="https://commons.wikimedia.org/wiki/File:Intel_A80386-16_%CE%A3%CE%A3.jpg">R</a>) by Thomas Nguyen, (<a href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">CC BY-SA 4.0</a>)</div></p> <p>Another memorable Pentium issue was the "F00F bug", a problem where a particular instruction sequence starting with F0 0F would cause the processor to lock up until rebooted.<span id="fnref:f00f"><a class="ref" href="#fn:f00f">30</a></span> The bug was found in 1997 and solved with an operating system update. The bug is presumably in the Pentium's voluminous microcode. The microcode is too complex for me to analyze, so don't expect a detailed blog post on this subject. :-)</p> <p>You might wonder why Intel needed to release a new revision of the Pentium to fix the FDIV bug, rather than just updating the microcode. The problem was that microcode for the Pentium (and earlier processors) was hard-coded into a ROM and couldn't be modified. Intel added patchable microcode to the Pentium Pro (1995), allowing limited modifications to the microcode. Intel originally implemented this feature for chip debugging and testing. But after the FDIV bug, Intel realized that patchable microcode was valuable for bug fixes too.<span id="fnref:patchable"><a class="ref" href="#fn:patchable">31</a></span> The Pentium Pro stores microcode in ROM, but it also has a static RAM that holds up to 60 microinstructions. During boot, the BIOS can load a microcode patch into this RAM. In modern Intel processors, microcode patches have been used for problems ranging from the <a href="https://support.microsoft.com/en-us/topic/kb4090007-intel-microcode-updates-3bdf784b-d4ad-d881-cfc1-658095b59638">Spectre</a> vulnerability to <a href="https://community.intel.com/t5/Processors/Microcode-0x129-Update-for-Intel-Core-13th-and-14th-Gen-Desktop/m-p/1622129">voltage problems</a>.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/pla-m2.jpg"><img alt="The Pentium PLA with the top metal layer removed, revealing the M2 and M1 layers. The OR and AND planes are at the top and bottom, with drivers and control logic in the middle." class="hilite" height="872" src="https://static.righto.com/images/pentium-fdiv/pla-m2-w250.jpg" title="The Pentium PLA with the top metal layer removed, revealing the M2 and M1 layers. The OR and AND planes are at the top and bottom, with drivers and control logic in the middle." width="250" /></a><div class="cite">The Pentium PLA with the top metal layer removed, revealing the M2 and M1 layers. The OR and AND planes are at the top and bottom, with drivers and control logic in the middle.</div></p> <p>As the number of transistors in a processor increased exponentially, as described by Moore's Law, processors used more complex circuits and algorithms. Division is one example. Early microprocessors such as the Intel 8080 (1974, 6000 transistors) had no hardware support for division or floating point arithmetic. The Intel 8086 (1978, 29,000 transistors) implemented integer division in microcode but required the 8087 coprocessor chip for floating point. The Intel 486 (1989, 1.2 million transistors) added floating-point support on the chip. The Pentium (1993, 3.1 million transistors) moved to the faster but more complicated SRT division algorithm. The Pentium's division PLA alone has roughly 4900 transistor sites, more than a MOS Technology 6502 processor—one component of the Pentium's division circuitry uses more transistors than an entire 1975 processor.</p> <p>The long-term effect of the FDIV bug on Intel is a subject of debate. On the one hand, competitors such as AMD benefitted from Intel's error. AMD's <a href="https://bsky.app/profile/trevorkevorson.bsky.social/post/3lcnv6h65hc26">ads</a> poked fun at the Pentium's problems by listing features of AMD's chips such as "You don't have to double check your math" and "Can actually handle the rigors of complex calculations like <em>division</em>." On the other hand, Robert Colwell, architect of the Pentium Pro, said that the FDIV bug may have been a net benefit to Intel as it created enormous name recognition for the Pentium, along with a demonstration that Intel was willing to back up its brand name. Industry writers agreed; see <a href="https://websrv.cecs.uci.edu/~papers/mpr/MPR/EDITOR/0903ed.pdf">The Upside of the Pentium Bug</a>. In any case, Intel survived the FDIV bug; time will tell how Intel survives its current problems.</p> <p>I plan to write more about the implementation of the Pentium's PLA, the adder, and the test circuitry. Until then, you may enjoy reading about the <a href="https://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html">Pentium Navajo rug</a>. (The rug represents the P54C variant of the Pentium, so it is safe from the FDIV bug.) Thanks to Bob Colwell and Ken Shoemaker for helpful discussions.</p> <h1>Footnotes and references</h1> <div class="footnote"> <ol> <li id="fn:dham"> <p>The book <a href="https://amzn.to/4gcXzVS">Inside Intel</a> says that Vin Dham, the "Pentium czar", found the FDIV problem in May 1994. The book "The Pentium Chronicles" says that Patrice Roussel, the floating-point architect for Intel's upcoming Pentium Pro processor, found the FDIV problem in Summer 1994. I suspect that the bug was kept quiet inside Intel and was discovered more than once. <a class="footnote-backref" href="#fnref:dham" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:prime"> <p>The divisor being a prime number has nothing to do with the bug. It's just a coincidence that the problem was found during research with prime numbers. <a class="footnote-backref" href="#fnref:prime" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:timeline"> <p>See Nicely's <a href="https://faculty.lynchburg.edu/~nicely/#PENT">FDIV page</a> for more information on the bug and its history. Other sources are the books <a href="https://amzn.to/4gAD1pM">Creating the Digital Future</a>, <a href="https://amzn.to/4gl8mx9">The Pentium Chronicles</a>, and <a href="https://amzn.to/4gcXzVS">Inside Intel</a>. The New York Times wrote about the bug: <a href="https://www.nytimes.com/1994/11/24/business/company-news-flaw-undermines-accuracy-of-pentium-chips.html">Flaw Undermines Accuracy of Pentium Chips</a>. Computerworld wrote <a href="https://books.google.com/books?id=LbKf4ilmW8EC&pg=PA1">Intel Policy Incites User Threats</a> on threats of a class-action lawsuit. IBM's response is described in <a href="https://www.nytimes.com/1994/12/13/us/ibm-deals-blow-to-a-rival-as-it-suspends-pentium-sales.html">IBM Deals Blow to a Rival as it Suspends Pentium Sales</a> <a class="footnote-backref" href="#fnref:timeline" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:letterman"> <p>Talk show host David Letterman <a href="http://lists.sigcis.org/pipermail/members-sigcis.org/2020-August/007088.html">joked</a> about the Pentium on <a href="https://groups.google.com/g/comp.sys.intel/c/xivOgqcUrS8/m/sODzYaJZzWMJ">December 15</a>: "You know what goes great with those defective Pentium chips? Defective Pentium salsa!" Although a list of Letterman-style <a href="https://groups.google.com/g/aus.jokes/c/72sZitg-bTY/m/LCMN-LRD6egJ">top ten Pentium slogans</a> circulated, the list was a Usenet creation. There's a <a href="https://historyofcomputers.eu/hardware/the-pentium-fdiv-bug-when-math-became-a-stand-up-comedy-act/">claim</a> that Jay Leno also joked about the Pentium, but I haven't found verification. <a class="footnote-backref" href="#fnref:letterman" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:errata"> <p>Processors have many more bugs than you might expect. Intel's 1995 errata list for the Pentium had "21 errata (including the FDIV problem), 4 changes, 16 clarifications, and 2 documentation changes." See <a href="https://ardent-tool.com/CPU/docs/Intel/Pentium/spec_update/242480-022.pdf">Pentium Processor Specification Update</a> and <a href="https://websrv.cecs.uci.edu/~papers/mpr/MPR/ARTICLES/090303.pdf">Intel Releases Pentium Errata List</a>. <a class="footnote-backref" href="#fnref:errata" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:apology"> <p>Intel published full-page newspaper ads apologizing for its handling of the problem, stating: "What Intel continues to believe is an extremely minor technical problem has taken on a life of its own."</p> <p><a href="https://static.righto.com/images/pentium-fdiv/apology.jpg"><img alt="Intel's apology letter, published in Financial Times. Note the UK country code in the phone number." class="hilite" height="771" src="https://static.righto.com/images/pentium-fdiv/apology-w500.jpg" title="Intel's apology letter, published in Financial Times. Note the UK country code in the phone number." width="500" /></a><div class="cite">Intel's apology letter, published in <a href="https://archive.org/details/FinancialTimes1994UKEnglish/Dec%2022%201994%2C%20Financial%20Times%2C%20%2322%2C%20UK%20%28en%29/page/n4/mode/1up">Financial Times</a>. Note the UK country code in the phone number.</div></p> <p><!-- --> <a class="footnote-backref" href="#fnref:apology" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:coe"> <p>Tim Coe's reverse engineering of the Pentium divider was described on the Usenet group <a href="https://groups.google.com/g/comp.sys.intel/c/L1KDE1d_ZLA/m/7rydJksrVTcJ">comp.sys.intel</a>, archived <a href="https://daviddeley.com/pentbug/tim_coe.txt">here</a>. To summarize, Andreas Kaiser found 23 failing reciprocals. Tim Coe determined that most of these failing reciprocals were of the form 3*(2^(K+30)) - 1149*(2^(K-(2*J))) - delta*(2^(K-(2*J))). He recognized that the factor of 2 indicated a radix-4 divider. The extremely low probability of error indicated the presence of a carry save adder; the odds of both the sum and carry bits getting long patterns of ones were very low. Coe constructed a simulation of the divider that matched the Pentium's behavior and noted which table entries must be faulty. <a class="footnote-backref" href="#fnref:coe" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:papers"> <p>The main papers on the FDIV bug are <a href="https://people.cs.vt.edu/~naren/Courses/CS3414/assignments/pentium.pdf">Computational Aspects of the Pentium Affair</a>, <a href="https://doi.org/10.1109/ARITH.1995.465365">It Takes Six Ones to Reach a Flaw</a>, <a href="https://www.jstor.org/stable/2133004">The Mathematics of the Pentium Division Bug</a>, <a href="https://web.archive.org/web/20060209005434/http://www.byte.com/art/9503/sec13/art1.htm">The Truth Behind the Pentium Bug</a>, <a href="http://link.springer.com/10.1007/3-540-59293-8_189">Anatomy of the Pentium Bug</a>, and <a href="http://boole.stanford.edu/pentium.html">Risk Analysis of the Pentium Bug</a>. Intel's whitepaper is <a href="https://www.ardent-tool.com/CPU/Intel/fdiv/white11.pdf">Statistical Analysis of Floating Point Flaw in the Pentium Processor</a>; I archived IBM's study <a href="https://righto.com/files/IBM_study.txt">here</a>. <a class="footnote-backref" href="#fnref:papers" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:ieee754"> <p>The Pentium uses floating point numbers that follow the IEEE 754 standard. Internally, floating point numbers are represented with 80 bits: 1 bit for the sign, 15 bits for the exponent, and 64 bits for the significand. Externally, floating point numbers are 32-bit single-precision numbers or 64-bit double-precision numbers. Note that the number of significand bits limits the accuracy of a floating-point number. <a class="footnote-backref" href="#fnref:ieee754" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:srt-history"> <p>The SRT division algorithm is named after the three people who independently created it in 1957-1958: Sweeney at IBM, Robertson at the University of Illinois, and Tocher at Imperial College London. The SRT algorithm was developed further by Atkins in his <a href="https://www.osti.gov/biblio/4157138">PhD research</a> (1970).</p> <p>The SRT algorithm became more practical in the 1980s as chips became denser. Taylor <a href="https://www.doi.org/10.1109/ARITH.1981.6159293">implemented</a> the SRT algorithm on a board with 150 chips in 1981. The IEEE floating point standard (1985) led to a market for faster floating point circuitry. For instance, the Weitek 4167 floating-point coprocessor chip (1989) was designed for use with the Intel 486 CPU (<a href="http://www.bitsavers.org/components/weitek/dataSheets/4167_Floating-Point_Coprocessor_Jul89.pdf">datasheet</a>) and described in <a href="https://www.ece.ucdavis.edu/~vojin/CLASSES/EPFL/Papers/4-Fandrianto_division_ARITH8.pdf">an influential paper</a>. Another important SRT implementation is the MIPS R3010 (1988), the coprocessor for the R3000 RISC processor. The MIPS R3010 uses radix-4 SRT for division with 9 bits from the partial remainder and 9 bits from the divisor, making for a larger lookup table and adder than the Pentium (<a href="https://doi.org/10.1109/40.540">link</a>).</p> <p>To summarize, when Intel wanted to make division faster on the Pentium (1993), the SRT algorithm was a reasonable choice. Competitors had already implemented SRT and multiple papers explained how SRT worked. The implementation should have been straightforward and bug-free. <a class="footnote-backref" href="#fnref:srt-history" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:dimensions"> <p>The dimensions of the lookup table can't be selected arbitrarily. In particular, if the table is too small, a cell may need to hold two different q values, which isn't possible. Note that constructing the table is only possible due to the redundancy of SRT. For instance, if some values in the call require q=1 and other values require q=1 or 2, then the value q=1 can be assigned to the cell. <a class="footnote-backref" href="#fnref:dimensions" title="Jump back to footnote 11 in the text">↩</a></p> </li> <li id="fn:intel-pla"> <p>In the white paper, Intel calls the PLA a Programmable Lookup Array, but that's an error; it's a Programmable <em>Logic</em> Array. <a class="footnote-backref" href="#fnref:intel-pla" title="Jump back to footnote 12 in the text">↩</a></p> </li> <li id="fn:pla"> <p>I'll explain a PLA in a bit more detail in this footnote. An example of a sum-of-products formula with inputs a and b is ab' + a'b + ab. This formula has three sum terms, so it requires three rows in the PLA. However, this formula can be reduced to a + b, which uses a smaller two-row PLA. Note that any formula can be trivially expressed with a separate product term for each 1 output in the truth table. The hard part is optimizing the PLA to use fewer terms. The original PLA patent is probably <a href="https://patents.google.com/patent/US3702985A">MOS Transistor Integrated Matrix</a> from 1969. <a class="footnote-backref" href="#fnref:pla" title="Jump back to footnote 13 in the text">↩</a></p> </li> <li id="fn:rom"> <p>A ROM and a PLA have many similarities. You can implement a ROM with a PLA by using the AND terms to decode addresses and the OR terms to hold the data. Alternatively, you can replace a PLA with a ROM by putting the function's truth table into the ROM. ROMs are better if you want to hold arbitrary data that doesn't have much structure (such as the microcode ROMs). PLAs are better if the functions have a lot of underlying structure. The key theoretical difference between a ROM and a PLA is that a ROM activates exactly one row at a time, corresponding to the address, while a PLA may activate one row, no rows, or multiple rows at a time. Another alternative for representing functions is to use logic gates directly (known as random logic); moving from the 286 to the 386, Intel replaced many small PLAs with logic gates, enabled by improvements in the standard-cell software. Intel's design process is described in <a href="https://www.researchgate.net/publication/268005718_Coping_with_the_Complexity_of_Microprocessor_Design_at_Intel_-_A_CAD_History">Coping with the Complexity of Microprocessor Design</a>. <a class="footnote-backref" href="#fnref:rom" title="Jump back to footnote 14 in the text">↩</a></p> </li> <li id="fn:espresso"> <p>In 1982, Intel developed a program called LOGMIN to automate PLA design. The original LOGMIN used an exhaustive exponential search, limiting its usability. See <a href="https://doi.org/10.1109/DAC.1982.1585495">A Logic Minimizer for VLSI PLA Design</a>. For the <a href="https://www.youtube.com/watch?v=LQcLhBZY12g&t=1700s">386</a>, Intel used <a href="https://en.wikipedia.org/wiki/Espresso_heuristic_logic_minimizer">Espresso</a>, a heuristic PLA minimizer that originated at IBM and was developed at UC Berkeley. Intel probably used Espresso for the Pentium, but I can't confirm that. <a class="footnote-backref" href="#fnref:espresso" title="Jump back to footnote 15 in the text">↩</a></p> </li> <li id="fn:split"> <p>The Pentium's PLA is split into a top half and a bottom half, so you might expect the top half would generate a quotient of 1 and the bottom half would generate a quotient of 2. However, the rows for the two quotients are shuffled together with no apparent pattern. I suspect that the PLA minimization software generated the order arbitrarily. <a class="footnote-backref" href="#fnref:split" title="Jump back to footnote 16 in the text">↩</a></p> </li> <li id="fn:demorgan"> <p>Conceptually, the PLA consists of AND gates feeding into OR gates. To simplify the implementation, both layers of gates are actually NOR gates. Specifically, if any transistor in a row turns on, the row will be pulled to ground, producing a zero. De Morgan's laws show that the two approaches are the same, if you invert the inputs and outputs. I'm ignoring this inversion in the diagrams.</p> <p>Note that each square can form a transistor on the left, the right, or both. The image must be examined closely to distinguish these cases. Specifically, if the polysilicon line produces a transistor, horizontal lines are visible in the polysilicon. If there are no horizontal lines, the polysilicon passes by without creating a transistor. <a class="footnote-backref" href="#fnref:demorgan" title="Jump back to footnote 17 in the text">↩</a></p> </li> <li id="fn:outputs"> <p>Each OR plane has four outputs, so there are eight outputs in total. These outputs are combined with logic gates to generate the desired two outputs (quotient of 1 or 2). I'm not sure why the PLA is implemented in this fashion. Each row alternates between an output on the left and an output on the right, but I don't think this makes the layout any denser. As far as I can tell, the extra outputs just waste space. One could imagine combining the outputs in a clever way to reduce the number of terms, but instead the outputs are simply OR'd together. <a class="footnote-backref" href="#fnref:outputs" title="Jump back to footnote 18 in the text">↩</a></p> </li> <li id="fn:chaos"> <p>The dynamics of the division algorithm are interesting. The computation of a particular division will result in the partial remainder bouncing from table cell to table cell, while remaining in one column of the table. I expect this could be analyzed in terms of chaotic dynamics. Specifically, the partial remainder interval is squished down by the subtraction and then expanded when multiplied by 4. This causes low-order bits to percolate upward so the result is exponentially sensitive to initial conditions. I think that the division behavior satisfies the definition of chaos in <a href="https://mathscinet.ams.org/mathscinet/relay-station?mr=1010233">Dynamics of Simple Maps</a>, but I haven't investigated this in detail.</p> <p>You can see this chaotic behavior with a base-10 division, e.g. compare 1/3.0001 to 1/3.0002: <br/><code>1/3.0001=0.333322222592580247325089163694543515216... 1/3.0002=0.333311112592493833744417038864075728284...</code><br/> Note that the results start off the same but are completely divergent by 15 digits. (The division result itself isn't chaotic, but the sequence of digits is.)</p> <p>I tried to make a fractal out of the SRT algorithm and came up with the image below. There are 5 bands for convergence, each made up of 5 sub-bands, each made up of 5 sub-sub bands, and so on, corresponding to the 5 q values.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/fractal.jpg"><img alt="A fractal showing convergence or divergence of SRT division as the scale factor (X-axis) ranges from the normal value of 4 to infinity. The Y-axis is the starting partial remainder. The divisor is (arbitrarily) 1.5. Red indicates convergence; gray is darker as the value diverges faster." class="hilite" height="500" src="https://static.righto.com/images/pentium-fdiv/fractal-w500.jpg" title="A fractal showing convergence or divergence of SRT division as the scale factor (X-axis) ranges from the normal value of 4 to infinity. The Y-axis is the starting partial remainder. The divisor is (arbitrarily) 1.5. Red indicates convergence; gray is darker as the value diverges faster." width="500" /></a><div class="cite">A fractal showing convergence or divergence of SRT division as the scale factor (X-axis) ranges from the normal value of 4 to infinity. The Y-axis is the starting partial remainder. The divisor is (arbitrarily) 1.5. Red indicates convergence; gray is darker as the value diverges faster.</div></p> <p><!-- --> <a class="footnote-backref" href="#fnref:chaos" title="Jump back to footnote 19 in the text">↩</a></p> </li> <li id="fn:bound"> <p>The algebra behind the bound of 8/3 is that <em>p</em> (the partial remainder) needs to be in an interval that stays the same size each step. Each step of division computes <em>p<sub>new</sub> = (p<sub>old</sub> - q*d)*4</em>. Thus, at the boundary, with <em>q=2</em>, you have <em>p = (p-2*d)*4</em>, so <em>3p=8d</em> and thus <em>p/d</em> = 8/3. Similarly, the other boundary, with <em>q=-2</em>, gives you <em>p/d</em> = -8/3. <a class="footnote-backref" href="#fnref:bound" title="Jump back to footnote 20 in the text">↩</a></p> </li> <li id="fn:8bit"> <p>I'm not completely happy with the 8-bit carry-lookahead adder. Coe's mathematical analysis in 1994 showed that the carry-lookahead adder operates on 7 bits. The adder in the Pentium has two 8-bit inputs connected to another part of the division circuit. However, the adder's bottom output bit is not connected to anything. That would suggest that the adder is adding 8 bits and then truncating to 7 bits, which would reduce the truncation error compared to a 7-bit adder. However, when I simulate the division algorithm this way, the FDIV bug doesn't occur. Wiring the bottom input bits to 0 would explain the behavior, but that seems pointless. I haven't examined the circuitry that feeds the adder, so I don't have a conclusive answer. <a class="footnote-backref" href="#fnref:8bit" title="Jump back to footnote 21 in the text">↩</a></p> </li> <li id="fn:testing"> <p>Half of the circuitry in the adder block is used to test the lookup table. The reason is that a chip such as the Pentium is very difficult to test: if one out of 3.1 million transistors goes bad, how do you detect it? For a simple processor like the 8080, you can run through the instruction set and be fairly confident that any problem would turn up. But with a complex chip, it is almost impossible to come up with an instruction sequence that would test every bit of the microcode ROM, every bit of the cache, and so forth. Starting with the 386, Intel added circuitry to the processor solely to make testing easier; about 2.7% of the transistors in the 386 were for testing.</p> <p>To test a ROM inside the processor, Intel added circuitry to scan the entire ROM and checksum its contents. Specifically, a pseudo-random number generator runs through each address, while another circuit computes a checksum of the ROM output, forming a "signature" word. At the end, if the signature word has the right value, the ROM is almost certainly correct. But if there is even a single bit error, the checksum will be wrong and the chip will be rejected. The pseudo-random numbers and the checksum are both implemented with linear feedback shift registers (LFSR), a shift register along with a few XOR gates to feed the output back to the input. For more information on testing circuitry in the 386, see <a href="https://doi.org/10.1109/MDT.1987.295165">Design and Test of the 80386</a>, written by Pat Gelsinger, who became Intel's CEO years later. Even with the test circuitry, 48% of the transistor sites in the 386 were untested. The instruction-level test suite to test the remaining circuitry took almost 800,000 clock cycles to run. The overhead of the test circuitry was about 10% more transistors in the blocks that were tested.</p> <p>In the Pentium, the circuitry to test the lookup table PLA is just below the 7-bit adder. An 11-bit LFSR creates the 11-bit input value to the lookup table. A 13-bit LFSR hashes the two-bit quotient result from the PLA, forming a 13-bit checksum. The checksum is fed serially to test circuitry elsewhere in the chip, where it is merged with other test data and written to a register. If the register is 0 at the end, all the tests pass. In particular, if the checksum is correct, you can be 99.99% sure that the lookup table is operating as expected. The ironic thing is that this test circuit was useless for the FDIV bug: it ensured that the lookup table held the intended values, but the intended values were wrong.</p> <p>Why did Intel generate test addresses with a pseudo-random sequence instead of a sequential counter? It turns out that a linear feedback shift register (LFSR) is slightly more compact than a counter. This LFSR trick was also used in a <a href="https://www.righto.com/2017/08/inside-fake-ram-chip-i-found-something.html">touch-tone chip</a> and the program counter of the Texas Instruments TMS 1000 microcontroller (1974). In the TMS 1000, the program counter steps through the program pseudo-randomly rather than sequentially. The program is shuffled appropriately in the ROM to counteract the sequence, so the program executes as expected and a few transistors are saved. <a class="footnote-backref" href="#fnref:testing" title="Jump back to footnote 22 in the text">↩</a></p> </li> <li id="fn:bicmos"> <p>One unusual feature of the Pentium is that it uses BiCMOS technology: both bipolar and CMOS transistors. Note the distinctive square boxes in the driver circuitry; these are bipolar transistors, part of the high-speed drivers.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/bipolar.jpg"><img alt="Three bipolar transistors. These transistors transmit the quotient to the rest of the division circuitry." class="hilite" height="269" src="https://static.righto.com/images/pentium-fdiv/bipolar-w350.jpg" title="Three bipolar transistors. These transistors transmit the quotient to the rest of the division circuitry." width="350" /></a><div class="cite">Three bipolar transistors. These transistors transmit the quotient to the rest of the division circuitry.</div></p> <p><!-- --> <a class="footnote-backref" href="#fnref:bicmos" title="Jump back to footnote 23 in the text">↩</a></p> </li> <li id="fn:64-bits"> <p>I think the partial remainder is actually 67 bits because there are three extra bits to handle rounding. Different parts of the floating-point datapath have different widths, depending on what width is needed at that point. <a class="footnote-backref" href="#fnref:64-bits" title="Jump back to footnote 24 in the text">↩</a></p> </li> <li id="fn:heatmaps"> <p>In this long footnote, I'll attempt to explain why the FDIV bug is so rare, using heatmaps. My analysis of Intel's lookup table shows several curious factors that almost cancel out, making failures rare but not impossible. (For a rigorous explanation, see <a href="https://doi.org/10.1109/ARITH.1995.465365">It Takes Six Ones to Reach a Flaw</a> and <a href="https://www.jstor.org/stable/2133004">The Mathematics of the Pentium Division Bug</a>. These papers explain that, among other factors, a bad divisor must have six consecutive ones in positions 5 through 10 and the division process must go through nine specific steps, making a bad result extremely uncommon.)</p> <p>The diagram below shows a heatmap of how often each table cell is accessed when simulating a generic SRT algorithm with a carry-save adder. The black lines show the boundaries of the quotient regions in the Pentium's lookup table. The key point is that the top colored cell in each column is above the black line, so some table cells are accessed but are not defined in the Pentium. This shows that the Pentium is missing 16 entries, not just the 5 entries that are usually discussed. (For this simulation, I generated the quotient digit directly from the SRT bounds, rather than the lookup table, selecting the digit randomly in the redundant regions.)</p> <p><a href="https://static.righto.com/images/pentium-fdiv/statsn-c-b-18.jpg"><img alt="A heatmap showing the table cells accessed by an SRT simulation." class="hilite" height="421" src="https://static.righto.com/images/pentium-fdiv/statsn-c-b-18-w350.jpg" title="A heatmap showing the table cells accessed by an SRT simulation." width="350" /></a><div class="cite">A heatmap showing the table cells accessed by an SRT simulation.</div></p> <p>The diagram is colored with a logarithmic color scale. The blue cells are accessed approximately uniformly. The green cells at the boundaries are accessed about 2 orders of magnitude less often. The yellow-green cells are accessed about 3 orders of magnitude less often. The point is that it is hard to get to the edge cells since you need to start in the right spot and get the right quotient digit, but it's not extraordinarily hard.</p> <p>(The diagram also shows an interesting but ultimately unimportant feature of the Pentium table: at the bottom of the diagram, five white cells are above the back line. This shows that the Pentium assigns values to five table cells that can't be accessed. (This was also mentioned in "The Mathematics of the Pentium Bug".) These cells are in the same columns as the 5 missing cells, so it would be interesting if they were related to the missing cells. But as far as I can tell, the extra cells are due to using a bound of "greater or equals" rather than "greater", unrelated to the missing cells. In any case, the extra cells are harmless.)</p> <p>The puzzling factor is that if the Pentium table has 16 missing table cells, and the SRT uses these cells fairly often, you'd expect maybe 1 division out of 1000 or so to be wrong. So why are division errors extremely rare?</p> <p>It turns out that the structure of the Pentium lookup table makes some table cells inaccessible. Specifically, the table is arbitrarily biased to pick the higher quotient digit rather than the lower quotient digit in the redundant regions. This has the effect of subtracting more from the partial remainder, pulling the partial remainder away from the table edges. The diagram below shows a simulation using the Pentium's lookup table and no carry-save adder. Notice that many cells inside the black lines are white, indicating that they are never accessed. This is by coincidence, due to arbitrary decisions when constructing in the lookup table. Importantly, the missing cells just above the black line are never accessed, so the missing cells shouldn't cause a bug.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/statsn-p-18.jpg"><img alt="A heatmap showing the table cells accessed by an SRT simulation using the Pentium's lookup table but no carry-save adder." class="hilite" height="422" src="https://static.righto.com/images/pentium-fdiv/statsn-p-18-w350.jpg" title="A heatmap showing the table cells accessed by an SRT simulation using the Pentium's lookup table but no carry-save adder." width="350" /></a><div class="cite">A heatmap showing the table cells accessed by an SRT simulation using the Pentium's lookup table but no carry-save adder.</div></p> <p>Thus, Intel almost got away with the missing table entries. Unfortunately, the carry-save adder makes it possible to reach some of the otherwise inaccessible cells. Because the output from the carry-save adder is truncated, the algorithm can access the table cell below the "right" cell. In the redundant regions, this can yield a different (but still valid) quotient digit, causing the next partial remainder to end up in a different cell than usual. The heatmap below shows the results.</p> <p><a href="https://static.righto.com/images/pentium-fdiv/statsn-c-p-merge.jpg"><img alt="A heatmap showing the probability of ending up in each table cell when using the Pentium's division algorithm." class="hilite" height="419" src="https://static.righto.com/images/pentium-fdiv/statsn-c-p-merge-w350.jpg" title="A heatmap showing the probability of ending up in each table cell when using the Pentium's division algorithm." width="350" /></a><div class="cite">A heatmap showing the probability of ending up in each table cell when using the Pentium's division algorithm.</div></p> <p>In particular, five cells above the black line can be reached: these are instances of the FDIV bug. These cells are orange, indicating that they are about 9 orders of magnitude less likely than the rest of the cells. It's almost impossible to reach these cells, requiring multiple "unlucky" values in a row from the carry-save adder. To summarize, the Pentium lookup table has 16 missing cells. Purely by coincidence, the choices in the lookup table make many cells inaccessible, which almost counteracts the problem. However, the carry-save adder provides a one-in-a-billion path to five of the missing cells, triggering the FDIV bug.</p> <p>One irony is that if division errors were more frequent, Intel would have caught the FDIV bug before shipping. But if division errors were substantially less frequent, no customers would have noticed the bug. Inconveniently, the frequency of errors fell into the intermediate zone: errors were too rare for Intel to spot them, but frequent enough for a single user to spot them. (This makes me wonder what other astronomically infrequent errors may be lurking in processors.) <a class="footnote-backref" href="#fnref:heatmaps" title="Jump back to footnote 25 in the text">↩</a></p> </li> <li id="fn:bounds"> <p><a href="https://link.springer.com/chapter/10.1007/3-540-59293-8_189">Anatomy of the Pentium Bug</a> reached a similar conclusion, stating "The [Intel] White Paper attributes the error to a script that incorrectly copied values; one is nevertheless tempted to wonder whether the rule for lowering thresholds was applied to the 8D/3 boundary, which would be an incorrect application because that boundary is serving to bound a threshold from below." (That paper also hypothesizes that the table was compressed to 6 columns, a hypothesis that my examination of the die disproves.) <a class="footnote-backref" href="#fnref:bounds" title="Jump back to footnote 26 in the text">↩</a></p> </li> <li id="fn:script"> <p>The Intel white paper describes the underlying cause of the bug: "After the quantized P-D plot (lookup table) was numerically generated as in Figure 4-1, a script was written to download the entries into a hardware PLA (Programmable Lookup Array). An error was made in this script that resulted in a few lookup entries (belonging to the positive plane of the P-D plot) being omitted from the PLA." The script explanation is repeated in <a href="https://web.archive.org/web/20060209005434/http://www.byte.com/art/9503/sec13/art1.htm">The Truth Behind the Pentium Bug</a>: "An engineer prepared the lookup table on a computer and wrote a script in C to download it into a PLA (programmable logic array) for inclusion in the Pentium's FPU. Unfortunately, due to an error in the script, five of the 1066 table entries were not downloaded. To compound this mistake, nobody checked the PLA to verify the table was copied correctly." My analysis suggests that the table was copied correctly; the problem was that the table was mathematically wrong. <a class="footnote-backref" href="#fnref:script" title="Jump back to footnote 27 in the text">↩</a></p> </li> <li id="fn:legends"> <p>It's not hard to find claims of people encountering the Pentium division bug, but these seem to be in the "urban legend" category. Either the problem is described second-hand, or the problem is unrelated to division, or the problem happened much too frequently to be the FDIV bug. It has been <a href="https://youtu.be/E2MIpi8pIvY?t=1511">said</a> that the game Quake would occasionally show the wrong part of a level due to the FDIV bug, but I find that implausible. <a href="https://archive.org/details/1995-01-01_W5YI_Report/page/n8/mode/1up">The "Intel Inside—Don't Divide" Chipwreck</a> describes how the division bug was blamed for everything from database and application server crashes to gibberish text. <a class="footnote-backref" href="#fnref:legends" title="Jump back to footnote 28 in the text">↩</a></p> </li> <li id="fn:ibm"> <p>IBM's analysis of the error rate seems contrived, coming up with reasons to use numbers that are likely to cause errors. In particular, IBM focuses on slightly truncated numbers, either numbers with two decimal digits or hardcoded constants. Note that a slightly truncated number is much more likely to hit a problem because its binary representation will have multiple 1's in a row, a necessity to trigger the bug. Another paper <a href="http://boole.stanford.edu/pentium.html">Risk Analysis of the Pentium Bug</a> claims a risk of one in every 200 divisions. It depends on "bruised integers", such as 4.999999, which are similarly contrived. I'll also point out that if you start with numbers that are "bruised" or otherwise corrupted, you obviously don't care about floating-point accuracy and shouldn't complain if the Pentium adds slightly more inaccuracy.</p> <p>The book "Inside Intel" says that "the IBM analysis was quite wrong" and "IBM's intervention in the Pentium affair was not an example of the company on its finest behavior" (page 364). <a class="footnote-backref" href="#fnref:ibm" title="Jump back to footnote 29 in the text">↩</a></p> </li> <li id="fn:f00f"> <p>The F00F bug happens when an invalid compare-and-exchange instruction leaves the bus locked. The instruction is supposed to exchange with a memory location, but the invalid instruction specifies a register instead causing unexpected behavior. This is very similar to some undocumented instructions in the 8086 processor where a register is specified when memory is required; see my article <a href="https://www.righto.com/2023/07/undocumented-8086-instructions.html">Undocumented 8086 instructions, explained by the microcode</a>. <a class="footnote-backref" href="#fnref:f00f" title="Jump back to footnote 30 in the text">↩</a></p> </li> <li id="fn:patchable"> <p>For details on the Pentium Pro's patchable microcode, see <a href="https://www.ele.uva.es/~jesman/BigSeti/ftp/Cajon_Desastre/MPR/111204.pdf">P6 Microcode Can Be Patched</a>. But patchable microcode dates back much earlier. The IBM System/360 mainframes (1964) had microcode that could be updated in the field, either to fix bugs or to implement new features. These systems stored microcode on metalized Mylar sheets that could be replaced as necessary. In that era, semiconductor ROMs didn't exist, so Mylar sheets were also a cost-effective way to implement read-only storage. See <a href="https://www.righto.com/2019/11/tros-how-ibm-mainframes-stored.html">TROS: How IBM mainframes stored microcode in transformers</a>. <a class="footnote-backref" href="#fnref:patchable" title="Jump back to footnote 31 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/639773237179033868' onclick=''> 14 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/639773237179033868' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=639773237179033868&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=639773237179033868&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=639773237179033868&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=639773237179033868&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=639773237179033868&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=639773237179033868&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://static.righto.com/images/pentium-antenna/diodes-w450.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='347521141499861916' itemprop='postId'/> <a name='347521141499861916'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html'>Antenna diodes in the Pentium processor</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-347521141499861916' itemprop='description articleBody'> <p>I was studying the silicon die of the Pentium processor and noticed some puzzling structures where signal lines were connected to the silicon substrate for no apparent reason. Two examples are in the photo below, where the metal wiring (orange) connects to small square regions of doped silicon (gray), isolated from the rest of the circuitry. I did some investigation and learned that these structures are "antenna diodes," special diodes that protect the circuitry from damage during manufacturing. In this blog post, I discuss the construction of the Pentium and explain how these antenna diodes work.</p> <p><a href="https://static.righto.com/images/pentium-antenna/diodes.jpg"><img alt="Closeup of the Pentium die showing the silicon and bottom metal layer. The arrows indicate connections to two antenna diodes. I removed the top two layers of metal for this photo." class="hilite" height="265" src="https://static.righto.com/images/pentium-antenna/diodes-w450.jpg" title="Closeup of the Pentium die showing the silicon and bottom metal layer. The arrows indicate connections to two antenna diodes. I removed the top two layers of metal for this photo." width="450" /></a><div class="cite">Closeup of the Pentium die showing the silicon and bottom metal layer. The arrows indicate connections to two antenna diodes. I removed the top two layers of metal for this photo.</div></p> <p>Intel released the Pentium processor in 1993, starting a long-running brand of high-performance processors: the Pentium Pro, Pentium II, and so on. In this post, I'm studying the original Pentium, which has 3.1 million transistors.<span id="fnref:versions"><a class="ref" href="#fn:versions">1</a></span> The die photo below shows the Pentium's fingernail-sized silicon die under a microscope. The chip has three layers of metal wiring on top of the silicon so the underlying silicon is almost entirely obscured.</p> <!-- The tiny white squares around the edges of the chip are bond pads. Bond wires attached to these pads provide the connections between the chip and its grid of 273 external pins. --> <p><a href="https://static.righto.com/images/pentium-antenna/pentium-labeled.jpg"><img alt="The Pentium die with the main functional blocks labeled. Click this photo (or any other) for a larger version." class="hilite" height="525" src="https://static.righto.com/images/pentium-antenna/pentium-labeled-w500.jpg" title="The Pentium die with the main functional blocks labeled. Click this photo (or any other) for a larger version." width="500" /></a><div class="cite">The Pentium die with the main functional blocks labeled. Click this photo (or any other) for a larger version.</div></p> <p>Modern processors are built from CMOS circuitry, which uses two types of transistors: NMOS and PMOS. The diagram below shows how an NMOS transistor is constructed. A transistor can be considered a switch between the source and drain, controlled by the gate. The source and drain regions (green) consist of silicon doped with impurities to change its semiconductor properties, forming N+ silicon. The gate consists of a layer of polysilicon (red), separated from the silicon by an absurdly thin insulating oxide layer. Since the oxide layer is just a few hundred atoms thick,<span id="fnref:gate"><a class="ref" href="#fn:gate">2</a></span> it is very fragile and easily damaged by excess voltage. (This is why CMOS chips are sensitive to static electricity.) As we will see, the oxide layer can also be damaged by voltage during manufacturing.</p> <p><a href="https://static.righto.com/images/pentium-antenna/mosfet-n.jpg"><img alt="Diagram showing the structure of an NMOS transistor." class="hilite" height="231" src="https://static.righto.com/images/pentium-antenna/mosfet-n-w400.jpg" title="Diagram showing the structure of an NMOS transistor." width="400" /></a><div class="cite">Diagram showing the structure of an NMOS transistor.</div></p> <p>The Pentium processor is constructed from multiple layers. Starting at the bottom, the Pentium has millions of transistors similar to the diagram above. Polysilicon wiring on top of the silicon not only forms the transistor gates but also provides short-range wiring. Above that, three layers of metal wiring connect the parts of the chip. Roughly speaking, the bottom layer of metal connects to the silicon and polysilicon to construct logic gates from the transistors, while the upper layers of wiring travel longer distances, with one layer for signals traveling horizontally and the other layer for signals traveling vertically. Tiny tungsten plugs called vias provide connections between the different layers of wiring. A key challenge of chip design is routing, directing signals through the multiple layers of wiring while packing the circuitry as densely as possible.</p> <p>The photo below shows a small region of the Pentium die with the three metal layers visible. The golden vertical lines are the top metal layer, formed from aluminum and copper. Underneath, you can see the horizontal wiring of the middle metal layer. The more complex wiring of the bottom metal layer can be seen, along with the silicon and polysilicon that form transistors. The small black dots are the tungsten vias that connect metal layers, while the larger dark circles are contacts with the underlying silicon or polysilicon. Near the bottom of the photo, the vertical gray bands are polysilicon lines, forming transistor gates. Although the chip appears flat, it has a three-dimensional structure with multiple layers of metal separated by insulating layers of silicon dioxide. This three-dimensional structure will be important in the discussion below. (The metal wiring is much denser over most of the chip; this region is one of the rare spots where all the layers are visible.)</p> <p><a href="https://static.righto.com/images/pentium-antenna/metal-layers.jpg"><img alt="Closeup of the Pentium die showing the metal layers. The L-shaped hook towards the lower left is a connection to an antenna diode. This photo shows a tiny part of the floating point unit. To show all the layers in focus, I combined multiple images with focus stacking." class="hilite" height="430" src="https://static.righto.com/images/pentium-antenna/metal-layers-w400.jpg" title="Closeup of the Pentium die showing the metal layers. The L-shaped hook towards the lower left is a connection to an antenna diode. This photo shows a tiny part of the floating point unit. To show all the layers in focus, I combined multiple images with focus stacking." width="400" /></a><div class="cite">Closeup of the Pentium die showing the metal layers. The L-shaped hook towards the lower left is a connection to an antenna diode. This photo shows a tiny part of the floating point unit. To show all the layers in focus, I combined multiple images with focus stacking.</div></p> <p>The manufacturing process for an integrated circuit is extraordinarily complicated but I'll skip over most of the details and focus on how each metal layer is constructed, layer by layer. First, a uniform metal layer is constructed over the silicon wafer. Next, the desired pattern is produced on the surface using a process called photolithography: a light-sensitive chemical called "resist" is applied to the wafer and exposed to light through a patterned mask. The light hardens the resist, creating a protective coating with the pattern of the desired wiring. Finally, the unprotected metal is etched away, leaving the wiring.</p> <p>In the early days of integrated circuits, the metal was removed with liquid acids, a process called wet etching. Inconveniently, wet etching tended to eat away metal underneath the edges of the mask, which became a problem as integrated circuits became denser and the wires needed to be thinner. The solution was dry etch, using a plasma to remove the metal. By applying a large voltage to plates above and below the chip, a gas such as HCl is ionized into a highly reactive plasma. This plasma attacks the surface (unless it is protected by the resist), removing the unwanted metal. The advantage of dry etching is that it can act vertically (anisotropically), providing more control over the line width.</p> <p>Although plasma etching improved the etching process, it caused another problem: plasma-induced oxide damage, also called (metaphorically) the "antenna effect."<span id="fnref:antenna"><a class="ref" href="#fn:antenna">3</a></span> The problem is that long metal wires on the chip could pick up an electrical charge from the plasma, producing a large voltage. As described earlier, the thin oxide layer under a transistor's gate is sensitive to voltage damage. The voltage induced by the plasma can destroy the transistor by blowing a hole through the gate oxide or it can degrade the transistor's performance by embedding charges inside the oxide layer.<span id="fnref:damage"><a class="ref" href="#fn:damage">4</a></span></p> <p>Several factors affect the risk of damage from the antenna effect. First, only the transistor's gate is sensitive to the induced voltage, due to the oxide layer. If the wire is also connected to a transistor's source or drain, the wire is "safe" since the source and drain provide connections to the chip's substrate, allowing the charge to dissipate harmlessly. Note that when the chip is completed, every transistor gate is connected to another transistor's source or drain (which provides the signal to the gate), so there is no risk of damage. Thus, the problem can only occur during manufacturing, with a metal line that is connected to a gate on one end but isn't connected on the other end. Moreover, the highest layer of metal is "safe" since everything is connected at that point. Another factor is that the induced voltage is proportional to the length of the metal wire, so short wires don't pose a risk. Finally, only the metal layer currently being etched poses a risk; since the lower layers are insulated by the thick oxide between layers, they won't pick up charge.</p> <p>These factors motivate several ways to prevent antenna problems.<span id="fnref:papers"><a class="ref" href="#fn:papers">5</a></span> First, a long wire can be broken into shorter segments, connected by jumpers on a higher layer. Second, moving long wires to the top metal layer eliminates problems.<span id="fnref:top-metal"><a class="ref" href="#fn:top-metal">6</a></span> Third, diodes can be added to drain the charge from the wire; these are called "antenna diodes". When the chip is in use, the antenna diodes are reverse-biased so they have no electrical effect. But during manufacturing, the antenna diodes let charge flow to the substrate before it causes problems.</p> <p>The third solution, the antenna diodes, explains the mysterious connections that I saw in the Pentium. In the diagram below, these diodes are visible on the die as square regions of doped silicon. The larger regions of doped silicon form PMOS transistors (upper) and NMOS transistors (lower). The polysilicon lines are faintly visible; they form transistor gates where they cross the doped silicon. (For this photo, I removed all the metal wiring.)</p> <p><a href="https://static.righto.com/images/pentium-antenna/silicon-diagram.jpg"><img alt="Closeup of the Pentium die showing transistors. The metal and polysilicon layers have been removed to show the silicon." class="hilite" height="574" src="https://static.righto.com/images/pentium-antenna/silicon-diagram-w450.jpg" title="Closeup of the Pentium die showing transistors. The metal and polysilicon layers have been removed to show the silicon." width="450" /></a><div class="cite">Closeup of the Pentium die showing transistors. The metal and polysilicon layers have been removed to show the silicon.</div></p> <p>Confusingly, the antenna diodes look almost identical to "well taps", connections from the substrate to the chip's positive voltage supply, but have a completely different purpose. In the Pentium, the PMOS transistors are constructed in "wells" of N-type silicon. These wells must be raised to the chip's positive voltage, so there are numerous well tap connections from the positive supply to the wells. The well taps consist of squares of N+ doped silicon in the the N-type silicon well, providing an electrical connection. On the other hand, the antenna diodes also consist of N+ doped silicon, but embedded in P-type silicon. This forms a P-N junction that creates the diode.</p> <p>In the Pentium, antenna diodes are used for only a small fraction of the wiring. The diodes require extra area on the die, so they are used only when necessary. Most of the antenna problems on the Pentium were apparently resolved through routing. Although the antenna diodes are relatively rare, they are still frequent enough that they caught my attention.</p> <p>Antenna effects are still an issue in modern integrated circuits. Integrated circuit fabricators provide rules on the maximum allowable size of antenna wires for a particular manufacturing process.<span id="fnref:rules"><a class="ref" href="#fn:rules">7</a></span> Software checks the design to ensure that the antenna rules are not violated, modifying the routing and inserting diodes as necessary. Violating the antenna rules can result in damaged chips and a very low yield, so it's more than just a theoretical issue.</p> <p>Thanks to <a href="https://www.reddit.com/r/chipdesign/comments/1gwkm65/pentium_why_are_signal_lines_connected_to_the/">/r/chipdesign</a> and Discord for discussion. If you're interested in the Pentium, I've written about <a href="https://www.righto.com/2024/07/pentium-standard-cells.html">standard cells</a> in the Pentium, and the Pentium as a <a href="https://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html">Navajo rug</a>. Follow me on Mastodon (<a href="https://oldbytes.space/@kenshirriff">@<span class="__cf_email__" data-cfemail="d4bfb1baa7bcbda6a6bdb2b294bbb8b0b6ada0b1a7faa7a4b5b7b1">[email protected]</span></a>) or Bluesky (<a href="https://bsky.app/profile/righto.com">@righto.com</a>) or <a href="http://www.righto.com/feeds/posts/default">RSS</a> for updates.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:versions"> <p>In this post, I'm looking at the Pentium model 80501 (codenamed P5). This model was soon replaced with a faster, lower-power version called the 80502 (P54C). Both are considered original Pentiums. <a class="footnote-backref" href="#fnref:versions" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:gate"> <p><a href="https://www.ardent-tool.com/CPU/docs/MPR/19930531/070705.pdf">IC manufacturing drives CPU performance</a> states that gate oxide thickness was 100 to 300 angstroms in 1993. <a class="footnote-backref" href="#fnref:gate" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:antenna"> <p>The wires are acting metaphorically as antennas, not literally, as they collect charge, not picking up radio waves.</p> <p>Plasma-induced oxide damage gave rise to research and conferences in the 1990s to address this problem. The <a href="https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=715190">International Symposium on Plasma- and Process-Induced Damage</a> started in 1996 and continued until 2003. Numerous researchers from semiconductor companies and academia studied the causes and effects of plasma damage. <a class="footnote-backref" href="#fnref:antenna" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:damage"> <p>The damage is caused by "Fowler-Nordheim tunneling", where electrons tunnel through the oxide and cause damage. Flash memory uses this tunneling to erase the memory; the cumulative damage is why flash memory can only be written a limited number of times. <a class="footnote-backref" href="#fnref:damage" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:papers"> <p>Some relevant papers: <a href="https://doi.org/10.1116/1.585577">Magnetron etching of polysilicon: Electrical damage</a> (1991), <a href="https://doi.org/10.1109/55.145056">Thin-oxide damage from gate charging during plasma processing</a> (1992), <a href="https://doi.org/10.1109/RELPHY.1998.670660">Antenna protection strategy for ultra-thin gate MOSFETs</a> (1998), <a href="https://doi.org/10.1109/ISQED.2000.838883">Fixing antenna problem by dynamic diode dropping and jumper insertion</a> (2000). The Pentium uses the "dynamic diode dropping" approach, adding antenna diodes only as needed, rather than putting them in every circuit. I noticed that the Pentium uses extension wires to put the diode in a more distant site if there is no room for the diode under the existing wiring. As an aside, the third paper uses the curious length unit of k碌m; by calling 1000 碌m a k碌m, you can think in micrometers, even though this unit is normally called a mm. <a class="footnote-backref" href="#fnref:papers" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:top-metal"> <p>Sources say that routing signals on the top metal prevents antenna violations. However, I see several antenna diodes in the Pentium that are connected directly from the bottom metal (M1) through M2 to long lines on M3. These diodes seem redundant since the source/drain connections are in place by that time. So there are still a few mysteries... <a class="footnote-backref" href="#fnref:top-metal" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:rules"> <p>Foundries have antenna rules provided as part of the Process Design Kit (PDK). Here are the rules for <a href="https://www.southampton.ac.uk/~bim/notes/ice/DesignRules/guidelines.html">MOSIS</a> and <a href="https://skywater-pdk.readthedocs.io/en/main/rules/antenna.html">SkyWater</a>. I've focused on antenna effects from the metal wiring, but polysilicon and vias can also cause antenna damage. Thus, there are rules for these layers too. Polysilicon wiring is less likely to cause antenna problems, though, as it is usually restricted to short distances due to its higher resistance. <a class="footnote-backref" href="#fnref:rules" title="Jump back to footnote 7 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/347521141499861916' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/347521141499861916' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=347521141499861916&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=347521141499861916&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=347521141499861916&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=347521141499861916&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=347521141499861916&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=347521141499861916&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/electronics' rel='tag'>electronics</a>, <a href='http://www.righto.com/search/label/Pentium' rel='tag'>Pentium</a>, <a href='http://www.righto.com/search/label/reverse-engineering' rel='tag'>reverse-engineering</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='http://www.righto.com/search?updated-max=2025-03-31T10:14:00-07:00&max-results=7&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='http://www.righto.com/search?updated-max=2024-11-23T11:59:00-08:00&max-results=7' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='http://www.righto.com/'>Home</a> </div> <div class='clear'></div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget HTML' data-version='1' id='HTML2'> <div class='widget-content'> <style> @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,500,700'); .form-preview { display: flex; flex-direction: column; justify-content: center; margin-top: 30px; padding: clamp(17px, 5%, 40px) clamp(17px, 7%, 50px); max-width: 350px; min-height: 200px; border-radius: 6px; box-shadow: 0 5px 25px rgba(34, 60, 47, 0.25); } .form-preview, .form-preview *{ box-sizing: border-box; } .form-preview .preview-heading { width: 100%; } .form-preview .preview-heading h5{ margin-top: 0; margin-bottom: 0; } .form-preview .preview-input-field { margin-top: 20px; width: 100%; } .form-preview .preview-input-field input { width: 100%; height: 40px; border-radius: 6px; border: 2px solid #e9e8e8; background-color: #fff; outline: none; } .form-preview .preview-input-field input::placeholder, .form-preview .preview-input-field input { opacity: 0.5; color: #000; font-family: "Montserrat"; font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; } .form-preview .preview-submit-button { margin-top: 10px; width: 100%; } .form-preview .preview-submit-button button { width: 100%; height: 40px; border: 0; border-radius: 6px; line-height: 0px; } .form-preview .preview-submit-button button:hover { cursor: pointer; } </style><form data-v-4c58e686="" action="https://api.follow.it/subscription-form/U3NBTmZKVkI1YVpCa000a0RCZHFiQ3FYMko1cWRTZTN6K3hJdWM2QWxJbE1uVXdXUHZZVzJVQzVLZGh5Y0RCVXB2d2JSTzBobGhuY0FsZnlHbVdFZ2VTN2Q4Vy84RnIxUTgzVlcrbXNIR0Y0aW93d3REM2J6VS9RL0gxWURnV1d8ZWN0YStwUWdWWUFiOTIyWDVGWjdYYVdGZEVNcC9qODZacjlwWXRIcEJQRT0=/8" method="post"><div data-v-4c58e686="" class="form-preview" style="background-color: rgb(255, 255, 255); border-style: solid; border-width: 1px; border-color: rgb(204, 204, 204); position: relative;"><div data-v-4c58e686="" class="preview-heading"><h5 data-v-4c58e686="" style="font-family: Montserrat; font-weight: bold; color: rgb(0, 0, 0); font-size: 12px; text-align: center;">Get new posts by email:</h5></div> <div data-v-4c58e686="" class="preview-input-field"><input data-v-4c58e686="" type="email" name="email" placeholder="Enter your email" spellcheck="false" /></div> <div data-v-4c58e686="" class="preview-submit-button"><button data-v-4c58e686="" type="submit" style="font-family: Montserrat; font-weight: bold; color: rgb(255, 255, 255); font-size: 12px; text-align: center; background-color: rgb(0, 0, 0);">Subscribe</button></div></div></form> </div> <div class='clear'></div> </div><div class='widget HTML' data-version='1' id='HTML3'> <h2 class='title'>About the site</h2> <div class='widget-content'> <a href="https://www.righto.com/p/index.html">Contact info and site index</a> </div> <div class='clear'></div> </div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'> <h2>Popular Posts</h2> <div class='widget-content popular-posts'> <ul> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uqJ07e2-TvsjYcCzO51ShqwFEVH1F8kue18aGqIk6yV7h4KV2AHZTD7Kd08MCjRF2Fa6YrAiKGpin1RhcmeNGbJXyH7OpbX2-RcsEsFVNEypLfai2j9Groapjd0PSxVWE=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html'>A USB interface to the "Mother of All Demos" keyset</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tdLaoBj6EMLkA7UqvPqZqEPeM-lHKFxRptyvErjPYXluz6YJYYRLEempbh4cyBsR_b-xW0Ibn7ozA9qAT-BdI9PvArfjFzE0qV5uHOQ_Tsyk7tcTQSGFHS_-W5qKLR5jIa4lHqExnlzyD9MJJGYNo=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html'>Notes on the Pentium's microcode circuitry</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/05/blog-post.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uetGew2cchk_VRNcKK1oDJTxcFR28_2bwhacTJpPoE9AneJSVXCDIZ5vbGBI7N9ZAxFxML99WJj3JczkyW9o-v9SZGYkzK9N1rpel9dbLO6JCanPN4EFVEI6P5UhOagI-ZBdwhKQGBexA9OpgxEWq2=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/05/blog-post.html'>Inside a vintage aerospace navigation computer of uncertain purpose</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_udYAi7gaqmK6eA5uEJ9hvDdaJEz6pREV1a-yV9T__LObjWx21exQFSOPKsjvMHmphhjCblZhn0a65vQq6lSvQ2e-Ou_EZw5io9YJdTuUsk53WhP2bW5Us4Moqm6BKNTSPa3ClRmLknzfbP=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html'>The Pentium contains a complicated circuit to multiply by three</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sIp1KNtFmprkFaOClQN_fu8YkIcyhwgBu1xpY8r415IyO5yFRrTmXQmG3-fFfYVZMABs-07gaVfN6lLM2xCLNdDndSORCPr0rToEiz8JUI-U8=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html'>A Multi-Protocol Infrared Remote Library for the Arduino</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sxuS-8FzzrUWAHM9RJ3KXKHRwliF7aJm1MMX4i4riP1xCdbg6yLBgOcN2T17ZlApbUKcW920Gtv2I54UY260LwO8XL07ZNiIi0h3By6CwCo511S7wd7SzfGuV9LEA=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html'>A dozen USB chargers in the lab: Apple is very good, but not quite the best</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t5xhNokjxClND0xO0Liae6zt5Vvs1nL2kFr48kr4GQBflnZ4iHai1kPpZ4nXBbiMEkHMYXkMB3lqqCMmYcCPZsU_XJ4CYBLVlUrGeSv7Y__4PF8kKuJMheYFjItHQJAgMd96zkUTEF9Jtu7ikSG2Gmu1E=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html'>Apple iPhone charger teardown: quality in a tiny expensive package</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t3FZAm-326FhRITzwJ9Zb_t_l7nx88NqVACqd3RZqKs7bzN2wxSulO3skbH7IminBNRUwz7VXe-HriqWw674ol5hs6sN1EvDitD1EmYIKLojZDueDlFZ5HgclrWeyiuYnU=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html'>Mining Bitcoin with pencil and paper: 0.67 hashes per day</a></div> </div> <div style='clear: both;'></div> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='http://www.righto.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget Label' data-version='1' id='Label1'> <h2>Labels</h2> <div class='widget-content cloud-label-widget-content'> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/386'>386</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/6502'>6502</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8008'>8008</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/8085'>8085</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/8086'>8086</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8087'>8087</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8088'>8088</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/aerospace'>aerospace</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/alto'>alto</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/analog'>analog</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Apollo'>Apollo</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/apple'>apple</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/arc'>arc</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arduino'>arduino</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arm'>arm</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/beaglebone'>beaglebone</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/bitcoin'>bitcoin</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/c%23'>c#</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/cadc'>cadc</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/calculator'>calculator</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/chips'>chips</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/css'>css</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/datapoint'>datapoint</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/dx7'>dx7</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/electronics'>electronics</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/f%23'>f#</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/fairchild'>fairchild</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fpga'>fpga</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fractals'>fractals</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/genome'>genome</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/globus'>globus</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/haskell'>haskell</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/HP'>HP</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/html5'>html5</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm'>ibm</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm1401'>ibm1401</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ibm360'>ibm360</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/intel'>intel</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ipv6'>ipv6</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ir'>ir</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/java'>java</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/javascript'>javascript</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/math'>math</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/microcode'>microcode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/oscilloscope'>oscilloscope</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Pentium'>Pentium</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/photo'>photo</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/power%20supply'>power supply</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/random'>random</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/reverse-engineering'>reverse-engineering</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/sheevaplug'>sheevaplug</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/snark'>snark</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/space'>space</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/spanish'>spanish</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/synth'>synth</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/teardown'>teardown</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/theory'>theory</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/unicode'>unicode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/Z-80'>Z-80</a> </span> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Blog Archive</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/'> 2025 </a> <span class='post-count' dir='ltr'>(8)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li><a href='http://www.righto.com/2024/12/this-die-photo-of-pentium-shows.html'>Intel's $475 million error: the silicon behind the...</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li><a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html'>Antenna diodes in the Pentium processor</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(35)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(26)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/08/'> August </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/05/'> May </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/03/'> March </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/12/'> December </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(34)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/10/'> October </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/06/'> June </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(13)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/'> 2013 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/'> 2012 </a> <span class='post-count' dir='ltr'>(10)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/11/'> November </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/08/'> August </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/03/'> March </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/02/'> February </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/2806328968-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY6DdQJDclGxCXowRPFmmPCGvxsXOg:1744051536204';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d6264947694886887540','//www.righto.com/2024/','6264947694886887540'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '6264947694886887540', 'title': 'Ken Shirriff\x27s blog', 'url': 'http://www.righto.com/2024/', 'canonicalUrl': 'http://www.righto.com/2024/', 'homepageUrl': 'http://www.righto.com/', 'searchUrl': 'http://www.righto.com/search', 'canonicalHomepageUrl': 'http://www.righto.com/', 'blogspotFaviconUrl': 'http://www.righto.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': false, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-3782444-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22http://www.righto.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - RSS\x22 href\x3d\x22http://www.righto.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/6264947694886887540/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/51ad58472e92bd27', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': '2024', 'pageTitle': 'Ken Shirriff\x27s blog: 2024'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Ken Shirriff\x27s blog', 'description': 'Computer history, restoring vintage computers, IC reverse engineering, and whatever', 'url': 'http://www.righto.com/2024/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2024, 'rangeMessage': 'Showing posts from 2024'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar-right-1', document.getElementById('HTML2'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML3', 'sidebar-right-1', document.getElementById('HTML3'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-right-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar-right-1', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>