logo Netzschleuder network catalog, repository, and centrifuge

History of itc99

The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.

[entries] New entry: itc99 by Tiago de Paula Peixoto 6882837
diff --git a/entries/itc99/__init__.py b/entries/itc99/__init__.py
new file mode 100644
index 0000000..d97985d
--- /dev/null
+++ b/entries/itc99/__init__.py
@@ -0,0 +1,107 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2020-2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from .. import *
+import re
+
+title = "ITC'99 benchmark circuits (2000)"
+description = """Gate-level netlists of the ITC'99 benchmark circuits developed by the CAD Group at Politecnico di Torino (the "I99T" set), a collection of synchronous digital circuits used as benchmarks for testing and verification (e.g. automatic test pattern generation) of integrated circuits. Each circuit was described at register-transfer level in VHDL and synthesized into gate-level netlists with the Synopsys Design Compiler; the netlists use only AND, NAND, OR, NOR and NOT gates and D-type flip-flops. The circuits implement, for example, finite-state machines that compare serial flows (b01) or recognize BCD numbers (b02), a resource arbiter (b03), a voting system (b10), and subsets of the Viper (b14) and Intel 80386 (b15) processors; the larger circuits combine several copies of these (b17: three copies of b15; b18 and b19: two copies of b14 and two of b17; b20 to b22: copies and modified versions of b14). Circuits b16 (parametric) and b30 have no gate-level netlist. The netlists are in the ISCAS'89 "bench" format of the second release of the benchmarks (2002). For each circuit, the collection contains up to four netlists: the network named after the circuit (e.g. `b01`) is the netlist synthesized with standard options, which may contain completely useless gates; the networks with the suffix `_opt` are the netlists synthesized with optimization options (which superseded the "stripped" netlists of the first release); and the networks with the suffixes `_C` and `_opt_C` are the combinational versions of these two, in which the flip-flops have been transformed into pairs of primary inputs and outputs (pseudo-inputs carrying the state, named after the flip-flop with the suffix `_SCAN_IN`, and pseudo-outputs carrying the next state), so that these networks have no directed cycles. Circuit b19 has no optimized netlists.
+
+In each network, nodes represent the signals of the circuit, i.e. its primary inputs and the logic gates and flip-flops (each identified with its output signal), plus one terminal node for each primary output of the circuit; a directed edge from node $i$ to node $j$ means that the signal $i$ is an input of gate or flip-flop $j$ (or is the signal delivered at primary output terminal $j$). Since flip-flops feed back the state of the circuit, the networks of the sequential versions contain directed cycles. A gate may take the same signal more than once, resulting in parallel edges (e.g. 13 in b05), and in some circuits some gates drive no other gate or output (e.g. 22 and 44 in b18 and b19, respectively).
+
+The networks have the following properties:
+
+- Nodes: `name`, the name of the signal in the netlist (e.g. `U34`, `STATO_REG_2_`), with the primary output terminals having the name of the output signal; `type`, the type of node: `INPUT` (primary input), `OUTPUT` (primary output terminal), `DFF` (D-type flip-flop, only in the sequential versions), or the logic gate (`AND`, `NAND`, `OR`, `NOR`, `NOT`).[^icon]
+
+[^icon]: Description obtained in part from the [ICON](https://icon.colorado.edu) project."""
+tags = ['Technological', 'Unweighted', 'Multigraph', 'Metadata']
+url = 'https://github.com/cad-polito-it/I99T'
+citation = [('F. Corno, M. Sonza Reorda, G. Squillero, "RT-level ITC\'99 benchmarks and first ATPG results." IEEE Design & Test of Computers 17(3), 44-53 (2000)', 'https://doi.org/10.1109/54.867894')]
+icon_hash = '5728d582461efe0c7a675f14'
+upstream_license = ("European Union Public Licence v1.2 (EUPL-1.2)",
+                    "https://github.com/cad-polito-it/I99T/blob/master/LICENSE")
+upstream_prefix = 'https://raw.githubusercontent.com/cad-polito-it/I99T/8a2c3b500ee7ff20e7031de92592b737bedc6d8c/i99t'
+_circuits = ['b01', 'b02', 'b03', 'b04', 'b05', 'b06', 'b07', 'b08', 'b09',
+             'b10', 'b11', 'b12', 'b13', 'b14', 'b15', 'b17', 'b18', 'b19',
+             'b20', 'b21', 'b22']
+# Standard synthesis first (as in earlier versions of this entry), then the
+# optimized (_opt) and combinational (_C, _opt_C) versions; b19 has no
+# optimized version.
+files = [(f'{c}/{c}{v}.bench', f'{c}{v}', 'bench')
+         for v in ['', '_opt', '_C', '_opt_C'] for c in _circuits
+         if not (c == 'b19' and v.startswith('_opt'))]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+def parse_bench(f):
+    """Parse a netlist in the ISCAS'89 bench format."""
+    g = Graph(directed=True)
+    g.vp.name = g.new_vp("string")
+    g.vp.type = g.new_vp("string")
+    vs = {}
+    def get_v(s):
+        v = vs.get(s)
+        if v is None:
+            v = vs[s] = g.add_vertex()
+            g.vp.name[v] = s
+        return v
+    outputs = []
+    edges = []
+    for line in f:
+        line = line.strip()
+        if not line or line.startswith("#"):
+            continue
+        m = re.fullmatch(r"(INPUT|OUTPUT)\s*\(\s*(\S+)\s*\)", line)
+        if m is not None:
+            if m[1] == "INPUT":
+                g.vp.type[get_v(m[2])] = "INPUT"
+            else:
+                outputs.append(m[2])
+            continue
+        m = re.fullmatch(r"(\S+)\s*=\s*(\w+)\s*\((.*)\)", line)
+        if m is None:
+            raise ValueError(f"cannot parse line: {line}")
+        v = get_v(m[1])
+        g.vp.type[v] = m[2].upper()
+        for s in m[3].split(","):
+            s = s.strip()
+            if s:
+                edges.append((get_v(s), v))
+    for s in outputs:
+        u = get_v(s)
+        v = g.add_vertex()
+        g.vp.name[v] = s
+        g.vp.type[v] = "OUTPUT"
+        edges.append((u, v))
+    g.add_edge_list(edges)
+    return g
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+    global files
+    name = __name__.split(".")[-1]
+    for fnames, alt, fmt in files:
+        if alts is not None and alt not in alts:
+            continue
+        with open_upstream_file(name, fnames, "r") as f:
+            g = parse_bench(f)
+        yield alt, g