From 3f0bb441f8a3014bf6b3a656b673fc07663bda76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 4 Feb 2019 16:46:24 -0800 Subject: Add tests --- tests/aig/and.aag | 5 +++++ tests/aig/buffer.aag | 3 +++ tests/aig/cnt1.aag | 3 +++ tests/aig/cnt1e.aag | 8 ++++++++ tests/aig/empty.aag | 1 + tests/aig/false.aag | 2 ++ tests/aig/halfadder.aag | 14 ++++++++++++++ tests/aig/inverter.aag | 3 +++ tests/aig/notcnt1.aag | 4 ++++ tests/aig/notcnt1e.aag | 8 ++++++++ tests/aig/or.aag | 5 +++++ tests/aig/run-test.sh | 20 ++++++++++++++++++++ tests/aig/toggle-re.aag | 14 ++++++++++++++ tests/aig/toggle.aag | 4 ++++ tests/aig/true.aag | 2 ++ tests/tools/autotest.sh | 21 +++++++++++++-------- 16 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 tests/aig/and.aag create mode 100644 tests/aig/buffer.aag create mode 100644 tests/aig/cnt1.aag create mode 100644 tests/aig/cnt1e.aag create mode 100644 tests/aig/empty.aag create mode 100644 tests/aig/false.aag create mode 100644 tests/aig/halfadder.aag create mode 100644 tests/aig/inverter.aag create mode 100644 tests/aig/notcnt1.aag create mode 100644 tests/aig/notcnt1e.aag create mode 100644 tests/aig/or.aag create mode 100755 tests/aig/run-test.sh create mode 100644 tests/aig/toggle-re.aag create mode 100644 tests/aig/toggle.aag create mode 100644 tests/aig/true.aag diff --git a/tests/aig/and.aag b/tests/aig/and.aag new file mode 100644 index 000000000..d1ef2c5a5 --- /dev/null +++ b/tests/aig/and.aag @@ -0,0 +1,5 @@ +aag 3 2 0 1 1 +2 +4 +6 +6 2 4 diff --git a/tests/aig/buffer.aag b/tests/aig/buffer.aag new file mode 100644 index 000000000..94a6fb1ed --- /dev/null +++ b/tests/aig/buffer.aag @@ -0,0 +1,3 @@ +aag 1 1 0 1 0 +2 +2 diff --git a/tests/aig/cnt1.aag b/tests/aig/cnt1.aag new file mode 100644 index 000000000..ce4f28fcb --- /dev/null +++ b/tests/aig/cnt1.aag @@ -0,0 +1,3 @@ +aag 1 0 1 0 0 1 +2 3 +2 diff --git a/tests/aig/cnt1e.aag b/tests/aig/cnt1e.aag new file mode 100644 index 000000000..6db3f0ffd --- /dev/null +++ b/tests/aig/cnt1e.aag @@ -0,0 +1,8 @@ +aag 5 1 1 0 3 1 +2 +4 10 +4 +6 5 3 +8 4 2 +10 9 7 +b0 AIGER_NEVER diff --git a/tests/aig/empty.aag b/tests/aig/empty.aag new file mode 100644 index 000000000..40c0f00cb --- /dev/null +++ b/tests/aig/empty.aag @@ -0,0 +1 @@ +aag 0 0 0 0 0 diff --git a/tests/aig/false.aag b/tests/aig/false.aag new file mode 100644 index 000000000..421e64a91 --- /dev/null +++ b/tests/aig/false.aag @@ -0,0 +1,2 @@ +aag 0 0 0 1 0 +0 diff --git a/tests/aig/halfadder.aag b/tests/aig/halfadder.aag new file mode 100644 index 000000000..5bf54d38d --- /dev/null +++ b/tests/aig/halfadder.aag @@ -0,0 +1,14 @@ +aag 7 2 0 2 3 +2 +4 +6 +12 +6 13 15 +12 2 4 +14 3 5 +i0 x +i1 y +o0 s +o1 c +c +half adder diff --git a/tests/aig/inverter.aag b/tests/aig/inverter.aag new file mode 100644 index 000000000..ff7c28542 --- /dev/null +++ b/tests/aig/inverter.aag @@ -0,0 +1,3 @@ +aag 1 1 0 1 0 +2 +3 diff --git a/tests/aig/notcnt1.aag b/tests/aig/notcnt1.aag new file mode 100644 index 000000000..e92815f23 --- /dev/null +++ b/tests/aig/notcnt1.aag @@ -0,0 +1,4 @@ +aag 1 0 1 0 0 1 +2 3 +3 +b0 AIGER_NEVER diff --git a/tests/aig/notcnt1e.aag b/tests/aig/notcnt1e.aag new file mode 100644 index 000000000..141c864f7 --- /dev/null +++ b/tests/aig/notcnt1e.aag @@ -0,0 +1,8 @@ +aag 5 1 1 0 3 1 +2 +4 10 +5 +6 5 3 +8 4 2 +10 9 7 +b0 AIGER_NEVER diff --git a/tests/aig/or.aag b/tests/aig/or.aag new file mode 100644 index 000000000..f780e339f --- /dev/null +++ b/tests/aig/or.aag @@ -0,0 +1,5 @@ +aag 3 2 0 1 1 +2 +4 +7 +6 3 5 diff --git a/tests/aig/run-test.sh b/tests/aig/run-test.sh new file mode 100755 index 000000000..308578f01 --- /dev/null +++ b/tests/aig/run-test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +OPTIND=1 +seed="" # default to no seed specified +while getopts "S:" opt +do + case "$opt" in + S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space + seed="SEED=$arg" ;; + esac +done +shift "$((OPTIND-1))" + +# check for Icarus Verilog +if ! which iverilog > /dev/null ; then + echo "$0: Error: Icarus Verilog 'iverilog' not found." + exit 1 +fi + +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" diff --git a/tests/aig/toggle-re.aag b/tests/aig/toggle-re.aag new file mode 100644 index 000000000..b662bb386 --- /dev/null +++ b/tests/aig/toggle-re.aag @@ -0,0 +1,14 @@ +aag 7 2 1 2 4 +2 +4 +6 8 +6 +7 +8 4 10 +10 13 15 +12 2 6 +14 3 7 +i0 enable +i1 reset +o0 Q +o1 !Q diff --git a/tests/aig/toggle.aag b/tests/aig/toggle.aag new file mode 100644 index 000000000..09651012d --- /dev/null +++ b/tests/aig/toggle.aag @@ -0,0 +1,4 @@ +aag 1 0 1 2 0 +2 3 +2 +3 diff --git a/tests/aig/true.aag b/tests/aig/true.aag new file mode 100644 index 000000000..366893648 --- /dev/null +++ b/tests/aig/true.aag @@ -0,0 +1,2 @@ +aag 0 0 0 1 0 +1 diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index d6216244f..c01ce5611 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -86,8 +86,9 @@ shift $((OPTIND - 1)) for fn do - bn=${fn%.v} - if [ "$bn" == "$fn" ]; then + bn=${fn%.*} + ext=${fn##*.} + if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]]; then echo "Invalid argument: $fn" >&2 exit 1 fi @@ -109,10 +110,14 @@ do fn=$(basename $fn) bn=$(basename $bn) - egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.v + if [[ "$ext" == "v" ]]; then + egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + else + cp ../$fn ${bn}_ref.${ext} + fi if [ ! -f ../${bn}_tb.v ]; then - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v + "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${ext} else cp ../${bn}_tb.v ${bn}_tb.v fi @@ -138,16 +143,16 @@ do fi if [ -n "$scriptfiles" ]; then - test_passes -f "$frontend $include_opts" ${bn}_ref.v $scriptfiles + test_passes -f "$frontend $include_opts" ${bn}_ref.${ext} $scriptfiles elif [ -n "$scriptopt" ]; then - test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.v + test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.${ext} elif [ "$frontend" = "verific" ]; then test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -all; opt; memory;;" elif [ "$frontend" = "verific_gates" ]; then test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -gates -all; opt; memory;;" else - test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v - test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v + test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${ext} + test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${ext} fi touch ../${bn}.log } -- cgit v1.2.3 From cc0b723484d27424a65336662b7e8c19e21589c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 12:19:48 -0800 Subject: WIP --- frontends/aiger/Makefile.inc | 3 + frontends/aiger/aigerparse.cc | 213 ++++++++++++++++++++++++++++++++++++++++++ frontends/aiger/aigerparse.h | 31 ++++++ 3 files changed, 247 insertions(+) create mode 100644 frontends/aiger/Makefile.inc create mode 100644 frontends/aiger/aigerparse.cc create mode 100644 frontends/aiger/aigerparse.h diff --git a/frontends/aiger/Makefile.inc b/frontends/aiger/Makefile.inc new file mode 100644 index 000000000..bc1112452 --- /dev/null +++ b/frontends/aiger/Makefile.inc @@ -0,0 +1,3 @@ + +OBJS += frontends/aiger/aigerparse.o + diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc new file mode 100644 index 000000000..c7a9aecb9 --- /dev/null +++ b/frontends/aiger/aigerparse.cc @@ -0,0 +1,213 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// [[CITE]] The AIGER And-Inverter Graph (AIG) Format Version 20071012 +// Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. +// http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include "aigerparse.h" + +YOSYS_NAMESPACE_BEGIN + +#define log_debug log + +void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ + std::string header; + f >> header; + if (header != "aag") { + log_error("Unsupported AIGER file!\n"); + return; + } + + int M, I, L, O, A; + int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + if (!(f >> M >> I >> L >> O >> A)) { + log_error("Invalid AIGER header\n"); + return; + } + for (auto &i : std::array,4>{B, C, J, F}) { + if (f.peek() != ' ') break; + if (!(f >> i)) { + log_error("Invalid AIGER header\n"); + return; + } + } + + std::string line; + std::getline(f, line); // Ignore up to start of next ine, as standard + // says anything that follows could be used for + // optional sections + + log_debug("M=%d I=%d L=%d O=%d A=%d B=%d C=%d J=%d F=%d\n", M, I, L, O, A, B, C, J, F); + + int line_count = 1; + std::stringstream ss; + + auto module = new RTLIL::Module; + module->name = RTLIL::escape_id("aig"); // TODO: Name? + if (design->module(module->name)) + log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + design->add(module); + + auto createWireIfNotExists = [module](int literal) { + const int variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? + inv->setPort("\\A", wire_inv); + inv->setPort("\\Y", wire); + + return wire; + }; + + int l1, l2, l3; + + // Parse inputs + for (int i = 0; i < I; ++i, ++line_count) { + if (!(f >> l1)) { + log_error("Line %d cannot be interpreted as an input!\n", line_count); + return; + } + log_debug("%d is an input\n", l1); + log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? + RTLIL::Wire *wire = createWireIfNotExists(l1); + wire->port_input = true; + } + + // Parse latches + for (int i = 0; i < L; ++i, ++line_count) { + if (!(f >> l1 >> l2)) { + log_error("Line %d cannot be interpreted as a latch!\n", line_count); + return; + } + log_debug("%d %d is a latch\n", l1, l2); + log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? + RTLIL::Wire *q_wire = createWireIfNotExists(l1); + RTLIL::Wire *d_wire = createWireIfNotExists(l2); + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + RTLIL::Wire *clk_wire = module->wire(clk_id); + if (!clk_wire) { + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } + + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } + + // Parse outputs + for (int i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) { + log_error("Line %d cannot be interpreted as an output!\n", line_count); + return; + } + + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(l1); + wire->port_output = true; + } + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse bad state properties + for (int i = 0; i < B; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse invariant constraints + for (int i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse justice properties + for (int i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse fairness constraints + for (int i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // Parse AND + for (int i = 0; i < A; ++i, ++line_count) { + if (!(f >> l1 >> l2 >> l3)) { + log_error("Line %d cannot be interpreted as an AND!\n", line_count); + return; + } + + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(l3); + + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } + + module->fixup_ports(); +} + +struct AigerFrontend : public Frontend { + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + log("Load modules from an AIGER file into the current design.\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + break; + } + extra_args(f, filename, args, argidx); + + parse_aiger(design, *f); + } +} AigerFrontend; + +YOSYS_NAMESPACE_END diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h new file mode 100644 index 000000000..6a250aa67 --- /dev/null +++ b/frontends/aiger/aigerparse.h @@ -0,0 +1,31 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef ABC_AIGERPARSE +#define ABC_AIGERPARSE + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + +YOSYS_NAMESPACE_END + +#endif -- cgit v1.2.3 From fdd55d064b16f9334c86bb15b1c32cfb45294802 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 12:20:36 -0800 Subject: Rename ASCII tests --- tests/aig/and.aag | 5 ----- tests/aig/buffer.aag | 3 --- tests/aig/cnt1.aag | 3 --- tests/aig/cnt1e.aag | 8 -------- tests/aig/empty.aag | 1 - tests/aig/false.aag | 2 -- tests/aig/halfadder.aag | 14 -------------- tests/aig/inverter.aag | 3 --- tests/aig/notcnt1.aag | 4 ---- tests/aig/notcnt1e.aag | 8 -------- tests/aig/or.aag | 5 ----- tests/aig/run-test.sh | 20 -------------------- tests/aig/toggle-re.aag | 14 -------------- tests/aig/toggle.aag | 4 ---- tests/aig/true.aag | 2 -- tests/aiger/and.aag | 5 +++++ tests/aiger/buffer.aag | 3 +++ tests/aiger/cnt1.aag | 3 +++ tests/aiger/cnt1e.aag | 8 ++++++++ tests/aiger/empty.aag | 1 + tests/aiger/false.aag | 2 ++ tests/aiger/halfadder.aag | 14 ++++++++++++++ tests/aiger/inverter.aag | 3 +++ tests/aiger/notcnt1.aag | 4 ++++ tests/aiger/notcnt1e.aag | 8 ++++++++ tests/aiger/or.aag | 5 +++++ tests/aiger/run-test.sh | 20 ++++++++++++++++++++ tests/aiger/toggle-re.aag | 14 ++++++++++++++ tests/aiger/toggle.aag | 4 ++++ tests/aiger/true.aag | 2 ++ 30 files changed, 96 insertions(+), 96 deletions(-) delete mode 100644 tests/aig/and.aag delete mode 100644 tests/aig/buffer.aag delete mode 100644 tests/aig/cnt1.aag delete mode 100644 tests/aig/cnt1e.aag delete mode 100644 tests/aig/empty.aag delete mode 100644 tests/aig/false.aag delete mode 100644 tests/aig/halfadder.aag delete mode 100644 tests/aig/inverter.aag delete mode 100644 tests/aig/notcnt1.aag delete mode 100644 tests/aig/notcnt1e.aag delete mode 100644 tests/aig/or.aag delete mode 100755 tests/aig/run-test.sh delete mode 100644 tests/aig/toggle-re.aag delete mode 100644 tests/aig/toggle.aag delete mode 100644 tests/aig/true.aag create mode 100644 tests/aiger/and.aag create mode 100644 tests/aiger/buffer.aag create mode 100644 tests/aiger/cnt1.aag create mode 100644 tests/aiger/cnt1e.aag create mode 100644 tests/aiger/empty.aag create mode 100644 tests/aiger/false.aag create mode 100644 tests/aiger/halfadder.aag create mode 100644 tests/aiger/inverter.aag create mode 100644 tests/aiger/notcnt1.aag create mode 100644 tests/aiger/notcnt1e.aag create mode 100644 tests/aiger/or.aag create mode 100755 tests/aiger/run-test.sh create mode 100644 tests/aiger/toggle-re.aag create mode 100644 tests/aiger/toggle.aag create mode 100644 tests/aiger/true.aag diff --git a/tests/aig/and.aag b/tests/aig/and.aag deleted file mode 100644 index d1ef2c5a5..000000000 --- a/tests/aig/and.aag +++ /dev/null @@ -1,5 +0,0 @@ -aag 3 2 0 1 1 -2 -4 -6 -6 2 4 diff --git a/tests/aig/buffer.aag b/tests/aig/buffer.aag deleted file mode 100644 index 94a6fb1ed..000000000 --- a/tests/aig/buffer.aag +++ /dev/null @@ -1,3 +0,0 @@ -aag 1 1 0 1 0 -2 -2 diff --git a/tests/aig/cnt1.aag b/tests/aig/cnt1.aag deleted file mode 100644 index ce4f28fcb..000000000 --- a/tests/aig/cnt1.aag +++ /dev/null @@ -1,3 +0,0 @@ -aag 1 0 1 0 0 1 -2 3 -2 diff --git a/tests/aig/cnt1e.aag b/tests/aig/cnt1e.aag deleted file mode 100644 index 6db3f0ffd..000000000 --- a/tests/aig/cnt1e.aag +++ /dev/null @@ -1,8 +0,0 @@ -aag 5 1 1 0 3 1 -2 -4 10 -4 -6 5 3 -8 4 2 -10 9 7 -b0 AIGER_NEVER diff --git a/tests/aig/empty.aag b/tests/aig/empty.aag deleted file mode 100644 index 40c0f00cb..000000000 --- a/tests/aig/empty.aag +++ /dev/null @@ -1 +0,0 @@ -aag 0 0 0 0 0 diff --git a/tests/aig/false.aag b/tests/aig/false.aag deleted file mode 100644 index 421e64a91..000000000 --- a/tests/aig/false.aag +++ /dev/null @@ -1,2 +0,0 @@ -aag 0 0 0 1 0 -0 diff --git a/tests/aig/halfadder.aag b/tests/aig/halfadder.aag deleted file mode 100644 index 5bf54d38d..000000000 --- a/tests/aig/halfadder.aag +++ /dev/null @@ -1,14 +0,0 @@ -aag 7 2 0 2 3 -2 -4 -6 -12 -6 13 15 -12 2 4 -14 3 5 -i0 x -i1 y -o0 s -o1 c -c -half adder diff --git a/tests/aig/inverter.aag b/tests/aig/inverter.aag deleted file mode 100644 index ff7c28542..000000000 --- a/tests/aig/inverter.aag +++ /dev/null @@ -1,3 +0,0 @@ -aag 1 1 0 1 0 -2 -3 diff --git a/tests/aig/notcnt1.aag b/tests/aig/notcnt1.aag deleted file mode 100644 index e92815f23..000000000 --- a/tests/aig/notcnt1.aag +++ /dev/null @@ -1,4 +0,0 @@ -aag 1 0 1 0 0 1 -2 3 -3 -b0 AIGER_NEVER diff --git a/tests/aig/notcnt1e.aag b/tests/aig/notcnt1e.aag deleted file mode 100644 index 141c864f7..000000000 --- a/tests/aig/notcnt1e.aag +++ /dev/null @@ -1,8 +0,0 @@ -aag 5 1 1 0 3 1 -2 -4 10 -5 -6 5 3 -8 4 2 -10 9 7 -b0 AIGER_NEVER diff --git a/tests/aig/or.aag b/tests/aig/or.aag deleted file mode 100644 index f780e339f..000000000 --- a/tests/aig/or.aag +++ /dev/null @@ -1,5 +0,0 @@ -aag 3 2 0 1 1 -2 -4 -7 -6 3 5 diff --git a/tests/aig/run-test.sh b/tests/aig/run-test.sh deleted file mode 100755 index 308578f01..000000000 --- a/tests/aig/run-test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! which iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" diff --git a/tests/aig/toggle-re.aag b/tests/aig/toggle-re.aag deleted file mode 100644 index b662bb386..000000000 --- a/tests/aig/toggle-re.aag +++ /dev/null @@ -1,14 +0,0 @@ -aag 7 2 1 2 4 -2 -4 -6 8 -6 -7 -8 4 10 -10 13 15 -12 2 6 -14 3 7 -i0 enable -i1 reset -o0 Q -o1 !Q diff --git a/tests/aig/toggle.aag b/tests/aig/toggle.aag deleted file mode 100644 index 09651012d..000000000 --- a/tests/aig/toggle.aag +++ /dev/null @@ -1,4 +0,0 @@ -aag 1 0 1 2 0 -2 3 -2 -3 diff --git a/tests/aig/true.aag b/tests/aig/true.aag deleted file mode 100644 index 366893648..000000000 --- a/tests/aig/true.aag +++ /dev/null @@ -1,2 +0,0 @@ -aag 0 0 0 1 0 -1 diff --git a/tests/aiger/and.aag b/tests/aiger/and.aag new file mode 100644 index 000000000..d1ef2c5a5 --- /dev/null +++ b/tests/aiger/and.aag @@ -0,0 +1,5 @@ +aag 3 2 0 1 1 +2 +4 +6 +6 2 4 diff --git a/tests/aiger/buffer.aag b/tests/aiger/buffer.aag new file mode 100644 index 000000000..94a6fb1ed --- /dev/null +++ b/tests/aiger/buffer.aag @@ -0,0 +1,3 @@ +aag 1 1 0 1 0 +2 +2 diff --git a/tests/aiger/cnt1.aag b/tests/aiger/cnt1.aag new file mode 100644 index 000000000..ce4f28fcb --- /dev/null +++ b/tests/aiger/cnt1.aag @@ -0,0 +1,3 @@ +aag 1 0 1 0 0 1 +2 3 +2 diff --git a/tests/aiger/cnt1e.aag b/tests/aiger/cnt1e.aag new file mode 100644 index 000000000..6db3f0ffd --- /dev/null +++ b/tests/aiger/cnt1e.aag @@ -0,0 +1,8 @@ +aag 5 1 1 0 3 1 +2 +4 10 +4 +6 5 3 +8 4 2 +10 9 7 +b0 AIGER_NEVER diff --git a/tests/aiger/empty.aag b/tests/aiger/empty.aag new file mode 100644 index 000000000..40c0f00cb --- /dev/null +++ b/tests/aiger/empty.aag @@ -0,0 +1 @@ +aag 0 0 0 0 0 diff --git a/tests/aiger/false.aag b/tests/aiger/false.aag new file mode 100644 index 000000000..421e64a91 --- /dev/null +++ b/tests/aiger/false.aag @@ -0,0 +1,2 @@ +aag 0 0 0 1 0 +0 diff --git a/tests/aiger/halfadder.aag b/tests/aiger/halfadder.aag new file mode 100644 index 000000000..5bf54d38d --- /dev/null +++ b/tests/aiger/halfadder.aag @@ -0,0 +1,14 @@ +aag 7 2 0 2 3 +2 +4 +6 +12 +6 13 15 +12 2 4 +14 3 5 +i0 x +i1 y +o0 s +o1 c +c +half adder diff --git a/tests/aiger/inverter.aag b/tests/aiger/inverter.aag new file mode 100644 index 000000000..ff7c28542 --- /dev/null +++ b/tests/aiger/inverter.aag @@ -0,0 +1,3 @@ +aag 1 1 0 1 0 +2 +3 diff --git a/tests/aiger/notcnt1.aag b/tests/aiger/notcnt1.aag new file mode 100644 index 000000000..e92815f23 --- /dev/null +++ b/tests/aiger/notcnt1.aag @@ -0,0 +1,4 @@ +aag 1 0 1 0 0 1 +2 3 +3 +b0 AIGER_NEVER diff --git a/tests/aiger/notcnt1e.aag b/tests/aiger/notcnt1e.aag new file mode 100644 index 000000000..141c864f7 --- /dev/null +++ b/tests/aiger/notcnt1e.aag @@ -0,0 +1,8 @@ +aag 5 1 1 0 3 1 +2 +4 10 +5 +6 5 3 +8 4 2 +10 9 7 +b0 AIGER_NEVER diff --git a/tests/aiger/or.aag b/tests/aiger/or.aag new file mode 100644 index 000000000..f780e339f --- /dev/null +++ b/tests/aiger/or.aag @@ -0,0 +1,5 @@ +aag 3 2 0 1 1 +2 +4 +7 +6 3 5 diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh new file mode 100755 index 000000000..308578f01 --- /dev/null +++ b/tests/aiger/run-test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +OPTIND=1 +seed="" # default to no seed specified +while getopts "S:" opt +do + case "$opt" in + S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space + seed="SEED=$arg" ;; + esac +done +shift "$((OPTIND-1))" + +# check for Icarus Verilog +if ! which iverilog > /dev/null ; then + echo "$0: Error: Icarus Verilog 'iverilog' not found." + exit 1 +fi + +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" diff --git a/tests/aiger/toggle-re.aag b/tests/aiger/toggle-re.aag new file mode 100644 index 000000000..b662bb386 --- /dev/null +++ b/tests/aiger/toggle-re.aag @@ -0,0 +1,14 @@ +aag 7 2 1 2 4 +2 +4 +6 8 +6 +7 +8 4 10 +10 13 15 +12 2 6 +14 3 7 +i0 enable +i1 reset +o0 Q +o1 !Q diff --git a/tests/aiger/toggle.aag b/tests/aiger/toggle.aag new file mode 100644 index 000000000..09651012d --- /dev/null +++ b/tests/aiger/toggle.aag @@ -0,0 +1,4 @@ +aag 1 0 1 2 0 +2 3 +2 +3 diff --git a/tests/aiger/true.aag b/tests/aiger/true.aag new file mode 100644 index 000000000..366893648 --- /dev/null +++ b/tests/aiger/true.aag @@ -0,0 +1,2 @@ +aag 0 0 0 1 0 +1 -- cgit v1.2.3 From 3f87cf86ccefe6e66f768fbf19c34db97cf7246d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:30:19 -0800 Subject: Revert most of autotest.sh; for non *.v use Yosys to translate --- tests/tools/autotest.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index c01ce5611..3bce003e1 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -113,16 +113,18 @@ do if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} else - cp ../$fn ${bn}_ref.${ext} + "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} + frontend="verilog" fi if [ ! -f ../${bn}_tb.v ]; then - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${ext} + "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v else cp ../${bn}_tb.v ${bn}_tb.v fi if $genvcd; then sed -i 's,// \$dump,$dump,g' ${bn}_tb.v; fi - compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs + compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs \ + "$toolsdir"/../../techlibs/common/simlib.v if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi test_count=0 @@ -143,16 +145,16 @@ do fi if [ -n "$scriptfiles" ]; then - test_passes -f "$frontend $include_opts" ${bn}_ref.${ext} $scriptfiles + test_passes -f "$frontend $include_opts" ${bn}_ref.v $scriptfiles elif [ -n "$scriptopt" ]; then - test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.${ext} + test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.v elif [ "$frontend" = "verific" ]; then test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -all; opt; memory;;" elif [ "$frontend" = "verific_gates" ]; then test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -gates -all; opt; memory;;" else - test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${ext} - test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${ext} + test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v + test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v fi touch ../${bn}.log } -- cgit v1.2.3 From 40db2f2eb61287071f59f3e15bd1cd1bf2838d1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:58:47 -0800 Subject: Refactor --- frontends/aiger/aigerparse.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c7a9aecb9..7f9feee4a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,15 +30,22 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); + void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { std::string header; f >> header; - if (header != "aag") { + if (header == "aag") + return parse_aiger_ascii(design, f, clk_name); + else { log_error("Unsupported AIGER file!\n"); return; } +} +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ int M, I, L, O, A; int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 if (!(f >> M >> I >> L >> O >> A)) { -- cgit v1.2.3 From 791f93181df091877e0b233fa21ee5fa34b24b27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 07:31:04 -0800 Subject: Stub for binary AIGER --- frontends/aiger/aigerparse.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7f9feee4a..a33110ed0 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -31,6 +31,7 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); +static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name); void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { @@ -38,10 +39,10 @@ void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) f >> header; if (header == "aag") return parse_aiger_ascii(design, f, clk_name); - else { + else if (header == "aig") + return parse_aiger_binary(design, f, clk_name); + else log_error("Unsupported AIGER file!\n"); - return; - } } static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) @@ -191,6 +192,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->fixup_ports(); } +static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ +} + struct AigerFrontend : public Frontend { AigerFrontend() : Frontend("aiger", "read AIGER file") { } void help() YS_OVERRIDE -- cgit v1.2.3 From 6dbeda1807b285ff079c15067e2f649180524c08 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:03:40 -0800 Subject: Add support for symbol tables --- frontends/aiger/aigerparse.cc | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a33110ed0..7a53bb808 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -107,6 +107,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin int l1, l2, l3; // Parse inputs + std::vector inputs; for (int i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) { log_error("Line %d cannot be interpreted as an input!\n", line_count); @@ -116,9 +117,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); wire->port_input = true; + inputs.push_back(wire); } // Parse latches + std::vector latches; for (int i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) { log_error("Line %d cannot be interpreted as a latch!\n", line_count); @@ -139,9 +142,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->addDff(NEW_ID, clk_wire, d_wire, q_wire); // AIGER latches are assumed to be initialized to zero q_wire->attributes["\\init"] = RTLIL::Const(0); + latches.push_back(q_wire); } // Parse outputs + std::vector outputs; for (int i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) { log_error("Line %d cannot be interpreted as an output!\n", line_count); @@ -151,9 +156,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); wire->port_output = true; + outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line - + // TODO: Parse bad state properties for (int i = 0; i < B; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line @@ -188,6 +194,48 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } + std::getline(f, line); // Ignore up to start of next line + + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'o') { + f.ignore(1); + if (!(f >> l1 >> s)) { + log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); + return; + } + + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) { + log_error("Line %d has invalid symbol position!\n", line_count); + return; + } + + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else log_abort(); + + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'l') { + } + else if (c == 'b' || c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + break; + } + else { + log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); + return; + } + std::getline(f, line); // Ignore up to start of next line + } module->fixup_ports(); } -- cgit v1.2.3 From 5a593ff41c44329e9a103d8c9f7a7351b1848043 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:04:48 -0800 Subject: Remove return after log_error --- frontends/aiger/aigerparse.cc | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7a53bb808..950432578 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -49,16 +49,12 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin { int M, I, L, O, A; int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - if (!(f >> M >> I >> L >> O >> A)) { + if (!(f >> M >> I >> L >> O >> A)) log_error("Invalid AIGER header\n"); - return; - } for (auto &i : std::array,4>{B, C, J, F}) { if (f.peek() != ' ') break; - if (!(f >> i)) { + if (!(f >> i)) log_error("Invalid AIGER header\n"); - return; - } } std::string line; @@ -109,10 +105,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse inputs std::vector inputs; for (int i = 0; i < I; ++i, ++line_count) { - if (!(f >> l1)) { + if (!(f >> l1)) log_error("Line %d cannot be interpreted as an input!\n", line_count); - return; - } log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -123,10 +117,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse latches std::vector latches; for (int i = 0; i < L; ++i, ++line_count) { - if (!(f >> l1 >> l2)) { + if (!(f >> l1 >> l2)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); - return; - } log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); @@ -148,10 +140,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse outputs std::vector outputs; for (int i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) { + if (!(f >> l1)) log_error("Line %d cannot be interpreted as an output!\n", line_count); - return; - } log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -178,10 +168,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse AND for (int i = 0; i < A; ++i, ++line_count) { - if (!(f >> l1 >> l2 >> l3)) { + if (!(f >> l1 >> l2 >> l3)) log_error("Line %d cannot be interpreted as an AND!\n", line_count); - return; - } log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? @@ -200,15 +188,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { if (c == 'i' || c == 'o') { f.ignore(1); - if (!(f >> l1 >> s)) { + if (!(f >> l1 >> s)) log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); - return; - } - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) { + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) log_error("Line %d has invalid symbol position!\n", line_count); - return; - } RTLIL::Wire* wire; if (c == 'i') wire = inputs[l1]; @@ -230,10 +214,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Else constraint (TODO) break; } - else { + else log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); - return; - } std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From 02f603ac1a43f3f98048c146b1950c776f73c070 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:05:27 -0800 Subject: Handle latch symbols too --- frontends/aiger/aigerparse.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 950432578..a2b2f611e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -186,7 +186,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::string s; for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'o') { + if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); if (!(f >> l1 >> s)) log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); @@ -202,8 +202,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->rename(wire, stringf("\\%s", s.c_str())); } - else if (c == 'l') { - } else if (c == 'b' || c == 'j' || c == 'f') { // TODO } -- cgit v1.2.3 From fafa972238e91f6d25bfa307a4ead4035477df18 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:08:49 -0800 Subject: Create clk outside of latch loop --- frontends/aiger/aigerparse.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a2b2f611e..abff6d8d9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -116,6 +116,15 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse latches std::vector latches; + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + clk_wire = module->wire(clk_id); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } for (int i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); @@ -123,13 +132,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); RTLIL::Wire *d_wire = createWireIfNotExists(l2); - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - RTLIL::Wire *clk_wire = module->wire(clk_id); - if (!clk_wire) { - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); - clk_wire->port_input = true; - } module->addDff(NEW_ID, clk_wire, d_wire, q_wire); // AIGER latches are assumed to be initialized to zero -- cgit v1.2.3 From 652e414392b8e9e8c7dde74e6f2c2369d8d65a20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:09:30 -0800 Subject: Change literal vars from int to unsigned --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index abff6d8d9..0414d3db3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -100,7 +100,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin return wire; }; - int l1, l2, l3; + unsigned l1, l2, l3; // Parse inputs std::vector inputs; -- cgit v1.2.3 From 5e24251a61b8798e597ac49bdc8aff2f378f625d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:37:18 -0800 Subject: Handle reset logic in latches --- frontends/aiger/aigerparse.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0414d3db3..c3cc6b321 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -134,8 +134,23 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin RTLIL::Wire *d_wire = createWireIfNotExists(l2); module->addDff(NEW_ID, clk_wire, d_wire, q_wire); - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %d cannot be interpreted as a latch!\n", line_count); + + if (l3 == 0 || l3 == 1) + q_wire->attributes["\\init"] = RTLIL::Const(0); + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %d has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } latches.push_back(q_wire); } -- cgit v1.2.3 From 36c56bf4127edc1ed0f8fbbd62bd70a859263570 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:37:44 -0800 Subject: Add comment --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c3cc6b321..56e4f3b2c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -135,6 +135,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { if (!(f >> l3)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); -- cgit v1.2.3 From 09d758f0a31e3b4290bfcd3d9864733e84c83628 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 10:54:31 -0800 Subject: Refactor to parse_aiger_header() --- frontends/aiger/aigerparse.cc | 58 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 56e4f3b2c..4c15e34d2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -45,13 +45,11 @@ void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) log_error("Unsupported AIGER file!\n"); } -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) { - int M, I, L, O, A; - int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 if (!(f >> M >> I >> L >> O >> A)) log_error("Invalid AIGER header\n"); - for (auto &i : std::array,4>{B, C, J, F}) { + for (auto &i : std::array,4>{B, C, J, F}) { if (f.peek() != ' ') break; if (!(f >> i)) log_error("Invalid AIGER header\n"); @@ -62,19 +60,27 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // says anything that follows could be used for // optional sections - log_debug("M=%d I=%d L=%d O=%d A=%d B=%d C=%d J=%d F=%d\n", M, I, L, O, A, B, C, J, F); + log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); +} + +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ + unsigned M, I, L, O, A; + unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - int line_count = 1; + unsigned line_count = 1; + std::string line; std::stringstream ss; auto module = new RTLIL::Module; module->name = RTLIL::escape_id("aig"); // TODO: Name? if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + log_error("Duplicate definition of module %s in line %u!\n", log_id(module->name), line_count); design->add(module); - auto createWireIfNotExists = [module](int literal) { - const int variable = literal >> 1; + auto createWireIfNotExists = [module](unsigned literal) { + const unsigned variable = literal >> 1; const bool invert = literal & 1; RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? RTLIL::Wire *wire = module->wire(wire_name); @@ -104,9 +110,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse inputs std::vector inputs; - for (int i = 0; i < I; ++i, ++line_count) { + for (unsigned i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) - log_error("Line %d cannot be interpreted as an input!\n", line_count); + log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -125,9 +131,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin clk_wire = module->addWire(clk_id); clk_wire->port_input = true; } - for (int i = 0; i < L; ++i, ++line_count) { + for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) - log_error("Line %d cannot be interpreted as a latch!\n", line_count); + log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); @@ -138,7 +144,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { if (!(f >> l3)) - log_error("Line %d cannot be interpreted as a latch!\n", line_count); + log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0 || l3 == 1) q_wire->attributes["\\init"] = RTLIL::Const(0); @@ -146,7 +152,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } else - log_error("Line %d has invalid reset literal for latch!\n", line_count); + log_error("Line %u has invalid reset literal for latch!\n", line_count); } else { // AIGER latches are assumed to be initialized to zero @@ -157,9 +163,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse outputs std::vector outputs; - for (int i = 0; i < O; ++i, ++line_count) { + for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) - log_error("Line %d cannot be interpreted as an output!\n", line_count); + log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -169,25 +175,25 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::getline(f, line); // Ignore up to start of next line // TODO: Parse bad state properties - for (int i = 0; i < B; ++i, ++line_count) + for (unsigned i = 0; i < B; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints - for (int i = 0; i < C; ++i, ++line_count) + for (unsigned i = 0; i < C; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse justice properties - for (int i = 0; i < J; ++i, ++line_count) + for (unsigned i = 0; i < J; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse fairness constraints - for (int i = 0; i < F; ++i, ++line_count) + for (unsigned i = 0; i < F; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // Parse AND - for (int i = 0; i < A; ++i, ++line_count) { + for (unsigned i = 0; i < A; ++i, ++line_count) { if (!(f >> l1 >> l2 >> l3)) - log_error("Line %d cannot be interpreted as an AND!\n", line_count); + log_error("Line %u cannot be interpreted as an AND!\n", line_count); log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? @@ -207,10 +213,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); if (!(f >> l1 >> s)) - log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %d has invalid symbol position!\n", line_count); + log_error("Line %u has invalid symbol position!\n", line_count); RTLIL::Wire* wire; if (c == 'i') wire = inputs[l1]; @@ -231,7 +237,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin break; } else - log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From 4e6c5e46725bb99e0c919a5f82ce5290da2ce2f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 11:41:25 -0800 Subject: Add binary AIGs converted from AAG --- tests/aiger/and.aig | 3 +++ tests/aiger/buffer.aig | 2 ++ tests/aiger/cnt1.aig | 3 +++ tests/aiger/cnt1e.aig | 4 ++++ tests/aiger/empty.aig | 1 + tests/aiger/false.aig | 2 ++ tests/aiger/halfadder.aig | 9 +++++++++ tests/aiger/inverter.aig | 2 ++ tests/aiger/notcnt1.aig | 4 ++++ tests/aiger/notcnt1e.aig | 4 ++++ tests/aiger/or.aig | 3 +++ tests/aiger/toggle-re.aig | 8 ++++++++ tests/aiger/toggle.aig | 4 ++++ tests/aiger/true.aig | 2 ++ 14 files changed, 51 insertions(+) create mode 100644 tests/aiger/and.aig create mode 100644 tests/aiger/buffer.aig create mode 100644 tests/aiger/cnt1.aig create mode 100644 tests/aiger/cnt1e.aig create mode 100644 tests/aiger/empty.aig create mode 100644 tests/aiger/false.aig create mode 100644 tests/aiger/halfadder.aig create mode 100644 tests/aiger/inverter.aig create mode 100644 tests/aiger/notcnt1.aig create mode 100644 tests/aiger/notcnt1e.aig create mode 100644 tests/aiger/or.aig create mode 100644 tests/aiger/toggle-re.aig create mode 100644 tests/aiger/toggle.aig create mode 100644 tests/aiger/true.aig diff --git a/tests/aiger/and.aig b/tests/aiger/and.aig new file mode 100644 index 000000000..da0fa0719 --- /dev/null +++ b/tests/aiger/and.aig @@ -0,0 +1,3 @@ +aig 3 2 0 1 1 +6 + \ No newline at end of file diff --git a/tests/aiger/buffer.aig b/tests/aiger/buffer.aig new file mode 100644 index 000000000..0c715fdeb --- /dev/null +++ b/tests/aiger/buffer.aig @@ -0,0 +1,2 @@ +aig 1 1 0 1 0 +2 diff --git a/tests/aiger/cnt1.aig b/tests/aiger/cnt1.aig new file mode 100644 index 000000000..8d0ba13b1 --- /dev/null +++ b/tests/aiger/cnt1.aig @@ -0,0 +1,3 @@ +aig 1 0 1 0 0 1 +3 +2 diff --git a/tests/aiger/cnt1e.aig b/tests/aiger/cnt1e.aig new file mode 100644 index 000000000..d8d159f11 --- /dev/null +++ b/tests/aiger/cnt1e.aig @@ -0,0 +1,4 @@ +aig 5 1 1 0 3 1 +10 +4 +b0 AIGER_NEVER diff --git a/tests/aiger/empty.aig b/tests/aiger/empty.aig new file mode 100644 index 000000000..a28373cd3 --- /dev/null +++ b/tests/aiger/empty.aig @@ -0,0 +1 @@ +aig 0 0 0 0 0 diff --git a/tests/aiger/false.aig b/tests/aiger/false.aig new file mode 100644 index 000000000..ad7d039fa --- /dev/null +++ b/tests/aiger/false.aig @@ -0,0 +1,2 @@ +aig 0 0 0 1 0 +0 diff --git a/tests/aiger/halfadder.aig b/tests/aiger/halfadder.aig new file mode 100644 index 000000000..83727ee63 --- /dev/null +++ b/tests/aiger/halfadder.aig @@ -0,0 +1,9 @@ +aig 5 2 0 2 3 +10 +6 +i0 x +i1 y +o0 s +o1 c +c +half adder diff --git a/tests/aiger/inverter.aig b/tests/aiger/inverter.aig new file mode 100644 index 000000000..525d82392 --- /dev/null +++ b/tests/aiger/inverter.aig @@ -0,0 +1,2 @@ +aig 1 1 0 1 0 +3 diff --git a/tests/aiger/notcnt1.aig b/tests/aiger/notcnt1.aig new file mode 100644 index 000000000..f8a667f1f --- /dev/null +++ b/tests/aiger/notcnt1.aig @@ -0,0 +1,4 @@ +aig 1 0 1 0 0 1 +3 +3 +b0 AIGER_NEVER diff --git a/tests/aiger/notcnt1e.aig b/tests/aiger/notcnt1e.aig new file mode 100644 index 000000000..7c85a7290 --- /dev/null +++ b/tests/aiger/notcnt1e.aig @@ -0,0 +1,4 @@ +aig 5 1 1 0 3 1 +10 +5 +b0 AIGER_NEVER diff --git a/tests/aiger/or.aig b/tests/aiger/or.aig new file mode 100644 index 000000000..75c9e4480 --- /dev/null +++ b/tests/aiger/or.aig @@ -0,0 +1,3 @@ +aig 3 2 0 1 1 +7 + \ No newline at end of file diff --git a/tests/aiger/toggle-re.aig b/tests/aiger/toggle-re.aig new file mode 100644 index 000000000..9d6730f21 --- /dev/null +++ b/tests/aiger/toggle-re.aig @@ -0,0 +1,8 @@ +aig 7 2 1 2 4 +14 +6 +7 +i0 enable +i1 reset +o0 Q +o1 !Q diff --git a/tests/aiger/toggle.aig b/tests/aiger/toggle.aig new file mode 100644 index 000000000..b69e21aaf --- /dev/null +++ b/tests/aiger/toggle.aig @@ -0,0 +1,4 @@ +aig 1 0 1 2 0 +3 +2 +3 diff --git a/tests/aiger/true.aig b/tests/aiger/true.aig new file mode 100644 index 000000000..10086f389 --- /dev/null +++ b/tests/aiger/true.aig @@ -0,0 +1,2 @@ +aig 0 0 0 1 0 +1 -- cgit v1.2.3 From 2a8cc36578be9a9d1645e435c3a79eb7d1abc7b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 11:45:16 -0800 Subject: Parse binary AIG files --- frontends/aiger/aigerparse.cc | 213 ++++++++++++++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 49 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4c15e34d2..4bc3918be 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,19 +30,55 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); -static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name); +static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name); +static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name); void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { + auto module = new RTLIL::Module; + module->name = RTLIL::escape_id("aig"); // TODO: Name? + if (design->module(module->name)) + log_error("Duplicate definition of module %s!\n", log_id(module->name)); + std::string header; f >> header; if (header == "aag") - return parse_aiger_ascii(design, f, clk_name); + parse_aiger_ascii(module, f, clk_name); else if (header == "aig") - return parse_aiger_binary(design, f, clk_name); + parse_aiger_binary(module, f, clk_name); else log_error("Unsupported AIGER file!\n"); + + module->fixup_ports(); + design->add(module); +} + +static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) +{ + const unsigned variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? + inv->setPort("\\A", wire_inv); + inv->setPort("\\Y", wire); + + return wire; } static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) @@ -56,14 +92,14 @@ static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsign } std::string line; - std::getline(f, line); // Ignore up to start of next ine, as standard + std::getline(f, line); // Ignore up to start of next line, as standard // says anything that follows could be used for // optional sections log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); } -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name) { unsigned M, I, L, O, A; unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 @@ -73,39 +109,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::string line; std::stringstream ss; - auto module = new RTLIL::Module; - module->name = RTLIL::escape_id("aig"); // TODO: Name? - if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %u!\n", log_id(module->name), line_count); - design->add(module); - - auto createWireIfNotExists = [module](unsigned literal) { - const unsigned variable = literal >> 1; - const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); - wire = module->addWire(wire_name); - if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); - RTLIL::Wire *wire_inv = module->wire(wire_inv_name); - if (wire_inv) { - if (module->cell(wire_inv_name)) return wire; - } - else { - log_debug("Creating %s\n", wire_inv_name.c_str()); - wire_inv = module->addWire(wire_inv_name); - } - - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? - inv->setPort("\\A", wire_inv); - inv->setPort("\\Y", wire); - - return wire; - }; - unsigned l1, l2, l3; // Parse inputs @@ -115,7 +118,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? - RTLIL::Wire *wire = createWireIfNotExists(l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_input = true; inputs.push_back(wire); } @@ -136,8 +139,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? - RTLIL::Wire *q_wire = createWireIfNotExists(l1); - RTLIL::Wire *d_wire = createWireIfNotExists(l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); module->addDff(NEW_ID, clk_wire, d_wire, q_wire); @@ -147,7 +150,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::Const(l3); else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -168,7 +171,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; outputs.push_back(wire); } @@ -197,9 +200,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(l3); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); and_cell->setPort("\\A", i1_wire); @@ -240,12 +243,124 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); std::getline(f, line); // Ignore up to start of next line } +} - module->fixup_ports(); +static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = f.get()) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return ref - (x | (ch << (7 * i))); } -static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name) { + unsigned M, I, L, O, A; + unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + parse_aiger_header(f, M, I, L, O, A, B, C, J, F); + + unsigned line_count = 1; + unsigned l1, l2, l3; + std::string line; + + // Parse inputs + std::vector inputs; + for (unsigned i = 1; i <= I; ++i) { + RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); + wire->port_input = true; + inputs.push_back(wire); + } + + // Parse latches + std::vector latches; + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + clk_wire = module->wire(clk_id); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } + l1 = (I+1) * 2; + for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { + if (!(f >> l2)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + log_debug("%d %d is a latch\n", l1, l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + + if (l3 == 0 || l3 == 1) + q_wire->attributes["\\init"] = RTLIL::Const(l3); + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } + latches.push_back(q_wire); + } + + // Parse outputs + std::vector outputs; + for (unsigned i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as an output!\n", line_count); + + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse bad state properties + for (unsigned i = 0; i < B; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // Parse AND + l1 = (I+L+1) << 1; + for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { + l2 = parse_next_delta_literal(f, l1); + l3 = parse_next_delta_literal(f, l2); + + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } + std::getline(f, line); // Ignore up to start of next line + } struct AigerFrontend : public Frontend { -- cgit v1.2.3 From f1befe1b44ada400e979f43e1b35ebe022ff8fe8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:04:26 -0800 Subject: Refactor into AigerReader class --- frontends/aiger/aigerparse.cc | 150 ++++++++++++++++++++---------------------- frontends/aiger/aigerparse.h | 21 +++++- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4bc3918be..365bf1b69 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,24 +30,84 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name); -static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name); - -void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name) + : design(design), f(f), clk_name(clk_name) { - auto module = new RTLIL::Module; + module = new RTLIL::Module; module->name = RTLIL::escape_id("aig"); // TODO: Name? if (design->module(module->name)) log_error("Duplicate definition of module %s!\n", log_id(module->name)); +} +void AigerReader::parse_aiger() +{ std::string header; f >> header; + if (header != "aag" && header != "aig") + log_error("Unsupported AIGER file!\n"); + + // Parse rest of header + if (!(f >> M >> I >> L >> O >> A)) + log_error("Invalid AIGER header\n"); + + // Optional values + B = C = J = F = 0; + for (auto &i : std::array,4>{B, C, J, F}) { + if (f.peek() != ' ') break; + if (!(f >> i)) + log_error("Invalid AIGER header\n"); + } + + std::string line; + std::getline(f, line); // Ignore up to start of next line, as standard + // says anything that follows could be used for + // optional sections + + log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); + + line_count = 1; + if (header == "aag") - parse_aiger_ascii(module, f, clk_name); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(module, f, clk_name); + parse_aiger_binary(); else - log_error("Unsupported AIGER file!\n"); + log_abort(); + + // Parse footer (symbol table, comments, etc.) + unsigned l1; + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'l' || c == 'o') { + f.ignore(1); + if (!(f >> l1 >> s)) + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); + + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) + log_error("Line %u has invalid symbol position!\n", line_count); + + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else log_abort(); + + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'b' || c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + break; + } + else + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + std::getline(f, line); // Ignore up to start of next line + } module->fixup_ports(); design->add(module); @@ -81,38 +141,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } -static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) +void AigerReader::parse_aiger_ascii() { - if (!(f >> M >> I >> L >> O >> A)) - log_error("Invalid AIGER header\n"); - for (auto &i : std::array,4>{B, C, J, F}) { - if (f.peek() != ' ') break; - if (!(f >> i)) - log_error("Invalid AIGER header\n"); - } - - std::string line; - std::getline(f, line); // Ignore up to start of next line, as standard - // says anything that follows could be used for - // optional sections - - log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); -} - -static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name) -{ - unsigned M, I, L, O, A; - unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - - unsigned line_count = 1; std::string line; std::stringstream ss; unsigned l1, l2, l3; // Parse inputs - std::vector inputs; for (unsigned i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); @@ -124,7 +160,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin } // Parse latches - std::vector latches; RTLIL::Wire *clk_wire = nullptr; if (L > 0) { RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); @@ -165,7 +200,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin } // Parse outputs - std::vector outputs; for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); @@ -210,39 +244,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line - - std::string s; - for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o') { - f.ignore(1); - if (!(f >> l1 >> s)) - log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); - - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %u has invalid symbol position!\n", line_count); - - RTLIL::Wire* wire; - if (c == 'i') wire = inputs[l1]; - else if (c == 'l') wire = latches[l1]; - else if (c == 'o') wire = outputs[l1]; - else log_abort(); - - module->rename(wire, stringf("\\%s", s.c_str())); - } - else if (c == 'b' || c == 'j' || c == 'f') { - // TODO - } - else if (c == 'c') { - f.ignore(1); - if (f.peek() == '\n') - break; - // Else constraint (TODO) - break; - } - else - log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - std::getline(f, line); // Ignore up to start of next line - } } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) @@ -254,18 +255,12 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) return ref - (x | (ch << (7 * i))); } -static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name) +void AigerReader::parse_aiger_binary() { - unsigned M, I, L, O, A; - unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - - unsigned line_count = 1; unsigned l1, l2, l3; std::string line; // Parse inputs - std::vector inputs; for (unsigned i = 1; i <= I; ++i) { RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; @@ -273,7 +268,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri } // Parse latches - std::vector latches; RTLIL::Wire *clk_wire = nullptr; if (L > 0) { RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); @@ -314,7 +308,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri } // Parse outputs - std::vector outputs; for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); @@ -385,7 +378,8 @@ struct AigerFrontend : public Frontend { } extra_args(f, filename, args, argidx); - parse_aiger(design, *f); + AigerReader reader(design, *f); + reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 6a250aa67..3e8ef09fc 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -24,7 +24,26 @@ YOSYS_NAMESPACE_BEGIN -extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); +struct AigerReader +{ + RTLIL::Design *design; + std::istream &f; + std::string clk_name; + RTLIL::Module *module; + + unsigned M, I, L, O, A; + unsigned B, C, J, F; // Optional in AIGER 1.9 + unsigned line_count; + + std::vector inputs; + std::vector latches; + std::vector outputs; + + AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + void parse_aiger(); + void parse_aiger_ascii(); + void parse_aiger_binary(); +}; YOSYS_NAMESPACE_END -- cgit v1.2.3 From fb8ad440a32da850e32765ec29119cacb3f3c27c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:40:43 -0800 Subject: Allow module name to be determined by argument too --- frontends/aiger/aigerparse.cc | 54 +++++++++++++++++++++++++++++++++---------- frontends/aiger/aigerparse.h | 4 ++-- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 365bf1b69..6ebb524bd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,11 +30,11 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name) : design(design), f(f), clk_name(clk_name) { module = new RTLIL::Module; - module->name = RTLIL::escape_id("aig"); // TODO: Name? + module->name = module_name; if (design->module(module->name)) log_error("Duplicate definition of module %s!\n", log_id(module->name)); } @@ -162,11 +162,10 @@ void AigerReader::parse_aiger_ascii() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - clk_wire = module->wire(clk_id); + clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); clk_wire->port_input = true; } for (unsigned i = 0; i < L; ++i, ++line_count) { @@ -270,11 +269,10 @@ void AigerReader::parse_aiger_binary() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - clk_wire = module->wire(clk_id); + clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); clk_wire->port_input = true; } l1 = (I+1) * 2; @@ -364,21 +362,53 @@ struct AigerFrontend : public Frontend { log("\n"); log(" read_aiger [options] [filename]\n"); log("\n"); - log("Load modules from an AIGER file into the current design.\n"); + log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -clk_name \n"); + log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); + log(" this name (default: clk)\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" +#ifdef _WIN32 + "top" // FIXME +#else + "" +#endif + ")\n"); log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing AIGER frontend.\n"); + RTLIL::IdString clk_name = "\\clk"; + RTLIL::IdString module_name; + size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; + if (arg == "-clk_name" && argidx+1 < args.size()) { + clk_name = RTLIL::escape_id(args[++argidx]); + continue; + } + if (arg == "-module_name" && argidx+1 < args.size()) { + module_name = RTLIL::escape_id(args[++argidx]); + continue; + } break; } extra_args(f, filename, args, argidx); - AigerReader reader(design, *f); + if (module_name.empty()) { +#ifdef _WIN32 + module_name = "top"; // FIXME: basename equivalent on Win32? +#else + module_name = RTLIL::escape_id(basename(filename.c_str())); +#endif + } + + AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 3e8ef09fc..39a77bd93 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -28,7 +28,7 @@ struct AigerReader { RTLIL::Design *design; std::istream &f; - std::string clk_name; + RTLIL::IdString clk_name; RTLIL::Module *module; unsigned M, I, L, O, A; @@ -39,7 +39,7 @@ struct AigerReader std::vector latches; std::vector outputs; - AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); void parse_aiger(); void parse_aiger_ascii(); void parse_aiger_binary(); -- cgit v1.2.3 From 391ec75b07cc8c10818884f19329d719847957d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:41:39 -0800 Subject: Add missing "[options]" to read_blif help --- frontends/blif/blifparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 9116b257f..a6a07863f 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -584,7 +584,7 @@ struct BlifFrontend : public Frontend { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" read_blif [filename]\n"); + log(" read_blif [options] [filename]\n"); log("\n"); log("Load modules from a BLIF file into the current design.\n"); log("\n"); -- cgit v1.2.3 From 587872236ecd1ca2f2a466bccc8d41618feb0dfb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:41:59 -0800 Subject: Support and differentiate between ASCII and binary AIG testing --- tests/aiger/run-test.sh | 6 +++++- tests/tools/autotest.sh | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 308578f01..e0a34f023 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -17,4 +17,8 @@ if ! which iverilog > /dev/null ; then exit 1 fi -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" +echo "===== AAG ======" +${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" + +echo "===== AIG ======" +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aig EXTRA_FLAGS="-f aiger" diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 3e1325b33..0ffa062e3 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -90,7 +90,7 @@ for fn do bn=${fn%.*} ext=${fn##*.} - if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]]; then + if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then echo "Invalid argument: $fn" >&2 exit 1 fi -- cgit v1.2.3 From aa66d8f12f89b457a4a23c04de706a36ee8fc114 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:49:55 -0800 Subject: -module_name arg to go before -clk_name --- frontends/aiger/aigerparse.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 6ebb524bd..5c982fb59 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -363,13 +363,13 @@ struct AigerFrontend : public Frontend { log(" read_aiger [options] [filename]\n"); log("\n"); log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" log("\n"); log(" -clk_name \n"); log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); log(" this name (default: clk)\n"); - log("\n"); - log(" -module_name \n"); - log(" Name of module to be created (default: )" #ifdef _WIN32 "top" // FIXME #else @@ -388,14 +388,14 @@ struct AigerFrontend : public Frontend { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if (arg == "-clk_name" && argidx+1 < args.size()) { - clk_name = RTLIL::escape_id(args[++argidx]); - continue; - } if (arg == "-module_name" && argidx+1 < args.size()) { module_name = RTLIL::escape_id(args[++argidx]); continue; } + if (arg == "-clk_name" && argidx+1 < args.size()) { + clk_name = RTLIL::escape_id(args[++argidx]); + continue; + } break; } extra_args(f, filename, args, argidx); -- cgit v1.2.3 From afc3c4b6139db528b58062f544fb0b098ab212b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:17:02 -0800 Subject: Fix tabulation --- frontends/aiger/aigerparse.cc | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 5c982fb59..154581179 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -237,10 +237,10 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line } @@ -345,42 +345,42 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line } struct AigerFrontend : public Frontend { - AigerFrontend() : Frontend("aiger", "read AIGER file") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_aiger [options] [filename]\n"); - log("\n"); - log("Load module from an AIGER file into the current design.\n"); + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" -module_name \n"); - log(" Name of module to be created (default: )" - log("\n"); - log(" -clk_name \n"); - log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); - log(" this name (default: clk)\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" #ifdef _WIN32 "top" // FIXME #else "" #endif ")\n"); - log("\n"); - } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing AIGER frontend.\n"); + log("\n"); + log(" -clk_name \n"); + log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); + log(" this name (default: clk)\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); RTLIL::IdString clk_name = "\\clk"; RTLIL::IdString module_name; @@ -410,7 +410,7 @@ struct AigerFrontend : public Frontend { AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); - } + } } AigerFrontend; YOSYS_NAMESPACE_END -- cgit v1.2.3 From 8886fa5506b227229398e5ac884203e799bce22c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:17:53 -0800 Subject: addDff -> addDffGate as per @daveshah1 --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 154581179..c45de8531 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -176,7 +176,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { -- cgit v1.2.3 From bb4164481d8b6eeec6bbc6f5b36f1286ada51eb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 11:51:44 -0800 Subject: Do not ignore newline after AND in binary AIG --- frontends/aiger/aigerparse.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c45de8531..ed91b6990 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -242,7 +242,6 @@ void AigerReader::parse_aiger_ascii() and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } - std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) -- cgit v1.2.3 From 727ba52504c65be1fcda9b03f6c2e1498e10061d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 13:24:21 -0800 Subject: No increment line_count for binary ANDs --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ed91b6990..096e269b2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -227,7 +227,7 @@ void AigerReader::parse_aiger_ascii() std::getline(f, line); // Ignore up to start of next line // Parse AND - for (unsigned i = 0; i < A; ++i, ++line_count) { + for (unsigned i = 0; i < A; ++i) { if (!(f >> l1 >> l2 >> l3)) log_error("Line %u cannot be interpreted as an AND!\n", line_count); -- cgit v1.2.3 From 04c580fde7a0d1d50c2d93bb6661b3f17a7d61a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 13:28:00 -0800 Subject: Do not break for constraints --- frontends/aiger/aigerparse.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 096e269b2..1e13e1124 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -102,7 +102,6 @@ void AigerReader::parse_aiger() if (f.peek() == '\n') break; // Else constraint (TODO) - break; } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); -- cgit v1.2.3 From a2ae39381124ccfec348293c7c7926597c26a5b8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 09:21:15 -0800 Subject: Use module->add{Not,And}Gate() functions --- frontends/aiger/aigerparse.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c45de8531..888a4afe6 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -134,9 +134,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? - inv->setPort("\\A", wire_inv); - inv->setPort("\\Y", wire); + module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? return wire; } @@ -236,11 +234,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); } std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From c23e3f07517d4818d9ab1b532250353492cf50c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 09:24:13 -0800 Subject: Missing headers for Xcode? --- passes/techmap/abc.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index d2d15a4a9..b215b1ea4 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -52,6 +52,8 @@ #include #include #include +#include +#include #ifndef _WIN32 # include -- cgit v1.2.3 From 430a7548bca6046c812f713877253f8c3d81d805 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 11:50:55 -0800 Subject: One more merge conflict --- tests/tools/autotest.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 2722cba19..b5abc3570 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -134,18 +134,13 @@ do fn=$(basename $fn) bn=$(basename $bn) -<<<<<<< HEAD + rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} else "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} frontend="verilog" fi -======= - rm -f ${bn}_ref.fir - - egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.v ->>>>>>> e45f62b0c56717a23099425f078d1e56212aa632 if [ ! -f ../${bn}_tb.v ]; then "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v -- cgit v1.2.3 From 9268a271fb8b22b089927d63f0b36d620e19704c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 12:07:14 -0800 Subject: read_aiger to ignore line after ands for ascii, not binary --- frontends/aiger/aigerparse.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7df28fe87..a1a0a08a0 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -235,6 +235,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); } + std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) @@ -342,8 +343,6 @@ void AigerReader::parse_aiger_binary() and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } - std::getline(f, line); // Ignore up to start of next line - } struct AigerFrontend : public Frontend { -- cgit v1.2.3 From de1dc7947b3d4bfc4e611740a906915a0c2490b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 20:59:15 -0800 Subject: Revert "Missing headers for Xcode?" This reverts commit c23e3f07517d4818d9ab1b532250353492cf50c2. --- passes/techmap/abc.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index b215b1ea4..d2d15a4a9 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -52,8 +52,6 @@ #include #include #include -#include -#include #ifndef _WIN32 # include -- cgit v1.2.3 From 8e1dbfac3af64339f021ed674bdd98e71cd7fb90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 20:59:53 -0800 Subject: Missing OSX headers? --- frontends/aiger/aigerparse.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a1a0a08a0..778b8b070 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,6 +22,11 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf +#ifdef __linux__ +#include +#endif +#include + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "aigerparse.h" -- cgit v1.2.3 From 843e7fc8a70b7510ae8dfbad2c9f66d2d64d0e64 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 09:02:37 -0800 Subject: Fix for using POSIX basename --- frontends/aiger/aigerparse.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 778b8b070..cf7950c85 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,7 +22,7 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf -#ifdef __linux__ +#ifndef _WIN32 #include #endif #include @@ -400,7 +400,9 @@ struct AigerFrontend : public Frontend { #ifdef _WIN32 module_name = "top"; // FIXME: basename equivalent on Win32? #else - module_name = RTLIL::escape_id(basename(filename.c_str())); + char* bn = strdup(filename.c_str()); + module_name = RTLIL::escape_id(bn); + free(bn); #endif } -- cgit v1.2.3 From d365682a21147b6a06d9548a6f4b99d347931441 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 15:25:47 -0800 Subject: Add aiger tests to make tests --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d83a71256..4324b2eec 100644 --- a/Makefile +++ b/Makefile @@ -580,6 +580,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/sat && bash run-test.sh +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +cd tests/opt && bash run-test.sh + +cd tests/aiger && bash run-test.sh @echo "" @echo " Passed \"make test\"." @echo "" -- cgit v1.2.3 From 3e89cf68bdc4e9eeb55bd9450121f421bcdc554a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 08:52:06 -0700 Subject: Add author name --- frontends/aiger/aigerparse.h | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 39a77bd93..c49cd152d 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3