The Mysterious Roman Dodecahedron Was Possibly Just For Knitting

Over the years archaeological digs of Roman sites have uncovered many of these strange dodecahedrons, usually made out of metal and with various holes in their faces. With no surviving records that describe how they were used, speculation has ranged from jewelry to a knitting aid. In a 2023 video by [Amy Gaines] it is this latter use which is explored, using a 3D printed dodecahedron and some wooden dowels to knit both gold wire and yarn into rather intricate patterns that are also referred to as ‘Viking Knitting’.

As we mentioned previously when yet another one of these dodecahedrons was uncovered, their use was unlikely to be of supreme relevance in military or scientific circles on account of a lack of evidence. What is quite possible is that these were both attractive shapes for jewelry (beads), and useful knitting aids for both jewelry makers (for e.g. gold wire braiding) and quite possibly yarn-related uses. The results which [Amy] demonstrates in the video for the gold wire in particular bear a striking resemblance to ancient braided gold chains on display at the Met and other museums, which leads credence to this theory.

If these items were effectively just common knitting tools, that would explain why the historical record is mum on them, as they would have been as notable as a hammer or a precision lathe used by the ancient Greeks.

Thanks to [john] for the tip.

Continue reading “The Mysterious Roman Dodecahedron Was Possibly Just For Knitting”

C++ Design Patterns For Low-Latency Applications

With performance optimizations seemingly having lost their relevance in an era of ever-increasing hardware performance, there are still many good reasons to spend some time optimizing code. In a recent preprint article by [Paul Bilokon] and [Burak Gunduz] of the Imperial College London the focus is specifically on low-latency patterns that are relevant for applications such as high-frequency trading (HFT). In HFT the small margins are compensated for by churning through absolutely massive volumes of trades, all of which relies on extremely low latency to gain every advantage. Although FPGA-based solutions are very common in HFT due their low-latency, high-parallelism, C++ is the main language being used beyond FPGAs.

Although many of the optimizations listed in the paper are quite obvious, such as prewarming the CPU caches, using constexpr, loop unrolling and use of inlining, other patterns are less obvious, such as hotpath versus coldpath. This overlaps with the branch reduction pattern, with both patterns involving the separation of commonly and rarely executed code (like error handling and logging), improving use of the CPU’s caches and preventing branch mispredictions, as the benchmarks (using Google Benchmark) clearly demonstrates. All design patterns can also be found in the GitHub repository.

Other interesting tidbits are the impact of signed and unsigned comparisons, mixing floating point datatypes and of course lock-free programming using a ring buffer design. Only missing from this list appears to be aligned vs unaligned memory accesses and zero-copy optimizations, but those should be easy additions to implement and test next to the other optimizations in this paper.

Making SD Cards More Nostalgic With More Cartridge-ness

As practical SD cards are, they lack much of what made floppy disks and cartridges so awesome: room for art and a list of contents, as well as the ability to not be lost in shaggy carpet or down a pet’s gullet. In a fit of righteous nostalgia, [Abe] decided that he’d turn SD cards into cartridges in the best way possible, and amazingly managed to not only finish the project after two years, but also make it look snazzy enough to have come straight out of the 1980s. The resulting cartridges come both with fixed (256 MB) and removable micro SD card storage, which are mounted on a PCB that passively connects to pogo pins in the custom, 3D printed reader.

Front of an SD-card-turned-cartridge with adn without decal. (Credit: Abe's Projects, YouTube)
Front of an SD-card-turned-cartridge with and without decal. (Credit: Abe’s Projects, YouTube)

The inspiration for this project kicked in while [Abe] was working on a floppy drive conversion project called the Floppy8, which crammed an MCU into an external floppy drive along with a rough version of these SD card-based cartridges that used the physical card’s edge connector to connect with a micro SD slot inside the converted floppy drive. The problem with this setup was that alignment was terrible, and micro SD cards would break, along with a range of other quality of life issues.

Next, the SD card was put into a slot on the carrier PCB that featured its own edge connector. This improved matters, but the overly complicated (moving) read head in the reader turned out to be very unreliable, in addition to FDM printed parts having general tolerance and durability issues. Eventually a simplified design which takes these limitations in mind was created that so far seems to work just fine.

Although SD cards in cartridges are not a new idea, using them purely as a data carrier is far less common. One could argue about the practicality of turning a fingernail-sized micro SD card into something much larger, but in terms of aesthetics and handleability it definitely gets an A+.

Continue reading “Making SD Cards More Nostalgic With More Cartridge-ness”

Why The 555 Is Not A Timer, But Can Be One

Although commonly referred to as a ‘timer IC’, the venerable NE555 and derivatives are in fact not timer ICs. This perhaps controversial statement is the open door that gets kicked in by [PKAE Electronics] over at YouTube, as he explains with excellent diagrams and simulations how exactly these ICs work, and what it takes to make it actually do timer things. For anyone who has ever used one of these chips there is probably nothing too mind-blowing, but it’s an infinitely better way to wrap your way around an NE555 and kin than a datasheet.

At its core, the 555 contains three 5 kOhm resistors as a voltage divider, which has been incorrectly postulated to be the source of the chip’s name. This voltage divider controls two comparators, which in turn control an SR flipflop. These comparators are used for the voltage trigger and threshold inputs, which in turn toggle the flipflop, respectively setting and resetting it. This by itself just means that the 555 can be used as a threshold detector, with settable control voltage. How a 555 becomes a timer is when the discharge, trigger and threshold pins are combined with external resistors and a capacitor, which creates a smooth square wave on the 555’s output pin.

There are many ways to make basic components into an oscillator of some type, but the 555 is a great choice when you want something more refined that doesn’t involve using an entire MCU. That said, there’s far more that the 555 can be used for, as [PKAE] alludes to, and we hope that he makes more excellent videos on these applications.

Continue reading “Why The 555 Is Not A Timer, But Can Be One”

Misconceptions About Loops, Or: Static Code Analysis Is Hard

When thinking about loops in programming languages, they often get simplified down to a conditions section and a body, but this belies the dizzying complexity that emerges when considering loop edge cases within the context of static analysis. A paper titled Misconceptions about Loops in C by [Martin Brain] and colleagues as presented to SOAP 2024 conference goes through a whole list of false assumptions when it comes to loops, including for languages other than C. Perhaps most interesting is the conclusion that these ‘edge cases’ are in fact a lot more common than generally assumed, courtesy of how creative languages and their users can be when writing their code, with or without dragging in the meta-language of C’s preprocessor.

Assumptions like loop equivalence can fall apart when considering the CFG ( control flow graph) interpretation versus a parse tree one where the former may e.g. merge loops. There are also doozies like assuming that the loop body will always exist, that the first instruction(s) in a loop are always the entry point, and the horrors of estimating loop exits in the context of labels, inlined functions and more. Some languages have specific loop control flow features that differ from C (e.g. Python’s for/else and Ada’s loop), all of which affect a static analysis.

Ultimately, writing a good static analysis tool is hard, and there are plenty of cases where it’s likely to trip up and give an invalid result. A language which avoids ambiguity (e.g. Ada) helps immensely here, but for other languages it helps to write your code as straightforward as possible to give the static analysis tool a fighting chance, or just get really good at recognizing confused static analysis tool noises.

(Heading image: Control flow merges can create multiple loop entry
edges (Credit: Martin Brand, et al., SOAP 2024) )

Looking At Standard-Cell Design In The Pentium Processor

Die photo of the Intel Pentium processor with standard cells highlighted in red. The edges of the chip suffered some damage when I removed the metal layers. (Credit: Ken Shirriff)
Die photo of the Intel Pentium processor with standard cells highlighted in red. The edges of the chip suffered some damage when I removed the metal layers. (Credit: Ken Shirriff)

Whereas the CPUs and similar ASICs of the 1970s had their transistors laid out manually, with the move from LSI to VLSI, it became necessary to optimize the process of laying out the transistors and the metal interconnects between them. This resulted in the development of standard-cells: effectively batches of transistors with each a specific function that could be chained together. First simple and then more advanced auto-routing algorithms handled the placement and routing of these standard elements, leading to dies with easily recognizable structures under an optical microscope. Case in point an original (P54C) Intel Pentium, which [Ken Shirriff] took an in-depth look at.

Using a by now almost unimaginably large 600 nm process, the individual elements of these standard cells including their PMOS and NMOS components within the BiCMOS process can be readily identified and their structure reverse-engineered. What’s interesting about BiCMOS compared to CMOS is that the former allows for the use of bipolar junction transistors, which offer a range of speed, gain and output impedance advantages that are beneficial for some part of a CPU compared to CMOS. Over time BiCMOS’ advantages became less pronounced and was eventually abandoned.

All in all, this glimpse at the internals of a Pentium processor provides a fascinating snapshot of high-end Intel semiconductor prowess in the early 1990s.

(Top image: A D flip-flop in the Pentium. Credit: [Ken Shirriff] )

The Flash Memory Lifespan Question: Why QLC May Be NAND Flash’s Swan Song

The late 1990s saw the widespread introduction of solid-state storage based around NAND Flash. Ranging from memory cards for portable devices to storage for desktops and laptops, the data storage future was prophesied to rid us of the shackles of magnetic storage that had held us down until then. As solid-state drives (SSDs) took off in the consumer market, there were those who confidently knew that before long everyone would be using SSDs and hard-disk drives (HDDs) would be relegated to the dust bin of history as the price per gigabyte and general performance of SSDs would just be too competitive.

Fast-forward a number of years, and we are now in a timeline where people are modifying SSDs to have less storage space, just so that their performance and lifespan are less terrible. The reason for this is that by now NAND Flash has hit a number of limits that prevent it from further scaling density-wise, mostly in terms of its feature size. Workarounds include stacking more layers on top of each other (3D NAND) and increasing the number of voltage levels – and thus bits – within an individual cell. Although this has boosted the storage capacity, the transition from single-level cell (SLC) to multi-level (MLC) and today’s TLC and QLC NAND Flash have come at severe penalties, mostly in the form of limited write cycles and much reduced transfer speeds.

So how did we get here, and is there life beyond QLC NAND Flash?

Continue reading “The Flash Memory Lifespan Question: Why QLC May Be NAND Flash’s Swan Song”