Setting up a flow for ABC9

Much of the configuration comes from attributes and specify blocks in Verilog simulation models.

specify syntax

Since specify is a relatively obscure part of the Verilog standard, a quick guide to the syntax:

specify                           // begins a specify block
  (A => B) = 123;                 // simple combinational path from A to B with a delay of 123.
  (A *> B) = 123;                 // simple combinational path from A to all bits of B with a delay of 123 for all.
  if (FOO) (A => B) = 123;        // paths may apply under specific conditions.
  (posedge CLK => (Q : D)) = 123; // combinational path triggered on the positive edge of CLK; used for clock-to-Q arrival paths.
  $setup(A, posedge CLK, 123);    // setup constraint for an input relative to a clock.
endspecify                        // ends a specify block

By convention, all delays in specify blocks are in integer picoseconds. Files containing specify blocks should be read with the -specify option to read_verilog so that they aren’t skipped.


LUTs need to be annotated with an (* abc9_lut=N *) attribute, where N is the relative area of that LUT model. For example, if an architecture can combine LUTs to produce larger LUTs, then the combined LUTs would have increasingly larger N. Conversely, if an architecture can split larger LUTs into smaller LUTs, then the smaller LUTs would have smaller N.

LUTs are generally specified with simple combinational paths from the LUT inputs to the LUT output.


DFFs should be annotated with an (* abc9_flop *) attribute, however ABC9 has some specific requirements for this to be valid: - the DFF must initialise to zero (consider using dfflegalize to ensure this). - the DFF cannot have any asynchronous resets/sets (see the simplification idiom and the Boxes section for what to do here).

It is worth noting that in pure abc9 mode, only the setup and arrival times are passed to ABC9 (specifically, they are modelled as buffers with the given delay). In abc9 -dff, the flop itself is passed to ABC9, permitting sequential optimisations.

Some vendors have universal DFF models which include async sets/resets even when they’re unused. Therefore the simplification idiom exists to handle this: by using a techmap file to discover flops which have a constant driver to those asynchronous controls, they can be mapped into an intermediate, simplified flop which qualifies as an (* abc9_flop *), ran through abc9, and then mapped back to the original flop. This is used in synth_intel_alm and synth_quicklogic for the PolarPro3.

DFFs are usually specified to have setup constraints against the clock on the input signals, and an arrival time for the Q output.


A “box” is a purely-combinational piece of hard logic. If the logic is exposed to ABC9, it’s a “whitebox”, otherwise it’s a “blackbox”. Carry chains would be best implemented as whiteboxes, but a DSP would be best implemented as a blackbox (multipliers are too complex to easily work with). LUT RAMs can be implemented as whiteboxes too.

Boxes are arguably the biggest advantage that ABC9 has over ABC: by being aware of carry chains and DSPs, it avoids optimising for a path that isn’t the actual critical path, while the generally-longer paths result in ABC9 being able to reduce design area by mapping other logic to larger-but-slower cells.