<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://pakkachan.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://pakkachan.github.io/" rel="alternate" type="text/html" /><updated>2026-09-02T13:13:36+00:00</updated><id>https://pakkachan.github.io/feed.xml</id><title type="html">Aaron Shi</title><subtitle>FPGA and low-latency systems</subtitle><entry><title type="html">Solving Jane Street’s “Can you reverse engineer an ASIC” puzzle</title><link href="https://pakkachan.github.io/asic/" rel="alternate" type="text/html" title="Solving Jane Street’s “Can you reverse engineer an ASIC” puzzle" /><published>2026-08-14T00:00:00+00:00</published><updated>2026-08-14T00:00:00+00:00</updated><id>https://pakkachan.github.io/reverse-engineering-an-asic</id><content type="html" xml:base="https://pakkachan.github.io/asic/"><![CDATA[<p><em>A note on AI: the reverse engineering, analysis and decisions are mine. I used AI to write/ check code and to help with visualisation scripts, not to solve the puzzle.</em></p>

<h2 id="contents">Contents</h2>

<p><a href="#introduction">Introduction</a></p>

<p><a href="#warmup">Warmup</a></p>

<p><a href="#puzzle">Puzzle</a></p>
<ul>
  <li><a href="#setting-up-and-initial-attempts">Setting up and initial attempts</a></li>
  <li><a href="#reading-the-hints">Reading the hints</a></li>
  <li><a href="#diving-deeper-into-the-cones">Diving deeper into the cones</a></li>
  <li><a href="#the-two-format-latches">The two format latches</a></li>
  <li><a href="#further-structural-exploration">Further structural exploration</a></li>
  <li><a href="#looking-inside-the-chip">Looking inside the chip</a></li>
  <li><a href="#the-impulse-sweep">The impulse sweep</a></li>
  <li><a href="#a-stroke-of-luck">A stroke of luck</a></li>
  <li><a href="#what-the-puzzle-actually-is">What the puzzle actually is</a></li>
</ul>

<p><a href="#easter-eggs">Easter eggs</a></p>

<h2 id="introduction">Introduction</h2>

<p>Hi there. I’m Aaron. Originally from NZ, I moved to Australia to study a Bachelor of Electrical Engineering at USYD (Graduating mid 2028). I’m interested in FPGAs and anything computing really so this puzzle really caught my eye.</p>

<p>Jane Street’s 2026 puzzle, “Can you reverse engineer an ASIC?”, is literally what the title says. They hand you the final mask of a chip. That is every metal, routing and transistor layer, plus a few sample test inputs and outputs. Our job is to reverse engineer it. The task breaks into three steps. Firstly, recover the netlist from the raw layout. Secondly, work out what the circuit actually does. Lastly, drive it with the right input so it outputs the answer string, which is what you submit.</p>

<h2 id="warmup">Warmup</h2>

<p>I started by doing the warmup, building the tools and getting familiarised with
the various formats (GDS, LEF, DEF). I then pulled the sky130 PDK, built
and instantiated the Verilog equivalent. I chose to use cocotb with verification since I’m the most familiar with it. Finally, I verified the warmup not only on the correct addition output,
but also wrote a testbench to confirm it does not assert correct in any of the
wrong cases.</p>

<h2 id="puzzle">Puzzle</h2>

<h3 id="setting-up-and-initial-attempts">Setting up and initial attempts</h3>

<p>I took the puzzle GDS and ran it through the same pipeline into Verilog, then wrote checkers to confirm the netlist was connected properly. Along the way I found the anomaly of one unconnected cell. Additionally, looking at the provided VCD inputs in GTKWave, the input is a 121 bit stream on <code class="language-plaintext highlighter-rouge">I</code>, sampled on each rising clock edge while <code class="language-plaintext highlighter-rouge">enable</code> is high. The output comes back on <code class="language-plaintext highlighter-rouge">O[7:0]</code>, 8 bits per cycle. This can be viewed as one ASCII character at a time since an invalid attempt streams “TRY AGAIN” on <code class="language-plaintext highlighter-rouge">O[7:0]</code> and never asserts success. The chip also streams other messages for different inputs, which I cover my findings in the <a href="#other-messages-the-machine-streams">easter eggs section</a>.</p>

<p>After extraction I could see the chip itself (with the help from AI for some visualisations). I first split the die into its registers and its combinational logic to see the overall anatomy of the chip. The ports are traced through the metal layers, so the inputs come in on the left and the outputs leave on the right. Visualisations helped me a lot here and were the ultimate
key to my success, so expect many diagrams (pls zoom in if words are too small).</p>

<p><img src="images/11_celltypes.png?v=1788354816" alt="the chip cells and traced ports" /></p>

<p>From investigating the sample input (covered in the <a href="#the-night-sky-awaits">easter eggs section below</a>), I first thought the puzzle was simply a word checker where each character was an 11 bit word: 7 ASCII bits with 4 bits of zero padding. Therefore, I came up with a few 11 letter words that fit the theme of some of my initially discovered easter eggs and AI helped me extend the list.</p>

<p>Some examples are:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SAGITTARIUS
ORIONS BELT
NIGHT SKIES
STARS ABOVE
JANE STREET
MILKY WAY
</code></pre></div></div>

<p>Words were also tried with various capitalisations and spacings.</p>

<p>I encoded each as ASCII with the same padding and sent them through a cocotb testbench into the reconstructed chip. However, that did not bear any fruit. Afterwards I tried different words, capitalisations and casings but success was never asserted and the chip said “TRY AGAIN” for all of them.</p>

<h3 id="reading-the-hints">Reading the hints</h3>

<p>Following these blind attempts, I went back to the article posting to gain some sense of direction. The blog said that <em>“The circuit is physically arranged to hint at its functionality,
so look closely at the layout”</em> and that <em>“There is one section of the design that is
used to generate the output but does not affect the [success] output. You can
safely ignore it.”</em> Therefore, I first traced which cells the input actually touches on
the way to success, i.e. the fan-in cone. I also wanted to trace a subset of the fan-in cone, the cells that reach the
success flop within a single clock cycle, which I call the success cone. The
success flop is <code class="language-plaintext highlighter-rouge">X228</code>. We first have the entire die after extraction:</p>

<p><img src="images/1_anatomy.png?v=1788354816" alt="the die after extraction" /></p>

<p>Where the output generator can be ignored. Hence catagorising the fan in cone along with the success cone:</p>

<p><img src="images/2_cones.png?v=1788354816" alt="fan in cone and success cone" /></p>

<p>And we can get some characteristics of both cones:</p>
<ul>
  <li><strong>Fan-in cone.</strong> Of the 728 logic cells, 484 can reach <code class="language-plaintext highlighter-rouge">success</code> and 244 cannot.
The 244 are the output generator the blog told me to ignore.</li>
  <li><strong>Success cone.</strong> Walking back from <code class="language-plaintext highlighter-rouge">X228</code> and stopping at flop boundaries gives
47 combinational cells over 57 stored bits. So the pass condition is a one cycle
function of 57 flops, an end of stream comparison.</li>
</ul>

<h3 id="diving-deeper-into-the-cones">Diving deeper into the cones</h3>

<p>Analysing the success cone, it is nearly all AND logic feeding one gate in front
of the success flop. That makes it invertible by hand: an AND forced to 1 pins
every input to 1, a NOR forced to 1 pins every input to 0, and an inverter just
flips the requirement through. No gate in this cone is ever asked for the value
that leaves a choice, so I could push <code class="language-plaintext highlighter-rouge">success = 1</code> backwards through all 47 gates
and every input came out uniquely determined.</p>

<p>Thereby I wrote a program that created <code class="language-plaintext highlighter-rouge">required_state.json</code>: the exact value each of the 56 flops within the success cone must hold for success to subsequently assert high. The required state here is a goal we can approach, but not the answer to the puzzle.</p>

<p><a id="required-state"></a>
<img src="images/9_required_state.png?v=1788354816" alt="the 56 flop required state" /></p>

<h3 id="looking-inside-the-chip">Looking inside the chip</h3>

<p>At this point, I needed a tool to help me iterate and visualise multiple ideas quickly. Therfore, with the great help of AI tooling, I quickly built an interactive viewer where I hand it an 11 by 11 grid of 0s and
1s and it streams those 121 bits into the extracted netlist using a cocotb testbench.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># grid.txt: 11 rows, each an 11-bit frame, the left bit is shifted in first
10000000000
01000000000
00100000000
00010000000
00001000000
00000100000
00000010000
00000001000
00000000100
00000000010
00000000001

# in puzzle/interactive:
make          # stream the grid in and print the output ASCII
make image    # also draw which cells lit up, to temp.png
</code></pre></div></div>

<p>It prints the ASCII the chip streams back on <code class="language-plaintext highlighter-rouge">O[7:0]</code> and outputs an image of which cells/ registers were touched, gradient colour coded by when they were first touched by the signal. As an example, streaming in a full grid of ones lights up almost every cell (and gives us a different output):</p>

<p><img src="images/12_interactive_example.png?v=1788354816" alt="an interactive run of a full grid of ones, cells coloured by the cycle they first went high" /></p>

<p>This turned many random ideas into a one command experiment where I could physically see which sections of the enigmatic chip activated and when.</p>

<h3 id="the-two-format-latches">The two format latches</h3>

<p>From earlier easter egg investigation, I already knew the input arrives as a stream of 121 bits, which can be interpreted as 11 frames of 11 bits. Feeding frames of different weights and watching the whole chip, register
<code class="language-plaintext highlighter-rouge">X5638</code> stayed low only when a frame held exactly two 1s. Any other count latched
it high and it stuck. Testing all 55 weight 2 symbols in all 11 positions, every
one passed and every other weight failed. So <code class="language-plaintext highlighter-rouge">X5638</code> can be interpreted as a sticky “bad weight”
flag.</p>

<p>During a wider hunt on valid inputs, <code class="language-plaintext highlighter-rouge">X5337</code> showed up. It latched whenever two 1s
sat next to each other in a frame. At the time I read this as a simple no horizontally adjacent
bits rule, only later realising it sat behind a 12 stage shift register which is discussed later on.</p>

<p><img src="images/3_latches.png?v=1788354816" alt="the two format latches and their circuits" /></p>

<p>Comparing back to required_state.json, both latches are in the required state and must be off for success, which thereby gives us the first two constraints:
exactly weight 2 per frame, and no two bits adjacent. I initially thought of brute forcing the input space however, the space is far too
large to brute force. Weight 2 gives 55 symbols per frame, and dropping the 10
side by side symbols leaves 45:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>45^11  =  about 1.5 x 10^18 streams
</code></pre></div></div>

<p>At around 0.4 seconds per attempt on my machine that is roughly 19 billion years.
Brute force was never on the table. Therefore I kept reading into the structure,
since I still did not truly understand the chip, only some rules on its input.</p>

<h3 id="further-structural-exploration">Further structural exploration</h3>

<p>Hence I dove deeper into the layout. Firstly, I chose to look into the two large vertical banks that share the same
narrow strip of x = ~125 (um), one above the other: Bank A up top and Bank D below. I named
them from some previous labelled regions (regions A, B, C, D and so on) of an earlier layout
sketch on paper and the names stuck.</p>

<p><img src="images/4_banks.png?v=1788354816" alt="Bank A and Bank D" /></p>

<p>From my setup, I had two things to work with. One was a list of every cell with its position on the die. The other was the extracted netlist, the graph of what drives what.</p>

<p>From there I noticed the flops in these banks were part of the required state, so I took their names and inspected their connectivity. I went to them and walked back through the netlist to see what each one reads. They fell into pairs. Each flop read only itself, its partner and one shared block of 9 flops that every pair also read. That gave 22 clean pairs, which split evenly into two banks of eleven, Bank A and Bank D. The banks did not read the shared block equally. Bank A flops attached to only 5 of the 9, while Bank D flops attached to all 9.</p>

<p><img src="images/10_banks_and_counters.png?v=1788354816" alt="the two banks and the shared counter" /></p>

<p>I then looked at what that shared block was. Its nine flops never saw the input and read only each other. Eight of them are part of some sort of counter and the ninth is an evaluation/ enable window flag, connected to the counter and enable and going high near the end. That flag flop is the only one of the nine in the required state, since the final compare lands on the window it marks. The counter itself is two 4bit fields. One is a column count that cycles every frame, the other a row count that ticks once per frame. That explains the 5 / 9 split. Bank A only needs the column, so it reads the column field plus the flag. Bank D needs the full position, so it reads both fields and the flag. Overall:</p>

<ul>
  <li>
    <p><strong>Bank A</strong>, 11 pairs. Small update logic, lightly gated by the counter, sitting close to the input. This felt like staging.</p>
  </li>
  <li>
    <p><strong>Bank D</strong>, 11 pairs. Much heavier logic, fully driven by the counter. Its update logic is the large combinational block in the bottom right corner, set apart from the flops it drives. This was clearly where the real work happened, though I could not yet understand it.</p>
  </li>
</ul>

<p>One result that shaped my thinking: there is not a single adder anywhere in
the design. Combined with the input arriving one bit at a time, that ruled out the chip doing any arithmetic on it. That likely rules out anything cryptographic too.</p>

<p>A few other structures I discovered and investigated:</p>

<ul>
  <li><strong>Large combinational block in the bottom right.</strong> Bank D’s update logic, sitting apart from
the flops it drives.</li>
  <li><strong>Weight counter.</strong> The two flops behind <code class="language-plaintext highlighter-rouge">X5638</code>, doing the per frame count.</li>
  <li><strong>Adjacency chain.</strong> <code class="language-plaintext highlighter-rouge">X5337</code> behind a 12 stage shift register, comparing the
current bit only against delays 1, 10, 11 and 12. Laid out as an 11 by 11 grid
those are exactly the four already seen neighbours: left, up, upper left and
upper right. The other four are checked when they take their turn. So the real
rule is no two 1s touching anywhere on the grid, diagonals included. This is
where I stopped seeing a stream and started seeing a grid.</li>
  <li><strong>Global count.</strong> A ripple counter whose value is just the total number of 1s in
the whole input.</li>
</ul>

<h3 id="the-impulse-sweep">The impulse sweep</h3>

<p>This was the move that helped me crack the puzzle. Inspired by my signals and systems class, I treated the netlist like a system and hit it
with impulses at various positions. Hold every input at zero, set a single 1 at a position and
clock the chip. Then diff every flop against the all zeros baseline. The flops that change are the response to that one bit. It is like a signals and systems move on
a digital netlist which better helped me understand the structure of the chip. I ran it for the 11 positions of one frame, then for all 121 positions in the grid.</p>

<p>The full sweep gave me something important: every position in the grid lights up exactly
one Bank A flop and exactly one Bank D flop, nothing else. Grouping the 121
positions by which flop they hit collapses each bank to 11 distinct groups.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Bank A                          Bank D
col: 0 1 2 3 4 5 6 7 8 9 10      col: 0 1 2 3 4 5 6 7 8 9 10

Grid:                            Grid:
     A B C D E F G H I J K            A A A A A B B C D D E
     A B C D E F G H I J K            A A F A A B C C D D E
     A B C D E F G H I J K            A A F B B B B C C D E
     A B C D E F G H I J K            A A F B G G G E C C E
     A B C D E F G H I J K            F A F B G E E E E E E
     A B C D E F G H I J K            F F F B G G G E H H H
     A B C D E F G H I J K            B B B B B B G E H I I
     A B C D E F G H I J K            B J J J G G G E H I I
     A B C D E F G H I J K            B J J K E E E E H I I
     A B C D E F G H I J K            B B J K K E E E H H H
     A B C D E F G H I J K            B J J K E E E E E E E
</code></pre></div></div>

<p>By inspection, Bank A is simply the column axis, one register pair per column. Bank D also collapses to 11 groups, but its map follows no clean rule of row, column or diagonal. It is
eleven contiguous regions of the grid of unequal size.</p>

<p>I then asked what a pair does when fed more than one 1 in its group. Driving k
ones into a single group, every group of both banks behaved the same:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>k          1     2     3     4+
pair       01    10    11    11
</code></pre></div></div>

<p>Therefore, each pair is a small saturating 2 bit counter of how many 1s were aimed at its group,
maxing out at a count of three. Each group is independent, ones aimed at one group never impact another.</p>

<h3 id="a-stroke-of-luck">A stroke of luck</h3>

<p>Stuck here, I was playing around with different shadings of the registers. Shading the impulse flops light and their partners dark, the picture suddenly looked a lot like the <a href="#required-state">required state</a>, so I compared them. Suprisingly, they matched exactly. So I followed that thread.</p>

<p><img src="images/6_hunch_1.png?v=1788354816" alt="hunch 1" /></p>

<p>This match corresponded with each counter pair set at a count of 2. I then added the two format latches in their passing state (off), and setting each group to a count of 2 subsequently set the
global counter with the value 22 which I also included in the image as flops in that region were also part of the <a href="#required-state">required state</a>. That accounted for 54 of the flops, all agreeing
with the required state.</p>

<p><img src="images/6_hunch_2.png?v=1788354816" alt="hunch 2" /></p>

<p>Finally, I added the two evaluation window flags at their required values. That brought it to 56, the full size of the required state.</p>

<p><img src="images/6_hunch_3.png?v=1788354816" alt="hunch 3" /></p>

<p>Diffing my constructed state against <code class="language-plaintext highlighter-rouge">required_state.json</code> gave 56 of 56 in
agreement, 0 disagreements. What I had built with reasoning was the required state.</p>

<p>This was really a check from two directions. The required state came backwards,
pushing success = 1 through 47 gates. The impulse map plus the counters built the
same 56 bits forwards. Two unrelated derivations agreeing 56 of 56 with 0
disagreements is confirmation, not a coincidence.</p>

<p><img src="images/7_comparison.png?v=1788354816" alt="the constructed state against the required state" /></p>

<p>Thefore, gathering all of my thoughts and findings together, the required state can we worded into a condition on the input. The condition says that: every group must have been hit exactly twice,
both latches off, the global count at 22 and the window open. This collapsed the problem to a few rules on the grid:</p>

<ol>
  <li><strong>Exactly 2 per row.</strong> The weight latch <code class="language-plaintext highlighter-rouge">X5638</code>.</li>
  <li><strong>Exactly 2 per column.</strong> Bank A is the columns, each must read 2.</li>
  <li><strong>Exactly 2 per Bank D region.</strong> Each of the eleven regions must read 2.</li>
  <li><strong>No two 1s touching</strong>, in any of the 8 directions. The adjacency chain.</li>
</ol>

<p>Hence I ran a depth first search over the rows, placing two 1s per row and discarding any branch that broke a column, region or adjacency rule. It returned exactly one grid:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>col:  0  1  2  3  4  5  6  7  8  9 10

Grid: 
      0  0  0  0  0  0  0  1  0  1  0
      1  0  0  0  0  1  0  0  0  0  0
      0  0  0  0  0  0  0  1  0  1  0
      1  0  1  0  0  0  0  0  0  0  0
      0  0  0  0  1  0  1  0  0  0  0
      0  0  1  0  0  0  0  0  1  0  0
      0  0  0  0  1  0  0  0  0  0  1
      0  1  0  0  0  0  1  0  0  0  0
      0  0  0  1  0  0  0  0  0  0  1
      0  0  0  0  0  1  0  0  1  0  0
      0  1  0  1  0  0  0  0  0  0  0
</code></pre></div></div>

<p><img src="images/8_solution.png?v=1788354816" alt="the regions and the solution" /></p>

<p>Feeding that grid into the viewer, on the netlist pulled straight from the GDS, we get this output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>decoded message : '(* TWO STARS *)'
success asserted: True
</code></pre></div></div>

<p>The overall lesson: visual aids really do help a lot :). But really though, these visualisations and the interactive suite AI helped me to build allowed me to iterate through various ideas quickly, whilst also deepening my understanding of the chip everytime I ran something.</p>

<h3 id="what-the-puzzle-actually-is">What the puzzle actually is</h3>

<p>In hindsight, after I had solved the puzzle and done some research, this circuit is simply a checker for a game. It is Two Not Touch, aka Star Battle. You take a grid split into regions and place two stars in every row, every column and every region, with no two stars touching in any of the eight directions. Looking back, those are the exact four constraints I had recovered the hard way.</p>

<p>The Bank D flops simply represented the regions of the grid. Each pair counted how many stars sat in its region, so every region had to read two. The chip even says it in the output: <code class="language-plaintext highlighter-rouge">(* TWO STARS *)</code>. Additionally, all the easter eggs point towards this same thematic similarity with the stars.</p>

<h2 id="easter-eggs">Easter eggs</h2>

<p>There are probably more easter eggs (and I will update the page if I find any more). These are the ones I found:</p>

<h3 id="morse-code-at-the-bottom-of-the-die">Morse code at the bottom of the die</h3>

<p>While viewing the chip in various online GDS viewers, I noticed a thin line below the die. It sits on layer 200/0, at y = -52.72, just under the design boundary. The row runs almost the full width of the chip. Some viewers do not draw it, since layer 200/0 is not a sky130 layer and it sits off screen below the die. Nonetheless, here is a screenshot of the morse code using <a href="https://www.appliednt.com/gds-viewer/">this GDS viewer</a>. Just remember to slightly zoom out and look below the chip.</p>

<p><img src="images/morse_line.png?v=1788354816" alt="the morse line at the bottom of the die, in a GDS viewer" /></p>

<p>Zooming in, the line is a row of dots and dashes. It is morse code.</p>

<p><img src="images/morse_alphabet.png?v=1788354816" alt="morse code alphabet" /></p>

<p>Decoding it left to right gives “PER ARENAM AD ASTRA”. Seems like some sort of Latin phrase. A quick search reveals that it is a play on “per aspera ad astra”, through hardships to the stars, with arenam meaning sand in place of silicon. It translates as through sand to the stars. The pun fits the theme of an actual chip, since silicon is refined from sand and we place stars in a grid.</p>

<h3 id="the-night-sky-awaits">The night sky awaits</h3>

<p>The original repo also provides an <code class="language-plaintext highlighter-rouge">example_inputs.vcd</code>, the sample input waveforms. While investigating the example inputs to the chip, I wrote a small Python parser to pull the serial input <code class="language-plaintext highlighter-rouge">I</code> out of it, sampling one bit on each positive clock edge while <code class="language-plaintext highlighter-rouge">enable</code> was high. Since each attempt was 121 bits, I split each attempt into 11 frames of 11 bits. I then discovered, in each frame, the first 7 bits are one ASCII character, read LSB first. The last 4 bits are just zero padding. Reading them out gave 11 ASCII characters per attempt. The two example attempts came out as “The night s” and “ky awaits  “, so together they spell “The night sky awaits”. It thereby carries the same night sky theme as the morse line and first prompted me into testing various ascii inputs with zero padding as a solution to this puzzle.</p>

<h3 id="other-messages-the-machine-streams">Other messages the machine streams</h3>

<p>Along the way I fed the chip some extreme inputs just to see what it would say. An empty grid of all zeros streams “EMPTY SKY”:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  cycle  0: 01000101  0x45  'E'
  cycle  1: 01001101  0x4D  'M'
  cycle  2: 01010000  0x50  'P'
  cycle  3: 01010100  0x54  'T'
  cycle  4: 01011001  0x59  'Y'
  cycle  5: 00100000  0x20  ' '
  cycle  6: 01010011  0x53  'S'
  cycle  7: 01001011  0x4B  'K'
  cycle  8: 01011001  0x59  'Y'
  decoded message : 'EMPTY SKY'
  success asserted: False
</code></pre></div></div>

<p>And a full grid of all ones streams “BIG BANG”:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  cycle  0: 01000010  0x42  'B'
  cycle  1: 01001001  0x49  'I'
  cycle  2: 01000111  0x47  'G'
  cycle  3: 00100000  0x20  ' '
  cycle  4: 01000010  0x42  'B'
  cycle  5: 01000001  0x41  'A'
  cycle  6: 01001110  0x4E  'N'
  cycle  7: 01000111  0x47  'G'
  decoded message : 'BIG BANG'
  success asserted: False
</code></pre></div></div>

<p>However, both are reject messages since success is never asserted.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Reverse engineering the Jane Street ASIC puzzle from the GDS up.]]></summary></entry></feed>