From 0caa62802ccb3ee67e05c948a9e334504cae9cc4 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 6 Jul 2018 01:36:41 -0400 Subject: Gate POSIX-only signals and resource module to only run on POSIX Python implementations. --- backends/smt2/smtio.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 1a8d2484c..3fc823e3e 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -17,7 +17,9 @@ # import sys, re, os, signal -import resource, subprocess +import subprocess +if os.name == "posix": + import resource from copy import deepcopy from select import select from time import time @@ -27,12 +29,13 @@ from threading import Thread # This is needed so that the recursive SMT2 S-expression parser # does not run out of stack frames when parsing large expressions -smtio_reclimit = 64 * 1024 -smtio_stacksize = 128 * 1024 * 1024 -if sys.getrecursionlimit() < smtio_reclimit: - sys.setrecursionlimit(smtio_reclimit) -if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1)) +if os.name == "posix": + smtio_reclimit = 64 * 1024 + smtio_stacksize = 128 * 1024 * 1024 + if sys.getrecursionlimit() < smtio_reclimit: + sys.setrecursionlimit(smtio_reclimit) + if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize: + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1)) # currently running solvers (so we can kill them) @@ -51,8 +54,9 @@ def force_shutdown(signum, frame): os.kill(p.pid, signal.SIGTERM) sys.exit(1) +if os.name == "posix": + signal.signal(signal.SIGHUP, force_shutdown) signal.signal(signal.SIGINT, force_shutdown) -signal.signal(signal.SIGHUP, force_shutdown) signal.signal(signal.SIGTERM, force_shutdown) def except_hook(exctype, value, traceback): @@ -1053,4 +1057,3 @@ class MkVcd: print("b0 %s" % self.nets[path][0], file=self.f) else: print("b1 %s" % self.nets[path][0], file=self.f) - -- cgit v1.2.3 From 3aa4484a3cd9a2e82fddd499cde575eaf8c565cc Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Fri, 20 Jul 2018 23:41:18 -0700 Subject: Consistent use of 'override' for virtual methods in derived classes. o Not all derived methods were marked 'override', but it is a great feature of C++11 that we should make use of. o While at it: touched header files got a -*- c++ -*- for emacs to provide support for that language. o use YS_OVERRIDE for all override keywords (though we should probably use the plain keyword going forward now that C++11 is established) --- backends/aiger/aiger.cc | 4 ++-- backends/blif/blif.cc | 4 ++-- backends/btor/btor.cc | 4 ++-- backends/edif/edif.cc | 4 ++-- backends/firrtl/firrtl.cc | 4 ++-- backends/ilang/ilang_backend.cc | 8 ++++---- backends/intersynth/intersynth.cc | 4 ++-- backends/json/json.cc | 8 ++++---- backends/protobuf/protobuf.cc | 8 ++++---- backends/simplec/simplec.cc | 4 ++-- backends/smt2/smt2.cc | 4 ++-- backends/smv/smv.cc | 4 ++-- backends/spice/spice.cc | 4 ++-- backends/table/table.cc | 4 ++-- backends/verilog/verilog_backend.cc | 4 ++-- 15 files changed, 36 insertions(+), 36 deletions(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 526e50a49..c323691a3 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -657,7 +657,7 @@ struct AigerWriter struct AigerBackend : public Backend { AigerBackend() : Backend("aiger", "write design to AIGER file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -690,7 +690,7 @@ struct AigerBackend : public Backend { log(" like -map, but more verbose\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; bool zinit_mode = false; diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index e4509e0d0..0db5ff27c 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -464,7 +464,7 @@ struct BlifDumper struct BlifBackend : public Backend { BlifBackend() : Backend("blif", "write design to BLIF file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -534,7 +534,7 @@ struct BlifBackend : public Backend { log(" do not write definitions for the $true, $false and $undef wires.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string top_module_name; std::string buf_type, buf_in, buf_out; diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 61a2f8ba3..58d2a8625 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -1076,7 +1076,7 @@ struct BtorWorker struct BtorBackend : public Backend { BtorBackend() : Backend("btor", "write design to BTOR file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1091,7 +1091,7 @@ struct BtorBackend : public Backend { log(" Output only a single bad property for all asserts\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool verbose = false, single_bad = false; diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index a6534b911..5f9ec54fd 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -90,7 +90,7 @@ struct EdifNames struct EdifBackend : public Backend { EdifBackend() : Backend("edif", "write design to EDIF netlist file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -116,7 +116,7 @@ struct EdifBackend : public Backend { log("is targeted.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing EDIF backend.\n"); std::string top_module_name; diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 06cbc9b2b..4f56f498c 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -527,7 +527,7 @@ struct FirrtlWorker struct FirrtlBackend : public Backend { FirrtlBackend() : Backend("firrtl", "write design to a FIRRTL file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -536,7 +536,7 @@ struct FirrtlBackend : public Backend { log("Write a FIRRTL netlist of the current design.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 1f7f12361..4c58ea087 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -382,7 +382,7 @@ PRIVATE_NAMESPACE_BEGIN struct IlangBackend : public Backend { IlangBackend() : Backend("ilang", "write design to ilang file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -395,7 +395,7 @@ struct IlangBackend : public Backend { log(" only write selected parts of the design.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool selected = false; @@ -422,7 +422,7 @@ struct IlangBackend : public Backend { struct DumpPass : public Pass { DumpPass() : Pass("dump", "print parts of the design in ilang format") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -445,7 +445,7 @@ struct DumpPass : public Pass { log(" like -outfile but append instead of overwrite\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool flag_m = false, flag_n = false, append = false; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 34cb52fb4..2eb08dbe9 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -46,7 +46,7 @@ static std::string netname(std::set &conntypes_code, std::set args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing INTERSYNTH backend.\n"); log_push(); diff --git a/backends/json/json.cc b/backends/json/json.cc index d3b7077a2..5a87859a0 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -250,7 +250,7 @@ struct JsonWriter struct JsonBackend : public Backend { JsonBackend() : Backend("json", "write design to a JSON file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -458,7 +458,7 @@ struct JsonBackend : public Backend { log("format. A program processing this format must ignore all unknown fields.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool aig_mode = false; @@ -482,7 +482,7 @@ struct JsonBackend : public Backend { struct JsonPass : public Pass { JsonPass() : Pass("json", "write design in JSON format") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -499,7 +499,7 @@ struct JsonPass : public Pass { log("See 'help write_json' for a description of the JSON format used.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool aig_mode = false; diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index 9a6fedee7..f56147cef 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -231,7 +231,7 @@ struct ProtobufDesignSerializer struct ProtobufBackend : public Backend { ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -249,7 +249,7 @@ struct ProtobufBackend : public Backend { log("Yosys source code distribution.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool aig_mode = false; bool text_mode = false; @@ -286,7 +286,7 @@ struct ProtobufBackend : public Backend { struct ProtobufPass : public Pass { ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -307,7 +307,7 @@ struct ProtobufPass : public Pass { log("Yosys source code distribution.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string filename; bool aig_mode = false; diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index c9656caff..349bc5a6d 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -742,7 +742,7 @@ struct SimplecWorker struct SimplecBackend : public Backend { SimplecBackend() : Backend("simplec", "convert design to simple C code") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -761,7 +761,7 @@ struct SimplecBackend : public Backend { log("THIS COMMAND IS UNDER CONSTRUCTION\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { reserved_cids.clear(); id2cid.clear(); diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index ca1ceacc7..e2777ae04 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1251,7 +1251,7 @@ struct Smt2Worker struct Smt2Backend : public Backend { Smt2Backend() : Backend("smt2", "write design to SMT-LIBv2 file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1407,7 +1407,7 @@ struct Smt2Backend : public Backend { log("from non-zero to zero in the test design.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::ifstream template_f; bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false, statedt = false; diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index 768969e6b..b8383412b 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -675,7 +675,7 @@ struct SmvWorker struct SmvBackend : public Backend { SmvBackend() : Backend("smv", "write design to SMV file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -693,7 +693,7 @@ struct SmvBackend : public Backend { log("THIS COMMAND IS UNDER CONSTRUCTION\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::ifstream template_f; bool verbose = false; diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 4101cbf98..b6a3f1e77 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -132,7 +132,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De struct SpiceBackend : public Backend { SpiceBackend() : Backend("spice", "write design to SPICE netlist file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -161,7 +161,7 @@ struct SpiceBackend : public Backend { log(" set the specified module as design top module\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string top_module_name; RTLIL::Module *top_module = NULL; diff --git a/backends/table/table.cc b/backends/table/table.cc index 27b7edfff..979273dd3 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN struct TableBackend : public Backend { TableBackend() : Backend("table", "write design as connectivity table") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -48,7 +48,7 @@ struct TableBackend : public Backend { log("module inputs and outputs are output using cell type and port '-' and with\n"); log("'pi' (primary input) or 'po' (primary output) or 'pio' as direction.\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing TABLE backend.\n"); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index b50dc12af..44e4e5f97 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1482,7 +1482,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) struct VerilogBackend : public Backend { VerilogBackend() : Backend("verilog", "write design to Verilog file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1550,7 +1550,7 @@ struct VerilogBackend : public Backend { log("this command is called on a design with RTLIL processes.\n"); log("\n"); } - virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing Verilog backend.\n"); -- cgit v1.2.3 From 7db05b2cc1befba7e9d7afbb270dd503e8ec5857 Mon Sep 17 00:00:00 2001 From: jpathy <15735913+jpathy@users.noreply.github.com> Date: Mon, 6 Aug 2018 06:51:07 +0000 Subject: Use `realpath` Use `os.path.realpath` instead to make sure symlinks are followed. This is also required to work for nix package manager. --- backends/smt2/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc index eacda2734..dce82f01a 100644 --- a/backends/smt2/Makefile.inc +++ b/backends/smt2/Makefile.inc @@ -6,7 +6,7 @@ ifneq ($(CONFIG),emcc) TARGETS += yosys-smtbmc yosys-smtbmc: backends/smt2/smtbmc.py - $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(__file__) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new + $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new $(Q) chmod +x $@.new $(Q) mv $@.new $@ -- cgit v1.2.3 From 1dd156f5167d9949eccb7abcbc65d9bc74f49ee8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 14 Aug 2018 23:31:25 +0200 Subject: Fix use of signed integers in JSON back-end Signed-off-by: Clifford Wolf --- backends/json/json.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index d3b7077a2..1a3ca64a3 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -93,8 +93,10 @@ struct JsonWriter f << get_string(param.second.decode_string()); else if (GetSize(param.second.bits) > 32) f << get_string(param.second.as_string()); - else + else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0) f << stringf("%d", param.second.as_int()); + else + f << stringf("%u", param.second.as_int()); first = false; } } -- cgit v1.2.3 From 93d19dc2fb35335607e67cab8ecf5ebe28268a1f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 23 Aug 2018 14:35:11 -0700 Subject: Add support for module instances. Don't pad logical operands to one bit. Use operand width and signedness in $reduce_bool. Shift amounts are unsigned and shouldn't be padded. Group "is invalid" with the wire declaration, not its use (otherwise it is incorrectly wired to 0). --- backends/firrtl/firrtl.cc | 139 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 17 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 4f56f498c..14fae1a83 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -28,10 +28,32 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +bool defparam, noattr; pool used_names; dict namecache; int autoid_counter; +typedef unsigned FDirection; +static const FDirection NODIRECTION = 0x0; +static const FDirection IN = 0x1; +static const FDirection OUT = 0x2; +static const FDirection INOUT = 0x3; + +// Get a port direction with respect to a specific module. +FDirection getPortFDirection(IdString id, Module *module) +{ + Wire *wire = module->wires_.at(id); + FDirection direction = NODIRECTION; + if (wire && wire->port_id) + { + if (wire->port_input) + direction |= IN; + if (wire->port_output) + direction |= OUT; + } + return direction; +} + string next_id() { string new_id; @@ -77,6 +99,8 @@ struct FirrtlWorker dict> reverse_wire_map; string unconn_id; + RTLIL::Design *design; + std::string indent; void register_reverse_wire_map(string id, SigSpec sig) { @@ -84,11 +108,11 @@ struct FirrtlWorker reverse_wire_map[sig[i]] = make_pair(id, i); } - FirrtlWorker(Module *module, std::ostream &f) : module(module), f(f) + FirrtlWorker(Module *module, std::ostream &f, RTLIL::Design *theDesign) : module(module), f(f), design(theDesign), indent(" ") { } - string make_expr(SigSpec sig) + string make_expr(const SigSpec &sig) { string expr; @@ -135,6 +159,74 @@ struct FirrtlWorker return expr; } + std::string fid(RTLIL::IdString internal_id) + { + const char *str = internal_id.c_str(); + return *str == '\\' ? str + 1 : str; + } + + + std::string cellname(RTLIL::Cell *cell) + { + return fid(cell->name).c_str(); + } + + void process_instance(RTLIL::Cell *cell, vector &wire_exprs) + { + // TODO: Deal with cell attributes + if (!noattr && !cell->attributes.empty()) { + + } + std::string cell_type = fid(cell->type); + + // TODO: Deal with cell parameters + if (!defparam && cell->parameters.size() > 0) { + + } + + std::string cell_name = cellname(cell); + std::string cell_name_comment; + if (cell_name != fid(cell->name)) + cell_name_comment = " /* " + fid(cell->name) + " */ "; + else + cell_name_comment = ""; + // Find the module corresponding to this instance. + auto instModule = design->module(cell->type); + wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), cell_type.c_str())); + + for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { + if (it->second.size() > 0) { + const SigSpec &secondSig = it->second; + const std::string firstName = cell_name + "." + make_id(it->first); + const std::string secondName = make_expr(secondSig); + // Find the direction for this port. + FDirection dir = getPortFDirection(it->first, instModule); + std::string source, sink; + switch (dir) { + case INOUT: + log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second)); + case OUT: + source = firstName; + sink = secondName; + break; + case NODIRECTION: + log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second)); + /* FALL_THROUGH */ + case IN: + source = secondName; + sink = firstName; + break; + default: + log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", log_id(cell_type), log_signal(it->second), dir); + break; + } + wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); + } + } + wire_exprs.push_back(stringf("\n")); + + } + void run() { f << stringf(" module %s:\n", make_id(module->name)); @@ -142,21 +234,28 @@ struct FirrtlWorker for (auto wire : module->wires()) { + const auto wireName = make_id(wire->name); if (wire->port_id) { if (wire->port_input && wire->port_output) log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); port_decls.push_back(stringf(" %s %s: UInt<%d>\n", wire->port_input ? "input" : "output", - make_id(wire->name), wire->width)); + wireName, wire->width)); } else { - wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", make_id(wire->name), wire->width)); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", wireName, wire->width)); } } for (auto cell : module->cells()) { + // Is this cell is a module instance? + if (cell->type[0] != '$') + { + process_instance(cell, wire_exprs); + continue; + } if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { string y_id = make_id(cell->name); @@ -169,7 +268,10 @@ struct FirrtlWorker a_expr = "asSInt(" + a_expr + ")"; } - a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + // Don't use the results of logical operations (a single bit) to control padding + if (!(cell->type.in("$eq", "$eqx", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$reduce_bool", "$logic_not") && y_width == 1) ) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + } string primop; bool always_uint = false; @@ -187,9 +289,12 @@ struct FirrtlWorker a_expr = stringf("xorr(%s)", a_expr.c_str()); } if (cell->type == "$reduce_bool") { - primop = "neq"; - a_expr = stringf("%s, UInt(0)", a_expr.c_str()); - } + primop = "neq"; + // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. + bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool(); + int a_width = cell->parameters.at("\\A_WIDTH").as_int(); + a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width); + } string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str()); @@ -215,16 +320,16 @@ struct FirrtlWorker if (cell->parameters.at("\\A_SIGNED").as_bool()) { a_expr = "asSInt(" + a_expr + ")"; } - if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type != "$shr")) { - b_expr = "asSInt(" + b_expr + ")"; + // Shift amount is always unsigned, and needn't be padded to result width. + if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { + if (cell->parameters.at("\\B_SIGNED").as_bool()) { + b_expr = "asSInt(" + b_expr + ")"; + } + b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); } a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); - if ((cell->type != "$shl") && (cell->type != "$sshl")) { - b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); - } - if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { a_expr = "asUInt(" + a_expr + ")"; } @@ -494,14 +599,14 @@ struct FirrtlWorker if (is_valid) { if (make_unconn_id) { wire_decls.push_back(stringf(" wire %s: UInt<1>\n", unconn_id.c_str())); - cell_exprs.push_back(stringf(" %s is invalid\n", unconn_id.c_str())); + wire_decls.push_back(stringf(" %s is invalid\n", unconn_id.c_str())); } wire_exprs.push_back(stringf(" %s <= %s\n", make_id(wire->name), expr.c_str())); } else { if (make_unconn_id) { unconn_id.clear(); } - wire_exprs.push_back(stringf(" %s is invalid\n", make_id(wire->name))); + wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name))); } } @@ -570,7 +675,7 @@ struct FirrtlBackend : public Backend { for (auto module : design->modules()) { - FirrtlWorker worker(module, *f); + FirrtlWorker worker(module, *f, design); worker.run(); } -- cgit v1.2.3 From 380c6f0e978869099d5b2c5dd81d8065a1f5c3cc Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 27 Aug 2018 10:18:33 -0700 Subject: Remove unused functions. --- backends/firrtl/firrtl.cc | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 14fae1a83..94236d0b1 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -28,7 +28,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool defparam, noattr; pool used_names; dict namecache; int autoid_counter; @@ -173,17 +172,8 @@ struct FirrtlWorker void process_instance(RTLIL::Cell *cell, vector &wire_exprs) { - // TODO: Deal with cell attributes - if (!noattr && !cell->attributes.empty()) { - - } std::string cell_type = fid(cell->type); - // TODO: Deal with cell parameters - if (!defparam && cell->parameters.size() > 0) { - - } - std::string cell_name = cellname(cell); std::string cell_name_comment; if (cell_name != fid(cell->name)) -- cgit v1.2.3 From 12440fcc8f705c117b5f91fae24b7e5c4fbf8560 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Sep 2018 00:18:01 +0200 Subject: Add $lut support to Verilog back-end Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 44e4e5f97..d3262ec47 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -779,6 +779,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type == "$lut") + { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + dump_const(f, cell->parameters.at("\\LUT")); + f << stringf(" >> "); + dump_attributes(f, "", cell->attributes, ' '); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(";\n"); + return true; + } + if (cell->type == "$dffsr") { SigSpec sig_clk = cell->getPort("\\CLK"); -- cgit v1.2.3 From efac8a45a6965bdcbb7fb810d657d2c63b6cb7fe Mon Sep 17 00:00:00 2001 From: acw1251 Date: Tue, 18 Sep 2018 13:34:30 -0400 Subject: Fixed typo in "verilog_write" help message --- backends/verilog/verilog_backend.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index d3262ec47..ae9031510 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1523,7 +1523,7 @@ struct VerilogBackend : public Backend { log("\n"); log(" -nodec\n"); log(" 32-bit constant values are by default dumped as decimal numbers,\n"); - log(" not bit pattern. This option decativates this feature and instead\n"); + log(" not bit pattern. This option deactivates this feature and instead\n"); log(" will write out all constants in binary.\n"); log("\n"); log(" -decimal\n"); @@ -1531,13 +1531,13 @@ struct VerilogBackend : public Backend { log("\n"); log(" -nohex\n"); log(" constant values that are compatible with hex output are usually\n"); - log(" dumped as hex values. This option decativates this feature and\n"); + log(" dumped as hex values. This option deactivates this feature and\n"); log(" instead will write out all constants in binary.\n"); log("\n"); log(" -nostr\n"); log(" Parameters and attributes that are specified as strings in the\n"); log(" original input will be output as strings by this back-end. This\n"); - log(" decativates this feature and instead will write string constants\n"); + log(" deactivates this feature and instead will write string constants\n"); log(" as binary numbers.\n"); log("\n"); log(" -defparam\n"); -- cgit v1.2.3 From 41affeeeb9935db73bb2774e74e6038a70cf667d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Sep 2018 20:43:49 +0200 Subject: added prefix to FDirection constants, fixing windows build --- backends/firrtl/firrtl.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 94236d0b1..32410a651 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -33,22 +33,22 @@ dict namecache; int autoid_counter; typedef unsigned FDirection; -static const FDirection NODIRECTION = 0x0; -static const FDirection IN = 0x1; -static const FDirection OUT = 0x2; -static const FDirection INOUT = 0x3; +static const FDirection FD_NODIRECTION = 0x0; +static const FDirection FD_IN = 0x1; +static const FDirection FD_OUT = 0x2; +static const FDirection FD_INOUT = 0x3; // Get a port direction with respect to a specific module. FDirection getPortFDirection(IdString id, Module *module) { Wire *wire = module->wires_.at(id); - FDirection direction = NODIRECTION; + FDirection direction = FD_NODIRECTION; if (wire && wire->port_id) { if (wire->port_input) - direction |= IN; + direction |= FD_IN; if (wire->port_output) - direction |= OUT; + direction |= FD_OUT; } return direction; } @@ -193,16 +193,16 @@ struct FirrtlWorker FDirection dir = getPortFDirection(it->first, instModule); std::string source, sink; switch (dir) { - case INOUT: + case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second)); - case OUT: + case FD_OUT: source = firstName; sink = secondName; break; - case NODIRECTION: + case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second)); /* FALL_THROUGH */ - case IN: + case FD_IN: source = secondName; sink = firstName; break; -- cgit v1.2.3 From 90e0938f9a94464ac48a8fd4acdfbf805216b763 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Mon, 1 Oct 2018 19:03:10 -0400 Subject: Update to .smv backend Splitting VAR and ASSIGN into IVAR, VAR, DEFINE and ASSIGN. This allows better handling by nuXmv for post-processing (since now only state variables are listed under VAR). --- backends/smv/smv.cc | 85 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 33 deletions(-) (limited to 'backends') diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index b8383412b..a53ee7a7c 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -42,7 +42,7 @@ struct SmvWorker pool partial_assignment_wires; dict> partial_assignment_bits; - vector assignments, invarspecs; + vector inputvars, vars, definitions, assignments, invarspecs; const char *cid() { @@ -195,7 +195,7 @@ struct SmvWorker return rvalue(sig); const char *temp_id = cid(); - f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig)); +// f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig)); int offset = 0; for (auto bit : sig) { @@ -210,14 +210,14 @@ struct SmvWorker void run() { f << stringf("MODULE %s\n", cid(module->name)); - f << stringf(" VAR\n"); for (auto wire : module->wires()) { if (SigSpec(wire) != sigmap(wire)) partial_assignment_wires.insert(wire); - f << stringf(" %s : unsigned word[%d]; -- %s\n", cid(wire->name), wire->width, log_id(wire)); + if (wire->port_input) + inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire))); if (wire->attributes.count("\\init")) assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at("\\init")))); @@ -232,7 +232,7 @@ struct SmvWorker SigSpec sig_a = cell->getPort("\\A"); SigSpec sig_en = cell->getPort("\\EN"); - invarspecs.push_back(stringf("!bool(%s) | bool(%s);", rvalue(sig_en), rvalue(sig_a))); + invarspecs.push_back(stringf("(!bool(%s) | bool(%s));", rvalue(sig_en), rvalue(sig_a))); continue; } @@ -275,8 +275,8 @@ struct SmvWorker const char *b_shr = rvalue_u(sig_b); const char *b_shl = cid(); - f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b)); - assignments.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b))); +// f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b)); + definitions.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b))); string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a.c_str(), b_shl, shift_b_width-1, width_y); string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a.c_str(), b_shr, shift_b_width-1, width_y); @@ -303,7 +303,7 @@ struct SmvWorker GetSize(sig_b)-shift_b_width, width_y, expr.c_str()); } - assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } @@ -319,12 +319,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue_s(cell->getPort("\\A"), width))); } else { - assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue_u(cell->getPort("\\A"), width))); } @@ -346,12 +346,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")), rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width))); } else { - assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width))); } @@ -370,12 +370,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width), width_y)); } else { - assignments.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")), rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width), width_y)); } @@ -407,7 +407,7 @@ struct SmvWorker expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort("\\B")), width); } - assignments.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort("\\Y")))); continue; @@ -425,7 +425,7 @@ struct SmvWorker if (cell->type == "$reduce_or") expr = stringf("%s != 0ub%d_0", expr_a, width_a); if (cell->type == "$reduce_bool") expr = stringf("%s != 0ub%d_0", expr_a, width_a); - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -444,7 +444,7 @@ struct SmvWorker if (cell->type == "$reduce_xnor") expr = "!(" + expr + ")"; - assignments.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -462,7 +462,7 @@ struct SmvWorker if (cell->type == "$logic_and") expr = expr_a + " & " + expr_b; if (cell->type == "$logic_or") expr = expr_a + " | " + expr_b; - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -474,7 +474,7 @@ struct SmvWorker string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a); const char *expr_y = lvalue(cell->getPort("\\Y")); - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y)); continue; } @@ -490,12 +490,13 @@ struct SmvWorker expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width))); expr += rvalue(sig_a); - assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } if (cell->type == "$dff") { + vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort("\\Q")), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")))); assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort("\\Q")), rvalue(cell->getPort("\\D")))); continue; } @@ -503,7 +504,7 @@ struct SmvWorker if (cell->type.in("$_BUF_", "$_NOT_")) { string op = cell->type == "$_NOT_" ? "!" : ""; - assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A")))); + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A")))); continue; } @@ -517,49 +518,49 @@ struct SmvWorker if (cell->type.in("$_XNOR_")) op = "xnor"; if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) - assignments.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else if (cell->type.in("$_NAND_", "$_NOR_")) - assignments.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else - assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); continue; } if (cell->type == "$_MUX_") { - assignments.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A")))); continue; } if (cell->type == "$_AOI3_") { - assignments.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } if (cell->type == "$_OAI3_") { - assignments.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } if (cell->type == "$_AOI4_") { - assignments.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } if (cell->type == "$_OAI4_") { - assignments.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } @@ -567,13 +568,13 @@ struct SmvWorker if (cell->type[0] == '$') log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell)); - f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); +// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); for (auto &conn : cell->connections()) if (cell->output(conn.first)) - assignments.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first))); + definitions.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first))); else - assignments.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second))); + definitions.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second))); } for (Wire *wire : partial_assignment_wires) @@ -657,7 +658,25 @@ struct SmvWorker } } - assignments.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str())); + definitions.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str())); + } + + if (!inputvars.empty()) { + f << stringf(" IVAR\n"); + for (const string &line : inputvars) + f << stringf(" %s\n", line.c_str()); + } + + if (!vars.empty()) { + f << stringf(" VAR\n"); + for (const string &line : vars) + f << stringf(" %s\n", line.c_str()); + } + + if (!definitions.empty()) { + f << stringf(" DEFINE\n"); + for (const string &line : definitions) + f << stringf(" %s\n", line.c_str()); } if (!assignments.empty()) { -- cgit v1.2.3 From 115ca576475a2e8d30e63b339ae6a1b5db6906a6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 5 Oct 2018 09:41:18 +0200 Subject: Add "write_edif -attrprop" Signed-off-by: Clifford Wolf --- backends/edif/edif.cc | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'backends') diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 5f9ec54fd..d4e56a9eb 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -106,6 +106,9 @@ struct EdifBackend : public Backend { log(" if the design contains constant nets. use \"hilomap\" to map to custom\n"); log(" constant drivers first)\n"); log("\n"); + log(" -attrprop\n"); + log(" create EDIF properties for cell attributes\n"); + log("\n"); log(" -pvector {par|bra|ang}\n"); log(" sets the delimiting character for module port rename clauses to\n"); log(" parentheses, square brackets, or angle brackets.\n"); @@ -121,6 +124,7 @@ struct EdifBackend : public Backend { log_header(design, "Executing EDIF backend.\n"); std::string top_module_name; bool port_rename = false; + bool attr_properties = false; std::map> lib_cell_ports; bool nogndvcc = false; CellTypes ct(design); @@ -137,6 +141,10 @@ struct EdifBackend : public Backend { nogndvcc = true; continue; } + if (args[argidx] == "-attrprop") { + attr_properties = true; + continue; + } if (args[argidx] == "-pvector" && argidx+1 < args.size()) { std::string parray; port_rename = true; @@ -332,24 +340,33 @@ struct EdifBackend : public Backend { *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); - for (auto &p : cell->parameters) - if ((p.second.flags & RTLIL::CONST_FLAG_STRING) != 0) - *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(p.first), p.second.decode_string().c_str()); - else if (p.second.bits.size() <= 32 && RTLIL::SigSpec(p.second).is_fully_def()) - *f << stringf("\n (property %s (integer %u))", EDIF_DEF(p.first), p.second.as_int()); + + auto add_prop = [&](IdString name, Const val) { + if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); + else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) + *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); else { std::string hex_string = ""; - for (size_t i = 0; i < p.second.bits.size(); i += 4) { + for (size_t i = 0; i < val.bits.size(); i += 4) { int digit_value = 0; - if (i+0 < p.second.bits.size() && p.second.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; - if (i+1 < p.second.bits.size() && p.second.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; - if (i+2 < p.second.bits.size() && p.second.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; - if (i+3 < p.second.bits.size() && p.second.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; + if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; + if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; + if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; + if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; hex_string = std::string(digit_str) + hex_string; } - *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(p.first), GetSize(p.second.bits), hex_string.c_str()); + *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); } + }; + + for (auto &p : cell->parameters) + add_prop(p.first, p.second); + if (attr_properties) + for (auto &p : cell->attributes) + add_prop(p.first, p.second); + *f << stringf(")\n"); for (auto &p : cell->connections()) { RTLIL::SigSpec sig = sigmap(p.second); -- cgit v1.2.3 From 749b3ed62a8665f756267fafd7520beb55570df5 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Mon, 15 Oct 2018 13:54:12 -0400 Subject: Minor update --- backends/smv/smv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index a53ee7a7c..f379c9c48 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -232,7 +232,7 @@ struct SmvWorker SigSpec sig_a = cell->getPort("\\A"); SigSpec sig_en = cell->getPort("\\EN"); - invarspecs.push_back(stringf("(!bool(%s) | bool(%s));", rvalue(sig_en), rvalue(sig_a))); + invarspecs.push_back(stringf("!bool(%s) | bool(%s);", rvalue(sig_en), rvalue(sig_a))); continue; } -- cgit v1.2.3 From 609f46eeb7b23fec2140dcfaaa5f3a8377153f43 Mon Sep 17 00:00:00 2001 From: rafaeltp Date: Thu, 18 Oct 2018 16:20:21 -0700 Subject: adding offset info to memories --- backends/verilog/verilog_backend.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index ae9031510..39683922f 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -388,7 +388,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory) { dump_attributes(f, indent, memory->attributes); - f << stringf("%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1); + f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), (memory->width-1), id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset); } void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true) @@ -952,6 +952,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) std::string mem_id = id(cell->parameters["\\MEMID"].decode_string()); int abits = cell->parameters["\\ABITS"].as_int(); int size = cell->parameters["\\SIZE"].as_int(); + int offset = cell->parameters["\\OFFSET"].as_int(); int width = cell->parameters["\\WIDTH"].as_int(); bool use_init = !(RTLIL::SigSpec(cell->parameters["\\INIT"]).is_fully_undef()); @@ -960,7 +961,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) // initial begin // memid[0] = ... // end - f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size-1, 0); + f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset); if (use_init) { f << stringf("%s" "initial begin\n", indent.c_str()); -- cgit v1.2.3 From c7770d9eeaf9fba0c9d07e7cce020fe89ec71600 Mon Sep 17 00:00:00 2001 From: rafaeltp Date: Thu, 18 Oct 2018 16:22:33 -0700 Subject: adding offset info to memories --- backends/verilog/verilog_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 39683922f..dde03f920 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -388,7 +388,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory) { dump_attributes(f, indent, memory->attributes); - f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), (memory->width-1), id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset); + f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset); } void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true) -- cgit v1.2.3 From b6781c6f4ba20ba14d1649a993fc09691921de2b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Nov 2018 11:40:58 +0100 Subject: Add support for signed $shift/$shiftx in smt2 back-end Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index e2777ae04..418f8d766 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -554,7 +554,9 @@ struct Smt2Worker if (cell->type.in("$shift", "$shiftx")) { if (cell->getParam("\\B_SIGNED").as_bool()) { - /* FIXME */ + return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) " + "(bvlshr A B) (bvlshr A (bvneg B)))", + GetSize(cell->getPort("\\B")), 0), 's'); } else { return export_bvop(cell, "(bvlshr A B)", 's'); } -- cgit v1.2.3 From d0acea4f2e6c98f09246584c2ac0903acc254093 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Nov 2018 14:41:28 +0100 Subject: Add proper error message for when smtbmc "append" fails Signed-off-by: Clifford Wolf --- backends/smt2/smtbmc.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 6af2a5ac1..b944ee004 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -1259,7 +1259,11 @@ elif covermode: smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i)) smt_assert_consequent(get_constr_expr(constr_assumes, i)) print_msg("Re-solving with appended steps..") - assert smt_check_sat() == "sat" + if smt_check_sat() == "unsat": + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) + found_failed_assert = True + retstatus = False + break reached_covers = smt.bv2bin(smt.get("(covers_%d s%d)" % (coveridx, step))) assert len(reached_covers) == len(cover_desc) @@ -1377,7 +1381,11 @@ else: # not tempind, covermode smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i)) smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i)) smt_assert_consequent(get_constr_expr(constr_assumes, i)) - assert smt_check_sat() == "sat" + print_msg("Re-solving with appended steps..") + if smt_check_sat() == "unsat": + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) + retstatus = False + break print_anyconsts(step) for i in range(step, last_check_step+1): print_failed_asserts(i) -- cgit v1.2.3 From 2b935421718c9a8d8f2183d9cb4a4973c078bcfa Mon Sep 17 00:00:00 2001 From: Arjen Roodselaar Date: Sun, 4 Nov 2018 21:58:09 -0800 Subject: Use conservative stack size for SMT2 on MacOS --- backends/smt2/smtio.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 3fc823e3e..e8ed5e63b 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -32,10 +32,15 @@ from threading import Thread if os.name == "posix": smtio_reclimit = 64 * 1024 smtio_stacksize = 128 * 1024 * 1024 + smtio_stacklimit = resource.RLIM_INFINITY + if os.uname().sysname == "Darwin": + # MacOS has rather conservative stack limits + smtio_stacksize = 16 * 1024 * 1024 + smtio_stacklimit = resource.getrlimit(resource.RLIMIT_STACK)[1] if sys.getrecursionlimit() < smtio_reclimit: sys.setrecursionlimit(smtio_reclimit) if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1)) + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, smtio_stacklimit)) # currently running solvers (so we can kill them) -- cgit v1.2.3 From 79075d123f749ad39bf35f658f00a79a24efcf98 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Nov 2018 10:05:23 +0100 Subject: Improve stack rlimit code in smtio.py Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index e8ed5e63b..e417b7758 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -31,16 +31,16 @@ from threading import Thread # does not run out of stack frames when parsing large expressions if os.name == "posix": smtio_reclimit = 64 * 1024 - smtio_stacksize = 128 * 1024 * 1024 - smtio_stacklimit = resource.RLIM_INFINITY - if os.uname().sysname == "Darwin": - # MacOS has rather conservative stack limits - smtio_stacksize = 16 * 1024 * 1024 - smtio_stacklimit = resource.getrlimit(resource.RLIMIT_STACK)[1] if sys.getrecursionlimit() < smtio_reclimit: sys.setrecursionlimit(smtio_reclimit) - if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, smtio_stacklimit)) + + smtio_stacksize = 128 * 1024 * 1024 + current_rlimit_stack = resource.getrlimit(resource.RLIMIT_STACK) + if current_rlimit_stack[0] != resource.RLIM_INFINITY: + if current_rlimit_stack[1] != resource.RLIM_INFINITY: + smtio_stacksize = min(smtio_stacksize, smtio_stacklimit) + if current_rlimit_stack[0] < smtio_stacksize: + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) # currently running solvers (so we can kill them) -- cgit v1.2.3 From 4c50e3abb9b39fe088cc0a08c63fcadb8abdabb7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Nov 2018 10:09:03 +0100 Subject: Fix for improved smtio.py rlimit code Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index e417b7758..108f6bcfe 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -38,7 +38,7 @@ if os.name == "posix": current_rlimit_stack = resource.getrlimit(resource.RLIMIT_STACK) if current_rlimit_stack[0] != resource.RLIM_INFINITY: if current_rlimit_stack[1] != resource.RLIM_INFINITY: - smtio_stacksize = min(smtio_stacksize, smtio_stacklimit) + smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) if current_rlimit_stack[0] < smtio_stacksize: resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) -- cgit v1.2.3 From f6c4485a3ac315fbed76f1a2e1f22df7afb36886 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Nov 2018 11:11:05 +0100 Subject: Run solver in non-incremental mode whem smtio.py is configured for non-incremental solving Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index e8ed5e63b..4c3245984 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -163,19 +163,28 @@ class SmtIo: self.unroll = False if self.solver == "yices": - self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['yices-smt2'] + self.solver_opts + else: + self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts if self.solver == "z3": self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts if self.solver == "cvc4": - self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + else: + self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts if self.solver == "mathsat": self.popen_vargs = ['mathsat'] + self.solver_opts if self.solver == "boolector": - self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['boolector', '--smt2'] + self.solver_opts + else: + self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts self.unroll = True if self.solver == "abc": -- cgit v1.2.3 From b54bf7c0f9720526dffce684ef1353b81f99547c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 7 Nov 2018 15:32:34 +0100 Subject: Limit stack size to 16 MB on Darwin Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 108f6bcfe..afbcf1fc4 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -34,9 +34,12 @@ if os.name == "posix": if sys.getrecursionlimit() < smtio_reclimit: sys.setrecursionlimit(smtio_reclimit) - smtio_stacksize = 128 * 1024 * 1024 current_rlimit_stack = resource.getrlimit(resource.RLIMIT_STACK) if current_rlimit_stack[0] != resource.RLIM_INFINITY: + smtio_stacksize = 128 * 1024 * 1024 + if os.uname().sysname == "Darwin": + # MacOS has rather conservative stack limits + smtio_stacksize = 16 * 1024 * 1024 if current_rlimit_stack[1] != resource.RLIM_INFINITY: smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) if current_rlimit_stack[0] < smtio_stacksize: -- cgit v1.2.3 From 82aaf6d9086176c746bb157f33fd085a2e03e461 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 12 Nov 2018 09:27:33 +0100 Subject: Add "write_aiger -I -O -B" Signed-off-by: Clifford Wolf --- backends/aiger/aiger.cc | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index c323691a3..dfe506c66 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -100,7 +100,7 @@ struct AigerWriter return aig_map.at(bit); } - AigerWriter(Module *module, bool zinit_mode) : module(module), zinit_mode(zinit_mode), sigmap(module) + AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -293,6 +293,10 @@ struct AigerWriter aig_map[bit] = 2*aig_m; } + if (imode && input_bits.empty()) { + aig_m++, aig_i++; + } + if (zinit_mode) { for (auto it : ff_map) { @@ -371,6 +375,11 @@ struct AigerWriter aig_outputs.push_back(bit2aig(bit)); } + if (omode && output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + } + for (auto it : asserts) { aig_b++; int bit_a = bit2aig(it.first); @@ -378,6 +387,11 @@ struct AigerWriter aig_outputs.push_back(mkgate(bit_a^1, bit_en)); } + if (bmode && asserts.empty()) { + aig_b++; + aig_outputs.push_back(0); + } + for (auto it : assumes) { aig_c++; int bit_a = bit2aig(it.first); @@ -689,6 +703,11 @@ struct AigerBackend : public Backend { log(" -vmap \n"); log(" like -map, but more verbose\n"); log("\n"); + log(" -I, -O, -B\n"); + log(" If the design contains no input/output/assert then create one\n"); + log(" dummy input/output/bad_state pin to make the tools reading the\n"); + log(" AIGER file happy.\n"); + log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -697,6 +716,9 @@ struct AigerBackend : public Backend { bool miter_mode = false; bool symbols_mode = false; bool verbose_map = false; + bool imode = false; + bool omode = false; + bool bmode = false; std::string map_filename; log_header(design, "Executing AIGER backend.\n"); @@ -729,6 +751,18 @@ struct AigerBackend : public Backend { verbose_map = true; continue; } + if (args[argidx] == "-I") { + imode = true; + continue; + } + if (args[argidx] == "-O") { + omode = true; + continue; + } + if (args[argidx] == "-B") { + bmode = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -738,7 +772,7 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - AigerWriter writer(top_module, zinit_mode); + AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From 7fe770a441a129c509fd4da04b60ada942a28bc8 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 18:48:06 +0000 Subject: write_verilog: correctly map RTLIL `sync init`. --- backends/verilog/verilog_backend.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index dde03f920..922b4c44c 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1352,6 +1352,8 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo if (sync->type == RTLIL::STa) { f << stringf("%s" "always @* begin\n", indent.c_str()); + } else if (sync->type == RTLIL::STi) { + f << stringf("%s" "initial begin\n", indent.c_str()); } else { f << stringf("%s" "always @(", indent.c_str()); if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1) -- cgit v1.2.3 From ed3c57fad3616b981e54e2f209e7ee40ff87c8a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Dec 2018 06:21:31 +0100 Subject: Fix btor init value handling Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 58d2a8625..ab2702807 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -506,6 +506,18 @@ struct BtorWorker } } + Const initval; + for (int i = 0; i < GetSize(sig_q); i++) + if (initbits.count(sig_q[i])) + initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); + else + initval.bits.push_back(State::Sx); + + int nid_init_val = -1; + + if (!initval.is_fully_undef()) + nid_init_val = get_sig_nid(initval); + int sid = get_bv_sid(GetSize(sig_q)); int nid = next_nid++; @@ -514,15 +526,7 @@ struct BtorWorker else btorf("%d state %d %s\n", nid, sid, log_id(symbol)); - Const initval; - for (int i = 0; i < GetSize(sig_q); i++) - if (initbits.count(sig_q[i])) - initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); - else - initval.bits.push_back(State::Sx); - - if (!initval.is_fully_undef()) { - int nid_init_val = get_sig_nid(initval); + if (nid_init_val >= 0) { int nid_init = next_nid++; if (verbose) btorf("; initval = %s\n", log_signal(initval)); -- cgit v1.2.3 From 47a5dfdaa4bd7d400c6e3d58476de80904df460d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Dec 2018 06:59:27 +0100 Subject: Add "yosys-smtbmc --btorwit" skeleton Signed-off-by: Clifford Wolf --- backends/smt2/smtbmc.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index b944ee004..57b50ccb6 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -32,6 +32,8 @@ cexfile = None aimfile = None aiwfile = None aigheader = True +btorfile = None +witfile = None vlogtbfile = None vlogtbtop = None inconstr = list() @@ -92,6 +94,10 @@ yosys-smtbmc [options] the AIGER witness file does not include the status and properties lines. + --btorwit + --btorwit : + read a BTOR file and a BTOR witness for that BTOR file. + --noinfo only run the core proof, do not collect and print any additional information (e.g. which assert failed) @@ -152,7 +158,7 @@ yosys-smtbmc [options] try: opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts + - ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "presat", + ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "btorwit=", "presat", "dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=", "smtc-init", "smtc-top=", "noinit"]) except: @@ -189,6 +195,12 @@ for o, a in opts: aiwfile = a + ".aiw" elif o == "--aig-noheader": aigheader = False + elif o == "--btorwit": + if ":" in a: + btorfile, witfile = a.split(":") + else: + btorfile = a + ".btor" + witfile = a + ".wit" elif o == "--dump-vcd": vcdfile = a elif o == "--dump-vlogtb": @@ -575,6 +587,12 @@ if aimfile is not None: num_steps = max(num_steps, step+1) step += 1 +if btorfile is not None: + print("The --btorwit feature is not implemented yet") + smt.write("(exit)") + smt.wait() + sys.exit(1) + def write_vcd_trace(steps_start, steps_stop, index): filename = vcdfile.replace("%", index) print_msg("Writing trace to VCD file: %s" % (filename)) -- cgit v1.2.3 From 0b9bb852c66ec2a6e9b4b510b3e2e32b8c6a6b16 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 10 Dec 2018 03:43:07 +0100 Subject: Add yosys-smtbmc support for btor witness Signed-off-by: Clifford Wolf --- backends/smt2/smtbmc.py | 115 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 15 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 57b50ccb6..721a395e3 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -32,8 +32,7 @@ cexfile = None aimfile = None aiwfile = None aigheader = True -btorfile = None -witfile = None +btorwitfile = None vlogtbfile = None vlogtbtop = None inconstr = list() @@ -94,9 +93,8 @@ yosys-smtbmc [options] the AIGER witness file does not include the status and properties lines. - --btorwit - --btorwit : - read a BTOR file and a BTOR witness for that BTOR file. + --btorwit + read a BTOR witness. --noinfo only run the core proof, do not collect and print any @@ -196,11 +194,7 @@ for o, a in opts: elif o == "--aig-noheader": aigheader = False elif o == "--btorwit": - if ":" in a: - btorfile, witfile = a.split(":") - else: - btorfile = a + ".btor" - witfile = a + ".wit" + btorwitfile = a elif o == "--dump-vcd": vcdfile = a elif o == "--dump-vlogtb": @@ -587,11 +581,102 @@ if aimfile is not None: num_steps = max(num_steps, step+1) step += 1 -if btorfile is not None: - print("The --btorwit feature is not implemented yet") - smt.write("(exit)") - smt.wait() - sys.exit(1) +if btorwitfile is not None: + with open(btorwitfile, "r") as f: + step = None + suffix = None + altsuffix = None + header_okay = False + + for line in f: + line = line.strip() + + if line == "sat": + header_okay = True + continue + + if not header_okay: + continue + + if line == "" or line[0] == "b" or line[0] == "j": + continue + + if line == ".": + break + + if line[0] == '#' or line[0] == '@': + step = int(line[1:]) + suffix = line + altsuffix = suffix + if suffix[0] == "@": + altsuffix = "#" + suffix[1:] + else: + altsuffix = "@" + suffix[1:] + continue + + line = line.split() + + if len(line) == 0: + continue + + if line[-1].endswith(suffix): + line[-1] = line[-1][0:len(line[-1]) - len(suffix)] + + if line[-1].endswith(altsuffix): + line[-1] = line[-1][0:len(line[-1]) - len(altsuffix)] + + if line[-1][0] == "$": + continue + + # BV assignments + if len(line) == 3 and line[1][0] != "[": + value = line[1] + name = line[2] + + path = smt.get_path(topmod, name) + + if not smt.net_exists(topmod, path): + continue + + width = smt.net_width(topmod, path) + + if width == 1: + assert value in ["0", "1"] + value = "true" if value == "1" else "false" + else: + value = "#b" + value + + smtexpr = "(= [%s] %s)" % (name, value) + constr_assumes[step].append((btorwitfile, smtexpr)) + + # Array assignments + if len(line) == 4 and line[1][0] == "[": + index = line[1] + value = line[2] + name = line[3] + + path = smt.get_path(topmod, name) + + if not smt.mem_exists(topmod, path): + continue + + meminfo = smt.mem_info(topmod, path) + + if meminfo[1] == 1: + assert value in ["0", "1"] + value = "true" if value == "1" else "false" + else: + value = "#b" + value + + assert index[0] == "[" + assert index[-1] == "]" + index = "#b" + index[1:-1] + + smtexpr = "(= (select [%s] %s) %s)" % (name, index, value) + constr_assumes[step].append((btorwitfile, smtexpr)) + + skip_steps = step + num_steps = step+1 def write_vcd_trace(steps_start, steps_stop, index): filename = vcdfile.replace("%", index) -- cgit v1.2.3 From fccaa25ec1b053259a377991d8deba0f71021956 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 13 Dec 2018 04:36:02 +0000 Subject: write_verilog: add a missing newline. --- backends/verilog/verilog_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index dde03f920..850abfad7 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1419,7 +1419,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) log_warning("Module %s contains unmapped RTLIL proccesses. RTLIL processes\n" "can't always be mapped directly to Verilog always blocks. Unintended\n" "changes in simulation behavior are possible! Use \"proc\" to convert\n" - "processes to logic networks and registers.", log_id(module)); + "processes to logic networks and registers.\n", log_id(module)); f << stringf("\n"); for (auto it = module->processes.begin(); it != module->processes.end(); ++it) -- cgit v1.2.3 From ca866d384e666f27e2cd7bb80950d0a1dd7c0ebd Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 16 Dec 2018 18:46:32 +0000 Subject: write_verilog: handle the $shift cell. The implementation corresponds to the following Verilog, which is lifted straight from simlib.v: module \\$shift (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (B_SIGNED) begin:BLOCK1 assign Y = $signed(B) < 0 ? A << -B : A >> B; end else begin:BLOCK2 assign Y = A >> B; end endgenerate endmodule --- backends/verilog/verilog_backend.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 3a47b478f..71db25f98 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -678,6 +678,35 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) #undef HANDLE_UNIOP #undef HANDLE_BINOP + if (cell->type == "$shift") + { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + if (cell->getParam("\\B_SIGNED").as_bool()) + { + f << stringf("$signed("); + dump_sigspec(f, cell->getPort("\\B")); + f << stringf(")"); + f << stringf(" < 0 ? "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" << - "); + dump_sigspec(f, cell->getPort("\\B")); + f << stringf(" : "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" >> "); + dump_sigspec(f, cell->getPort("\\B")); + } + else + { + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" >> "); + dump_sigspec(f, cell->getPort("\\B")); + } + f << stringf(";\n"); + return true; + } + if (cell->type == "$shiftx") { f << stringf("%s" "assign ", indent.c_str()); -- cgit v1.2.3 From abf5930a3325b8ae89f8cbb89a0f963e316c0889 Mon Sep 17 00:00:00 2001 From: makaimann Date: Mon, 5 Nov 2018 11:49:31 -0800 Subject: Add btor ops for $mul, $div, $mod and $concat --- backends/btor/btor.cc | 40 ++++++++++++++++++++++++++++++++++++++-- backends/btor/test_cells.sh | 0 2 files changed, 38 insertions(+), 2 deletions(-) mode change 100644 => 100755 backends/btor/test_cells.sh (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index ab2702807..d3fb9b858 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -133,12 +133,13 @@ struct BtorWorker cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); - if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx", - "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) + if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx", + "$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { string btor_op; if (cell->type == "$add") btor_op = "add"; if (cell->type == "$sub") btor_op = "sub"; + if (cell->type == "$mul") btor_op = "mul"; if (cell->type.in("$shl", "$sshl")) btor_op = "sll"; if (cell->type == "$shr") btor_op = "srl"; if (cell->type == "$sshr") btor_op = "sra"; @@ -146,6 +147,7 @@ struct BtorWorker if (cell->type.in("$and", "$_AND_")) btor_op = "and"; if (cell->type.in("$or", "$_OR_")) btor_op = "or"; if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor"; + if (cell->type == "$concat") btor_op = "concat"; if (cell->type == "$_NAND_") btor_op = "nand"; if (cell->type == "$_NOR_") btor_op = "nor"; if (cell->type.in("$xnor", "$_XNOR_")) btor_op = "xnor"; @@ -214,6 +216,40 @@ struct BtorWorker goto okay; } + if (cell->type.in("$div", "$mod")) + { + string btor_op; + if (cell->type == "$div") btor_op = "div"; + if (cell->type == "$mod") btor_op = "rem"; + log_assert(!btor_op.empty()); + + int width = GetSize(cell->getPort("\\Y")); + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); + + bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false; + bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false; + + int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed); + int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed); + + int sid = get_bv_sid(width); + int nid = next_nid++; + btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b); + + SigSpec sig = sigmap(cell->getPort("\\Y")); + + if (GetSize(sig) < width) { + int sid = get_bv_sid(GetSize(sig)); + int nid2 = next_nid++; + btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1); + nid = nid2; + } + + add_nid_sig(nid, sig); + goto okay; + } + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) { int sid = get_bv_sid(1); diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh old mode 100644 new mode 100755 -- cgit v1.2.3 From 23bb77867f56e966195d99d1d89b45d510d0b92d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 18 Dec 2018 20:02:39 +0100 Subject: Minor style fixes Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 2 +- backends/btor/test_cells.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 backends/btor/test_cells.sh (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index d3fb9b858..53359bd7b 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -134,7 +134,7 @@ struct BtorWorker btorf_push(log_id(cell)); if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx", - "$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) + "$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { string btor_op; if (cell->type == "$add") btor_op = "add"; diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh old mode 100755 new mode 100644 -- cgit v1.2.3 From 99706b3bf48de121e58b76d4341d601f0bcc26cd Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Fri, 28 Dec 2018 08:24:31 -0800 Subject: Squelch a little more trailing whitespace --- backends/simplec/test00_uut.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/simplec/test00_uut.v b/backends/simplec/test00_uut.v index 744dbe9e3..92329a6f9 100644 --- a/backends/simplec/test00_uut.v +++ b/backends/simplec/test00_uut.v @@ -3,12 +3,12 @@ module test(input [31:0] a, b, c, output [31:0] x, y, z, w); unit_y unit_y_inst (.a(a), .b(b), .c(c), .y(y)); assign z = a ^ b ^ c, w = z; endmodule - + module unit_x(input [31:0] a, b, c, output [31:0] x); assign x = (a & b) | c; endmodule - + module unit_y(input [31:0] a, b, c, output [31:0] y); assign y = a & (b | c); endmodule - + -- cgit v1.2.3 From efa278e232d20ea080743801bd91d55ec62955cf Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 19:14:07 +0000 Subject: Fix typographical and grammatical errors and inconsistencies. The initial list of hits was generated with the codespell command below, and each hit was evaluated and fixed manually while taking context into consideration. DIRS="kernel/ frontends/ backends/ passes/ techlibs/" DIRS="${DIRS} libs/ezsat/ libs/subcircuit" codespell $DIRS -S *.o -L upto,iff,thru,synopsys,uint More hits were found by looking through comments and strings manually. --- backends/simplec/simplec.cc | 2 +- backends/smt2/smtbmc.py | 8 ++++---- backends/table/table.cc | 2 +- backends/verilog/verilog_backend.cc | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 349bc5a6d..6f2ccbe20 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -748,7 +748,7 @@ struct SimplecBackend : public Backend { log("\n"); log(" write_simplec [options] [filename]\n"); log("\n"); - log("Write simple C code for simulating the design. The C code writen can be used to\n"); + log("Write simple C code for simulating the design. The C code written can be used to\n"); log("simulate the design in a C environment, but the purpose of this command is to\n"); log("generate code that works well with C-based formal verification.\n"); log("\n"); diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 721a395e3..94a5e2da0 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -87,7 +87,7 @@ yosys-smtbmc [options] --aig : like above, but for map files and witness files that do not - share a filename prefix (or use differen file extensions). + share a filename prefix (or use different file extensions). --aig-noheader the AIGER witness file does not include the status and @@ -103,8 +103,8 @@ yosys-smtbmc [options] --presat check if the design with assumptions but without assertions is SAT before checking if assertions are UNSAT. This will - detect if there are contradicting assumtions. In some cases - this will also help to "warmup" the solver, potentially + detect if there are contradicting assumptions. In some cases + this will also help to "warm up" the solver, potentially yielding a speedup. --final-only @@ -149,7 +149,7 @@ yosys-smtbmc [options] --append add time steps at the end of the trace when creating a counter example (this additional time - steps will still be constrained by assumtions) + steps will still be constrained by assumptions) """ + so.helpmsg()) sys.exit(1) diff --git a/backends/table/table.cc b/backends/table/table.cc index 979273dd3..b75169ea4 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -109,7 +109,7 @@ struct TableBackend : public Backend { else if (cell->output(conn.first)) *f << "out" << "\t"; else - *f << "unkown" << "\t"; + *f << "unknown" << "\t"; *f << log_signal(sigmap(conn.second)) << "\n"; } diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 71db25f98..2537e18e5 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1447,7 +1447,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } if (!module->processes.empty()) - log_warning("Module %s contains unmapped RTLIL proccesses. RTLIL processes\n" + log_warning("Module %s contains unmapped RTLIL processes. RTLIL processes\n" "can't always be mapped directly to Verilog always blocks. Unintended\n" "changes in simulation behavior are possible! Use \"proc\" to convert\n" "processes to logic networks and registers.\n", log_id(module)); -- cgit v1.2.3 From 6c5049f016538e887476bb66d3f653155fa354ff Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 15 Jan 2019 10:55:27 +0100 Subject: Fix handling of $shiftx in Verilog back-end Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 2537e18e5..8da3c0627 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -709,11 +709,14 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (cell->type == "$shiftx") { + std::string temp_id = next_auto_id(); + f << stringf("%s" "wire [%d:0] %s = ", indent.c_str(), GetSize(cell->getPort("\\A"))-1, temp_id.c_str()); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(";\n"); + f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, cell->getPort("\\Y")); - f << stringf(" = "); - dump_sigspec(f, cell->getPort("\\A")); - f << stringf("["); + f << stringf(" = %s[", temp_id.c_str()); if (cell->getParam("\\B_SIGNED").as_bool()) f << stringf("$signed("); dump_sigspec(f, cell->getPort("\\B")); -- cgit v1.2.3 From 54dc33b90518d8962d949a8f8b25842f720ac670 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 17 Jan 2019 13:33:11 +0100 Subject: Add "write_edif -gndvccy" Signed-off-by: Clifford Wolf --- backends/edif/edif.cc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index d4e56a9eb..2d25f879d 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -106,6 +106,10 @@ struct EdifBackend : public Backend { log(" if the design contains constant nets. use \"hilomap\" to map to custom\n"); log(" constant drivers first)\n"); log("\n"); + log(" -gndvccy\n"); + log(" create \"GND\" and \"VCC\" cells with \"Y\" outputs. (the default is \"G\"\n"); + log(" for \"GND\" and \"P\" for \"VCC\".)\n"); + log("\n"); log(" -attrprop\n"); log(" create EDIF properties for cell attributes\n"); log("\n"); @@ -126,7 +130,7 @@ struct EdifBackend : public Backend { bool port_rename = false; bool attr_properties = false; std::map> lib_cell_ports; - bool nogndvcc = false; + bool nogndvcc = false, gndvccy = true; CellTypes ct(design); EdifNames edif_names; @@ -141,6 +145,10 @@ struct EdifBackend : public Backend { nogndvcc = true; continue; } + if (args[argidx] == "-gndvccy") { + gndvccy = true; + continue; + } if (args[argidx] == "-attrprop") { attr_properties = true; continue; @@ -211,7 +219,7 @@ struct EdifBackend : public Backend { *f << stringf(" (cellType GENERIC)\n"); *f << stringf(" (view VIEW_NETLIST\n"); *f << stringf(" (viewType NETLIST)\n"); - *f << stringf(" (interface (port G (direction OUTPUT)))\n"); + *f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'G'); *f << stringf(" )\n"); *f << stringf(" )\n"); @@ -219,7 +227,7 @@ struct EdifBackend : public Backend { *f << stringf(" (cellType GENERIC)\n"); *f << stringf(" (view VIEW_NETLIST\n"); *f << stringf(" (viewType NETLIST)\n"); - *f << stringf(" (interface (port P (direction OUTPUT)))\n"); + *f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'P'); *f << stringf(" )\n"); *f << stringf(" )\n"); } @@ -420,9 +428,9 @@ struct EdifBackend : public Backend { if (nogndvcc) log_error("Design contains constant nodes (map with \"hilomap\" first).\n"); if (sig == RTLIL::State::S0) - *f << stringf(" (portRef G (instanceRef GND))\n"); + *f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G'); if (sig == RTLIL::State::S1) - *f << stringf(" (portRef P (instanceRef VCC))\n"); + *f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P'); } *f << stringf(" ))\n"); } -- cgit v1.2.3 From 42c47a83dab873290040367455c48f619d83e2a3 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 26 Jan 2019 23:55:46 +0000 Subject: write_verilog: escape names that match SystemVerilog keywords. --- backends/verilog/verilog_backend.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 8da3c0627..fc38afbda 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -126,6 +126,33 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true) break; } + const pool keywords = { + // IEEE 1800-2017 Annex B + "accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before", + "begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle", + "checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint", + "cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker", + "endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage", + "endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually", + "expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function", + "generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies", + "import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface", + "intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint", + "macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor", + "noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive", + "priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent", + "pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat", + "restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until", + "s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify", + "specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on", + "sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1", + "tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with", + "untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while", + "wildcard", "wire", "with", "within", "wor", "xnor", "xor", + }; + if (keywords.count(str)) + do_escape = true; + if (do_escape) return "\\" + std::string(str) + " "; return std::string(str); -- cgit v1.2.3 From 3d7925ad9f7840d5269b84d053ae808f36ccf762 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 27 Jan 2019 00:21:31 +0000 Subject: write_verilog: write $tribuf cell as ternary. --- backends/verilog/verilog_backend.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 8da3c0627..54281e32e 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -789,6 +789,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type == "$tribuf") + { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + dump_sigspec(f, cell->getPort("\\EN")); + f << stringf(" ? "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" : %d'bz;\n", cell->parameters.at("\\WIDTH").as_int()); + return true; + } + if (cell->type == "$slice") { f << stringf("%s" "assign ", indent.c_str()); -- cgit v1.2.3 From da65e1e8d9552f64e1e03c08108ca0532719bbfe Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 29 Jan 2019 02:24:00 +0000 Subject: write_verilog: correctly emit asynchronous transparent ports. This commit fixes two related issues: * For asynchronous ports, clock is no longer added to domain list. (This would lead to absurd constructs like `always @(posedge 0)`. * The logic to distinguish synchronous and asynchronous ports is changed to correctly use or avoid clock in all cases. Before this commit, the following RTLIL snippet (after memory_collect) cell $memrd $2 parameter \MEMID "\\mem" parameter \ABITS 2 parameter \WIDTH 4 parameter \CLK_ENABLE 0 parameter \CLK_POLARITY 1 parameter \TRANSPARENT 1 connect \CLK 1'0 connect \EN 1'1 connect \ADDR \mem_r_addr connect \DATA \mem_r_data end would lead to invalid Verilog: reg [1:0] _0_; always @(posedge 1'h0) begin _0_ <= mem_r_addr; end assign mem_r_data = mem[_0_]; Note that there are two potential pitfalls remaining after this change: * For asynchronous ports, the \EN input and \TRANSPARENT parameter are silently ignored. (Per discussion in #760 this is the correct behavior.) * For synchronous transparent ports, the \EN input is ignored. This matches the behavior of the $mem simulation cell. Again, see #760. --- backends/verilog/verilog_backend.cc | 79 +++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a7f329ef8..60668f1f0 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1065,43 +1065,46 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) use_rd_clk = cell->parameters["\\RD_CLK_ENABLE"].extract(i).as_bool(); rd_clk_posedge = cell->parameters["\\RD_CLK_POLARITY"].extract(i).as_bool(); rd_transparent = cell->parameters["\\RD_TRANSPARENT"].extract(i).as_bool(); + if (use_rd_clk) { - std::ostringstream os; - dump_sigspec(os, sig_rd_clk); - clk_domain_str = stringf("%sedge %s", rd_clk_posedge ? "pos" : "neg", os.str().c_str()); - if( clk_to_lof_body.count(clk_domain_str) == 0 ) - clk_to_lof_body[clk_domain_str] = std::vector(); - } - if (use_rd_clk && !rd_transparent) - { - // for clocked read ports make something like: - // reg [..] temp_id; - // always @(posedge clk) - // if (rd_en) temp_id <= array_reg[r_addr]; - // assign r_data = temp_id; - std::string temp_id = next_auto_id(); - lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", sig_rd_data.size() - 1, temp_id.c_str()) ); { std::ostringstream os; - if (sig_rd_en != RTLIL::SigBit(true)) + dump_sigspec(os, sig_rd_clk); + clk_domain_str = stringf("%sedge %s", rd_clk_posedge ? "pos" : "neg", os.str().c_str()); + if( clk_to_lof_body.count(clk_domain_str) == 0 ) + clk_to_lof_body[clk_domain_str] = std::vector(); + } + if (!rd_transparent) + { + // for clocked read ports make something like: + // reg [..] temp_id; + // always @(posedge clk) + // if (rd_en) temp_id <= array_reg[r_addr]; + // assign r_data = temp_id; + std::string temp_id = next_auto_id(); + lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", sig_rd_data.size() - 1, temp_id.c_str()) ); + { + std::ostringstream os; + if (sig_rd_en != RTLIL::SigBit(true)) + { + os << stringf("if ("); + dump_sigspec(os, sig_rd_en); + os << stringf(") "); + } + os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str()); + dump_sigspec(os, sig_rd_addr); + os << stringf("];\n"); + clk_to_lof_body[clk_domain_str].push_back(os.str()); + } { - os << stringf("if ("); - dump_sigspec(os, sig_rd_en); - os << stringf(") "); + std::ostringstream os; + dump_sigspec(os, sig_rd_data); + std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str()); + clk_to_lof_body[""].push_back(line); } - os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str()); - dump_sigspec(os, sig_rd_addr); - os << stringf("];\n"); - clk_to_lof_body[clk_domain_str].push_back(os.str()); } + else { - std::ostringstream os; - dump_sigspec(os, sig_rd_data); - std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str()); - clk_to_lof_body[""].push_back(line); - } - } else { - if (rd_transparent) { // for rd-transparent read-ports make something like: // reg [..] temp_id; // always @(posedge clk) @@ -1121,15 +1124,15 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), temp_id.c_str()); clk_to_lof_body[""].push_back(line); } - } else { - // for non-clocked read-ports make something like: - // assign r_data = array_reg[r_addr]; - std::ostringstream os, os2; - dump_sigspec(os, sig_rd_data); - dump_sigspec(os2, sig_rd_addr); - std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str()); - clk_to_lof_body[""].push_back(line); } + } else { + // for non-clocked read-ports make something like: + // assign r_data = array_reg[r_addr]; + std::ostringstream os, os2; + dump_sigspec(os, sig_rd_data); + dump_sigspec(os2, sig_rd_addr); + std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str()); + clk_to_lof_body[""].push_back(line); } } -- cgit v1.2.3 From e112d2fbf5a31f00ef19e6d05f28fecc1e9c56b9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 6 Feb 2019 16:35:59 +0100 Subject: Add missing blackslash-to-slash convertion to smtio.py (matching Smt2Worker::get_id() behavior) Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 68783e744..ab20a4af2 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -784,7 +784,7 @@ class SmtIo: def get_path(self, mod, path): assert mod in self.modinfo - path = path.split(".") + path = path.replace("\\", "/").split(".") for i in range(len(path)-1): first = ".".join(path[0:i+1]) -- cgit v1.2.3 From 8241db6960d17469678e8c71fd7d6c1b7ddc4fe7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:17:09 -0800 Subject: write_verilog to cope with init attr on q when -noexpr --- backends/verilog/verilog_backend.cc | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a7f329ef8..04191443a 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1247,7 +1247,30 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) dump_attributes(f, indent, cell->attributes); f << stringf("%s" "%s", indent.c_str(), id(cell->type, false).c_str()); - if (!defparam && cell->parameters.size() > 0) { + std::string init; + if (cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { + auto q_wire = cell->getPort("\\Q"); + + Const initval; + bool gotinit = false; + + for (auto bit : active_sigmap(q_wire)) { + if (active_initdata.count(bit)) { + initval.bits.push_back(active_initdata.at(bit)); + gotinit = true; + } else { + initval.bits.push_back(State::Sx); + } + } + + if (gotinit) { + std::stringstream ss; + dump_const(ss, initval); + init = ss.str(); + } + } + + if (!defparam && (cell->parameters.size() > 0 || !init.empty())) { f << stringf(" #("); for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { if (it != cell->parameters.begin()) @@ -1257,6 +1280,11 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) dump_const(f, it->second, -1, 0, false, is_signed); f << stringf(")"); } + if (!init.empty()) { + if (!cell->parameters.empty()) + f << stringf(","); + f << stringf("\n%s .INIT(%s)", indent.c_str(), init.c_str()); + } f << stringf("\n%s" ")", indent.c_str()); } @@ -1298,13 +1326,15 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } f << stringf("\n%s" ");\n", indent.c_str()); - if (defparam && cell->parameters.size() > 0) { + if (defparam && (cell->parameters.size() > 0 || !init.empty())) { for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { f << stringf("%sdefparam %s.%s = ", indent.c_str(), cell_name.c_str(), id(it->first).c_str()); bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; dump_const(f, it->second, -1, 0, false, is_signed); f << stringf(";\n"); } + if (!init.empty()) + f << stringf("%sdefparam %s.INIT = %s;\n", indent.c_str(), cell_name.c_str(), init.c_str()); } } -- cgit v1.2.3 From c373640a3ac6c2f76f0a8dce4e44236154ca24bc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:28:44 -0800 Subject: Refactor --- backends/verilog/verilog_backend.cc | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 04191443a..66a9e70d3 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -293,7 +293,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } -void dump_reg_init(std::ostream &f, SigSpec sig) +void dump_reg_init(std::ostream &f, SigSpec sig, bool write_equals = true) { Const initval; bool gotinit = false; @@ -308,7 +308,7 @@ void dump_reg_init(std::ostream &f, SigSpec sig) } if (gotinit) { - f << " = "; + if (write_equals) f << " = "; dump_const(f, initval); } } @@ -1249,25 +1249,9 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) std::string init; if (cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { - auto q_wire = cell->getPort("\\Q"); - - Const initval; - bool gotinit = false; - - for (auto bit : active_sigmap(q_wire)) { - if (active_initdata.count(bit)) { - initval.bits.push_back(active_initdata.at(bit)); - gotinit = true; - } else { - initval.bits.push_back(State::Sx); - } - } - - if (gotinit) { - std::stringstream ss; - dump_const(ss, initval); - init = ss.str(); - } + std::stringstream ss; + dump_reg_init(ss, cell->getPort("\\Q"), false /* write_equals */); + init = ss.str(); } if (!defparam && (cell->parameters.size() > 0 || !init.empty())) { -- cgit v1.2.3 From 20ca795b87b810063cdcee6e92e3922281f6b092 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:53:40 -0800 Subject: Remove check for cell->name[0] == '$' --- backends/verilog/verilog_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 66a9e70d3..7b3a60e61 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1248,7 +1248,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" "%s", indent.c_str(), id(cell->type, false).c_str()); std::string init; - if (cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { + if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { std::stringstream ss; dump_reg_init(ss, cell->getPort("\\Q"), false /* write_equals */); init = ss.str(); -- cgit v1.2.3 From db08afe146b885777bb1bfa2260c090d9554afe3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 14:53:12 -0800 Subject: Copy backends/aiger/aiger.cc to xaiger.cc --- backends/aiger/xaiger.cc | 788 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 backends/aiger/xaiger.cc (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc new file mode 100644 index 000000000..dfe506c66 --- /dev/null +++ b/backends/aiger/xaiger.cc @@ -0,0 +1,788 @@ +/* + * 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. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void aiger_encode(std::ostream &f, int x) +{ + log_assert(x >= 0); + + while (x & ~0x7f) { + f.put((x & 0x7f) | 0x80); + x = x >> 7; + } + + f.put(x); +} + +struct AigerWriter +{ + Module *module; + bool zinit_mode; + SigMap sigmap; + + dict init_map; + pool input_bits, output_bits; + dict not_map, ff_map, alias_map; + dict> and_map; + vector> asserts, assumes; + vector> liveness, fairness; + pool initstate_bits; + + vector> aig_gates; + vector aig_latchin, aig_latchinit, aig_outputs; + int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; + int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; + + dict aig_map; + dict ordered_outputs; + dict ordered_latches; + + dict init_inputs; + int initstate_ff = 0; + + int mkgate(int a0, int a1) + { + aig_m++, aig_a++; + aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0)); + return 2*aig_m; + } + + int bit2aig(SigBit bit) + { + if (aig_map.count(bit) == 0) + { + aig_map[bit] = -1; + + if (initstate_bits.count(bit)) { + log_assert(initstate_ff > 0); + aig_map[bit] = initstate_ff; + } else + if (not_map.count(bit)) { + int a = bit2aig(not_map.at(bit)) ^ 1; + aig_map[bit] = a; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + aig_map[bit] = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + aig_map[bit] = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) + log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + } + + log_assert(aig_map.at(bit) >= 0); + return aig_map.at(bit); + } + + AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + { + pool undriven_bits; + pool unused_bits; + + // promote public wires + for (auto wire : module->wires()) + if (wire->name[0] == '\\') + sigmap.add(wire); + + // promote input wires + for (auto wire : module->wires()) + if (wire->port_input) + sigmap.add(wire); + + // promote output wires + for (auto wire : module->wires()) + if (wire->port_output) + sigmap.add(wire); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_map[initsig[i]] = initval[i] == State::S1; + } + + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); + + if (bit.wire == nullptr) { + if (wire->port_output) { + aig_map[wirebit] = (bit == State::S1) ? 1 : 0; + output_bits.insert(wirebit); + } + continue; + } + + undriven_bits.insert(bit); + unused_bits.insert(bit); + + if (wire->port_input) + input_bits.insert(bit); + + if (wire->port_output) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + } + + for (auto bit : input_bits) + undriven_bits.erase(bit); + + for (auto bit : output_bits) + unused_bits.erase(bit); + + for (auto cell : module->cells()) + { + if (cell->type == "$_NOT_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + undriven_bits.erase(Y); + not_map[Y] = A; + continue; + } + + if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + { + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + unused_bits.erase(D); + undriven_bits.erase(Q); + ff_map[Q] = D; + continue; + } + + if (cell->type == "$_AND_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit B = sigmap(cell->getPort("\\B").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + unused_bits.erase(B); + undriven_bits.erase(Y); + and_map[Y] = make_pair(A, B); + continue; + } + + if (cell->type == "$initstate") + { + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + undriven_bits.erase(Y); + initstate_bits.insert(Y); + continue; + } + + if (cell->type == "$assert") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + asserts.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$assume") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + assumes.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$live") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + liveness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$fair") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + fairness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$anyconst") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + ff_map[bit] = bit; + } + continue; + } + + if (cell->type == "$anyseq") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + input_bits.insert(bit); + } + continue; + } + + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + } + + for (auto bit : unused_bits) + undriven_bits.erase(bit); + + if (!undriven_bits.empty()) { + undriven_bits.sort(); + for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + input_bits.insert(bit); + } + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + } + + init_map.sort(); + input_bits.sort(); + output_bits.sort(); + not_map.sort(); + ff_map.sort(); + and_map.sort(); + + aig_map[State::S0] = 0; + aig_map[State::S1] = 1; + + for (auto bit : input_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + if (imode && input_bits.empty()) { + aig_m++, aig_i++; + } + + if (zinit_mode) + { + for (auto it : ff_map) { + if (init_map.count(it.first)) + continue; + aig_m++, aig_i++; + init_inputs[it.first] = 2*aig_m; + } + } + + int fair_live_inputs_cnt = GetSize(liveness); + int fair_live_inputs_m = aig_m; + + aig_m += fair_live_inputs_cnt; + aig_i += fair_live_inputs_cnt; + + for (auto it : ff_map) { + aig_m++, aig_l++; + aig_map[it.first] = 2*aig_m; + ordered_latches[it.first] = aig_l-1; + if (init_map.count(it.first) == 0) + aig_latchinit.push_back(2); + else + aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) { + aig_m++, aig_l++; + initstate_ff = 2*aig_m+1; + aig_latchinit.push_back(0); + } + + int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); + int fair_live_latches_m = aig_m; + int fair_live_latches_l = aig_l; + + aig_m += fair_live_latches_cnt; + aig_l += fair_live_latches_cnt; + + for (int i = 0; i < fair_live_latches_cnt; i++) + aig_latchinit.push_back(0); + + if (zinit_mode) + { + for (auto it : ff_map) + { + int l = ordered_latches[it.first]; + + if (aig_latchinit.at(l) == 1) + aig_map[it.first] ^= 1; + + if (aig_latchinit.at(l) == 2) + { + int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + } + } + } + + for (auto it : ff_map) { + int a = bit2aig(it.second); + int l = ordered_latches[it.first]; + if (zinit_mode && aig_latchinit.at(l) == 1) + aig_latchin.push_back(a ^ 1); + else + aig_latchin.push_back(a); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) + aig_latchin.push_back(1); + + for (auto bit : output_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + + if (omode && output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + } + + for (auto it : asserts) { + aig_b++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)); + } + + if (bmode && asserts.empty()) { + aig_b++; + aig_outputs.push_back(0); + } + + for (auto it : assumes) { + aig_c++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); + } + + for (auto it : liveness) + { + int input_m = ++fair_live_inputs_m; + int latch_m1 = ++fair_live_latches_m; + int latch_m2 = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 2; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_s = 2*input_m; + int bit_q1 = 2*latch_m1; + int bit_q2 = 2*latch_m2; + + int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; + int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; + + aig_j++; + aig_latchin.push_back(bit_d1); + aig_latchin.push_back(bit_d2); + aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); + } + + for (auto it : fairness) + { + int latch_m = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 1; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_q = 2*latch_m; + + aig_f++; + aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); + aig_outputs.push_back(bit_q^1); + } + } + + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + { + int aig_obc = aig_o + aig_b + aig_c; + int aig_obcj = aig_obc + aig_j; + int aig_obcjf = aig_obcj + aig_f; + + log_assert(aig_m == aig_i + aig_l + aig_a); + log_assert(aig_l == GetSize(aig_latchin)); + log_assert(aig_l == GetSize(aig_latchinit)); + log_assert(aig_obcjf == GetSize(aig_outputs)); + + if (miter_mode) { + if (aig_b || aig_c || aig_j || aig_f) + log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); + f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); + } else { + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + if (aig_b || aig_c || aig_j || aig_f) + f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); + f << stringf("\n"); + } + + if (ascii_mode) + { + for (int i = 0; i < aig_i; i++) + f << stringf("%d\n", 2*i+2); + + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) + f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second); + } + else + { + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d 1\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) { + int lhs = 2*(aig_i+aig_l+i)+2; + int rhs0 = aig_gates.at(i).first; + int rhs1 = aig_gates.at(i).second; + int delta0 = lhs - rhs0; + int delta1 = rhs0 - rhs1; + aiger_encode(f, delta0); + aiger_encode(f, delta1); + } + } + + if (symbols_mode) + { + dict> symbols; + + for (auto wire : module->wires()) + { + if (wire->name[0] == '$') + continue; + + SigSpec sig = sigmap(wire); + + for (int i = 0; i < GetSize(wire); i++) + { + if (sig[i].wire == nullptr) { + if (wire->port_output) + sig[i] = SigBit(wire, i); + else + continue; + } + + if (wire->port_input) { + int a = aig_map.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); + } + + if (wire->port_output) { + int o = ordered_outputs.at(SigSpec(wire, i)); + if (GetSize(wire) != 1) + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; + if (GetSize(wire) != 1) + symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); + else + symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); + } + } + } + + symbols.sort(); + + for (auto &sym : symbols) { + f << sym.first; + std::sort(sym.second.begin(), sym.second.end()); + for (auto &s : sym.second) + f << " " << s; + f << std::endl; + } + } + + f << stringf("c\nGenerated by %s\n", yosys_version_str); + } + + void write_map(std::ostream &f, bool verbose_map) + { + dict input_lines; + dict init_lines; + dict output_lines; + dict latch_lines; + dict wire_lines; + + for (auto wire : module->wires()) + { + if (!verbose_map && wire->name[0] == '$') + continue; + + SigSpec sig = sigmap(wire); + + for (int i = 0; i < GetSize(wire); i++) + { + if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + continue; + + int a = aig_map.at(sig[i]); + + if (verbose_map) + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); + + if (wire->port_input) { + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (wire->port_output) { + int o = ordered_outputs.at(sig[i]); + output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + if (zinit_mode && (aig_latchinit.at(l) == 1)) + latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); + else + latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + } + } + } + + input_lines.sort(); + for (auto &it : input_lines) + f << it.second; + + init_lines.sort(); + for (auto &it : init_lines) + f << it.second; + + output_lines.sort(); + for (auto &it : output_lines) + f << it.second; + + latch_lines.sort(); + for (auto &it : latch_lines) + f << it.second; + + wire_lines.sort(); + for (auto &it : wire_lines) + f << it.second; + } +}; + +struct AigerBackend : public Backend { + AigerBackend() : Backend("aiger", "write design to AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_aiger [options] [filename]\n"); + log("\n"); + log("Write the current design to an AIGER file. The design must be flattened and\n"); + log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); + log("$assert and $assume cells, and $initstate cells.\n"); + log("\n"); + log("$assert and $assume cells are converted to AIGER bad state properties and\n"); + log("invariant constraints.\n"); + log("\n"); + log(" -ascii\n"); + log(" write ASCII version of AGIER format\n"); + log("\n"); + log(" -zinit\n"); + log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); + log(" uninitialized FFs.\n"); + log("\n"); + log(" -miter\n"); + log(" design outputs are AIGER bad state properties\n"); + log("\n"); + log(" -symbols\n"); + log(" include a symbol table in the generated AIGER file\n"); + log("\n"); + log(" -map \n"); + log(" write an extra file with port and latch symbols\n"); + log("\n"); + log(" -vmap \n"); + log(" like -map, but more verbose\n"); + log("\n"); + log(" -I, -O, -B\n"); + log(" If the design contains no input/output/assert then create one\n"); + log(" dummy input/output/bad_state pin to make the tools reading the\n"); + log(" AIGER file happy.\n"); + log("\n"); + } + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + bool ascii_mode = false; + bool zinit_mode = false; + bool miter_mode = false; + bool symbols_mode = false; + bool verbose_map = false; + bool imode = false; + bool omode = false; + bool bmode = false; + std::string map_filename; + + log_header(design, "Executing AIGER backend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-ascii") { + ascii_mode = true; + continue; + } + if (args[argidx] == "-zinit") { + zinit_mode = true; + continue; + } + if (args[argidx] == "-miter") { + miter_mode = true; + continue; + } + if (args[argidx] == "-symbols") { + symbols_mode = true; + continue; + } + if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + continue; + } + if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + verbose_map = true; + continue; + } + if (args[argidx] == "-I") { + imode = true; + continue; + } + if (args[argidx] == "-O") { + omode = true; + continue; + } + if (args[argidx] == "-B") { + bmode = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + Module *top_module = design->top_module(); + + if (top_module == nullptr) + log_error("Can't find top module in current design!\n"); + + AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + + if (!map_filename.empty()) { + std::ofstream mapf; + mapf.open(map_filename.c_str(), std::ofstream::trunc); + if (mapf.fail()) + log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); + writer.write_map(mapf, verbose_map); + } + } +} AigerBackend; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From ecd24461323d4dc0cd369d3173a39912aa459618 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 15:18:42 -0800 Subject: Add write_xaiger --- backends/aiger/Makefile.inc | 1 + backends/aiger/xaiger.cc | 31 ++++++++++--------------------- 2 files changed, 11 insertions(+), 21 deletions(-) (limited to 'backends') diff --git a/backends/aiger/Makefile.inc b/backends/aiger/Makefile.inc index 0fc37e95c..4a4cf30bd 100644 --- a/backends/aiger/Makefile.inc +++ b/backends/aiger/Makefile.inc @@ -1,3 +1,4 @@ OBJS += backends/aiger/aiger.o +OBJS += backends/aiger/xaiger.o diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dfe506c66..7fc61fa9a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -35,7 +35,7 @@ void aiger_encode(std::ostream &f, int x) f.put(x); } -struct AigerWriter +struct XAigerWriter { Module *module; bool zinit_mode; @@ -100,7 +100,7 @@ struct AigerWriter return aig_map.at(bit); } - AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -669,20 +669,16 @@ struct AigerWriter } }; -struct AigerBackend : public Backend { - AigerBackend() : Backend("aiger", "write design to AIGER file") { } +struct XAigerBackend : public Backend { + XAigerBackend() : Backend("xaiger", "write design to XAIGER file") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" write_aiger [options] [filename]\n"); + log(" write_xaiger [options] [filename]\n"); log("\n"); - log("Write the current design to an AIGER file. The design must be flattened and\n"); - log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); - log("$assert and $assume cells, and $initstate cells.\n"); - log("\n"); - log("$assert and $assume cells are converted to AIGER bad state properties and\n"); - log("invariant constraints.\n"); + log("Write the current design to an XAIGER file. The design must be flattened and\n"); + log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AGIER format\n"); @@ -691,9 +687,6 @@ struct AigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -miter\n"); - log(" design outputs are AIGER bad state properties\n"); - log("\n"); log(" -symbols\n"); log(" include a symbol table in the generated AIGER file\n"); log("\n"); @@ -721,7 +714,7 @@ struct AigerBackend : public Backend { bool bmode = false; std::string map_filename; - log_header(design, "Executing AIGER backend.\n"); + log_header(design, "Executing XAIGER backend.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -734,10 +727,6 @@ struct AigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-miter") { - miter_mode = true; - continue; - } if (args[argidx] == "-symbols") { symbols_mode = true; continue; @@ -772,7 +761,7 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { @@ -783,6 +772,6 @@ struct AigerBackend : public Backend { writer.write_map(mapf, verbose_map); } } -} AigerBackend; +} XAigerBackend; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From afa4389445adc8e53871af78ab1c38c98e03a6fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 13:27:26 -0800 Subject: Get rid of formal stuff from xaiger backend --- backends/aiger/xaiger.cc | 58 ------------------------------------------------ 1 file changed, 58 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7fc61fa9a..c5cede3b1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -205,64 +205,6 @@ struct XAigerWriter continue; } - if (cell->type == "$assert") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - asserts.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$assume") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - assumes.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$live") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - liveness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$fair") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - fairness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$anyconst") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - ff_map[bit] = bit; - } - continue; - } - - if (cell->type == "$anyseq") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - input_bits.insert(bit); - } - continue; - } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } -- cgit v1.2.3 From 732877558475788992ad822f28a99fd16336e05a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:48:38 -0800 Subject: More cleanup of write_xaiger --- backends/aiger/xaiger.cc | 74 +----------------------------------------------- 1 file changed, 1 insertion(+), 73 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c5cede3b1..758513cd4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -45,8 +45,6 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - vector> asserts, assumes; - vector> liveness, fairness; pool initstate_bits; vector> aig_gates; @@ -249,12 +247,6 @@ struct XAigerWriter } } - int fair_live_inputs_cnt = GetSize(liveness); - int fair_live_inputs_m = aig_m; - - aig_m += fair_live_inputs_cnt; - aig_i += fair_live_inputs_cnt; - for (auto it : ff_map) { aig_m++, aig_l++; aig_map[it.first] = 2*aig_m; @@ -271,16 +263,6 @@ struct XAigerWriter aig_latchinit.push_back(0); } - int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); - int fair_live_latches_m = aig_m; - int fair_live_latches_l = aig_l; - - aig_m += fair_live_latches_cnt; - aig_l += fair_live_latches_cnt; - - for (int i = 0; i < fair_live_latches_cnt; i++) - aig_latchinit.push_back(0); - if (zinit_mode) { for (auto it : ff_map) @@ -322,64 +304,10 @@ struct XAigerWriter aig_outputs.push_back(0); } - for (auto it : asserts) { - aig_b++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)); - } - - if (bmode && asserts.empty()) { + if (bmode) { aig_b++; aig_outputs.push_back(0); } - - for (auto it : assumes) { - aig_c++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); - } - - for (auto it : liveness) - { - int input_m = ++fair_live_inputs_m; - int latch_m1 = ++fair_live_latches_m; - int latch_m2 = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 2; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_s = 2*input_m; - int bit_q1 = 2*latch_m1; - int bit_q2 = 2*latch_m2; - - int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; - int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; - - aig_j++; - aig_latchin.push_back(bit_d1); - aig_latchin.push_back(bit_d2); - aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); - } - - for (auto it : fairness) - { - int latch_m = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 1; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_q = 2*latch_m; - - aig_f++; - aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); - aig_outputs.push_back(bit_q^1); - } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) -- cgit v1.2.3 From c69fba8de5056e5892014b143856993d404e7c84 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:52:47 -0800 Subject: More cleanup --- backends/aiger/xaiger.cc | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 758513cd4..4155c5281 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; dict aig_map; dict ordered_outputs; @@ -305,32 +304,24 @@ struct XAigerWriter } if (bmode) { - aig_b++; + //aig_b++; aig_outputs.push_back(0); } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) { - int aig_obc = aig_o + aig_b + aig_c; - int aig_obcj = aig_obc + aig_j; - int aig_obcjf = aig_obcj + aig_f; + int aig_obc = aig_o; + int aig_obcj = aig_obc; + int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); log_assert(aig_l == GetSize(aig_latchin)); log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); - if (miter_mode) { - if (aig_b || aig_c || aig_j || aig_f) - log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); - f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); - } else { - f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); - if (aig_b || aig_c || aig_j || aig_f) - f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); - f << stringf("\n"); - } + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + f << stringf("\n"); if (ascii_mode) { -- cgit v1.2.3 From fc1c9aa11fbfbb1ea5b63e1830549d453ba01dfb Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 15 Feb 2019 11:14:17 -0800 Subject: Update cells supported for verilog to FIRRTL conversion. Issue warning messages for missing parameterized modules and attempts to set initial values. Replace simple "if (cell-type)" with "else if" chain. Fix FIRRTL shift handling. Add support for parameterized modules, $shift, $shiftx. Handle default output file. Deal with no top module. Automatically run pmuxtree pass. Allow EXTRA_FLAGS and SEED parameters to be set in the environment for tests/tools/autotest.mk. Support FIRRTL regression testing in tests/tools/autotest.sh Add xfirrtl files to test directories to exclude files from FIRRTL regression tests that are known to fail. --- backends/firrtl/firrtl.cc | 273 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 225 insertions(+), 48 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 32410a651..7ca5dc756 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -23,7 +23,11 @@ #include "kernel/celltypes.h" #include "kernel/cellaigs.h" #include "kernel/log.h" +#include #include +#include +#include +#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -37,6 +41,7 @@ static const FDirection FD_NODIRECTION = 0x0; static const FDirection FD_IN = 0x1; static const FDirection FD_OUT = 0x2; static const FDirection FD_INOUT = 0x3; +static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width // Get a port direction with respect to a specific module. FDirection getPortFDirection(IdString id, Module *module) @@ -91,6 +96,23 @@ const char *make_id(IdString id) return namecache.at(id).c_str(); } +static std::vector Tokenize( const string str, const std::regex regex ) +{ + using namespace std; + + std::vector result; + + sregex_token_iterator it( str.begin(), str.end(), regex, -1 ); + sregex_token_iterator reg_end; + + for ( ; it != reg_end; ++it ) { + if ( !it->str().empty() ) //token could be empty:check + result.emplace_back( it->str() ); + } + + return result; +} + struct FirrtlWorker { Module *module; @@ -173,6 +195,26 @@ struct FirrtlWorker void process_instance(RTLIL::Cell *cell, vector &wire_exprs) { std::string cell_type = fid(cell->type); + std::string instanceOf; + // If this is a parameterized module, its parent module is encoded in the cell type + if (cell->type.substr(0, 8) == "$paramod") + { + std::string::iterator it; + for (it = cell_type.begin(); it < cell_type.end(); it++) + { + switch (*it) { + case '\\': /* FALL_THROUGH */ + case '=': /* FALL_THROUGH */ + case '\'': /* FALL_THROUGH */ + case '$': instanceOf.append("_"); break; + default: instanceOf.append(1, *it); break; + } + } + } + else + { + instanceOf = cell_type; + } std::string cell_name = cellname(cell); std::string cell_name_comment; @@ -182,7 +224,13 @@ struct FirrtlWorker cell_name_comment = ""; // Find the module corresponding to this instance. auto instModule = design->module(cell->type); - wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), cell_type.c_str())); + // If there is no instance for this, just return. + if (instModule == NULL) + { + log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); + return; + } + wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->second.size() > 0) { @@ -194,20 +242,20 @@ struct FirrtlWorker std::string source, sink; switch (dir) { case FD_INOUT: - log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second)); + log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); case FD_OUT: source = firstName; sink = secondName; break; case FD_NODIRECTION: - log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second)); + log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); /* FALL_THROUGH */ case FD_IN: source = secondName; sink = firstName; break; default: - log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", log_id(cell_type), log_signal(it->second), dir); + log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); break; } wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); @@ -217,6 +265,20 @@ struct FirrtlWorker } + // Given an expression for a shift amount, and a maximum width, + // generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics. + std::string gen_dshl(const string b_expr, const int b_padded_width) + { + string result = b_expr; + if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { + int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1; + string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<name)); @@ -225,6 +287,12 @@ struct FirrtlWorker for (auto wire : module->wires()) { const auto wireName = make_id(wire->name); + // If a wire has initial data, issue a warning since FIRRTL doesn't currently support it. + if (wire->attributes.count("\\init")) { + log_warning("Initial value (%s) for (%s.%s) not supported\n", + wire->attributes.at("\\init").as_string().c_str(), + log_id(module), log_id(wire)); + } if (wire->port_id) { if (wire->port_input && wire->port_output) @@ -240,7 +308,8 @@ struct FirrtlWorker for (auto cell : module->cells()) { - // Is this cell is a module instance? + bool extract_y_bits = false; // Assume no extraction of final bits will be required. + // Is this cell is a module instance? if (cell->type[0] != '$') { process_instance(cell, wire_exprs); @@ -264,21 +333,21 @@ struct FirrtlWorker } string primop; - bool always_uint = false; + bool always_uint = false; if (cell->type == "$not") primop = "not"; - if (cell->type == "$neg") primop = "neg"; - if (cell->type == "$logic_not") { + else if (cell->type == "$neg") primop = "neg"; + else if (cell->type == "$logic_not") { primop = "eq"; a_expr = stringf("%s, UInt(0)", a_expr.c_str()); } - if (cell->type == "$reduce_and") primop = "andr"; - if (cell->type == "$reduce_or") primop = "orr"; - if (cell->type == "$reduce_xor") primop = "xorr"; - if (cell->type == "$reduce_xnor") { + else if (cell->type == "$reduce_and") primop = "andr"; + else if (cell->type == "$reduce_or") primop = "orr"; + else if (cell->type == "$reduce_xor") primop = "xorr"; + else if (cell->type == "$reduce_xnor") { primop = "not"; a_expr = stringf("xorr(%s)", a_expr.c_str()); } - if (cell->type == "$reduce_bool") { + else if (cell->type == "$reduce_bool") { primop = "neq"; // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool(); @@ -297,14 +366,16 @@ struct FirrtlWorker continue; } if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx", - "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", - "$logic_and", "$logic_or")) + "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", + "$logic_and", "$logic_or")) { string y_id = make_id(cell->name); bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); + int a_padded_width = cell->parameters.at("\\A_WIDTH").as_int(); string b_expr = make_expr(cell->getPort("\\B")); + int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); if (cell->parameters.at("\\A_SIGNED").as_bool()) { @@ -315,67 +386,93 @@ struct FirrtlWorker if (cell->parameters.at("\\B_SIGNED").as_bool()) { b_expr = "asSInt(" + b_expr + ")"; } - b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); + if (b_padded_width < y_width) { + auto b_sig = cell->getPort("\\B"); + b_padded_width = y_width; + } } - a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + auto a_sig = cell->getPort("\\A"); if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { a_expr = "asUInt(" + a_expr + ")"; } string primop; - bool always_uint = false; + bool always_uint = false; if (cell->type == "$add") primop = "add"; - if (cell->type == "$sub") primop = "sub"; - if (cell->type == "$mul") primop = "mul"; - if (cell->type == "$div") primop = "div"; - if (cell->type == "$mod") primop = "rem"; - if (cell->type == "$and") { + else if (cell->type == "$sub") primop = "sub"; + else if (cell->type == "$mul") primop = "mul"; + else if (cell->type == "$div") primop = "div"; + else if (cell->type == "$mod") primop = "rem"; + else if (cell->type == "$and") { primop = "and"; always_uint = true; } - if (cell->type == "$or" ) { + else if (cell->type == "$or" ) { primop = "or"; always_uint = true; } - if (cell->type == "$xor") { + else if (cell->type == "$xor") { primop = "xor"; always_uint = true; } - if ((cell->type == "$eq") | (cell->type == "$eqx")) { + else if ((cell->type == "$eq") | (cell->type == "$eqx")) { primop = "eq"; always_uint = true; } - if ((cell->type == "$ne") | (cell->type == "$nex")) { + else if ((cell->type == "$ne") | (cell->type == "$nex")) { primop = "neq"; always_uint = true; } - if (cell->type == "$gt") { + else if (cell->type == "$gt") { primop = "gt"; always_uint = true; } - if (cell->type == "$ge") { + else if (cell->type == "$ge") { primop = "geq"; always_uint = true; } - if (cell->type == "$lt") { + else if (cell->type == "$lt") { primop = "lt"; always_uint = true; } - if (cell->type == "$le") { + else if (cell->type == "$le") { primop = "leq"; always_uint = true; } - if ((cell->type == "$shl") | (cell->type == "$sshl")) primop = "dshl"; - if ((cell->type == "$shr") | (cell->type == "$sshr")) primop = "dshr"; - if ((cell->type == "$logic_and")) { + else if ((cell->type == "$shl") | (cell->type == "$sshl")) { + // FIRRTL will widen the result (y) by the amount of the shift. + // We'll need to offset this by extracting the un-widened portion as Verilog would do. + extract_y_bits = true; + // Is the shift amount constant? + auto b_sig = cell->getPort("\\B"); + if (b_sig.is_fully_const()) { + primop = "shl"; + } else { + primop = "dshl"; + // Convert from FIRRTL left shift semantics. + b_expr = gen_dshl(b_expr, b_padded_width); + } + } + else if ((cell->type == "$shr") | (cell->type == "$sshr")) { + // We don't need to extract a specific range of bits. + extract_y_bits = false; + // Is the shift amount constant? + auto b_sig = cell->getPort("\\B"); + if (b_sig.is_fully_const()) { + primop = "shr"; + } else { + primop = "dshr"; + } + } + else if ((cell->type == "$logic_and")) { primop = "and"; a_expr = "neq(" + a_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))"; always_uint = true; } - if ((cell->type == "$logic_or")) { + else if ((cell->type == "$logic_or")) { primop = "or"; a_expr = "neq(" + a_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))"; @@ -388,6 +485,11 @@ struct FirrtlWorker string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); + // Deal with FIRRTL's "shift widens" semantics + if (extract_y_bits) { + expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); + } + if ((is_signed && !always_uint) || cell->type.in("$sub")) expr = stringf("asUInt(%s)", expr.c_str()); @@ -513,7 +615,67 @@ struct FirrtlWorker continue; } - log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + // This may be a parameterized module - paramod. + if (cell->type.substr(0, 8) == "$paramod") + { + auto paramod_module = log_id(module); + auto paramod_instance = log_id(cell); + process_instance(cell, wire_exprs); + continue; + } + if (cell->type == "$shiftx") { + // assign y = a[b +: y_width]; + // We'll extract the correct bits as part of the primop. + + string y_id = make_id(cell->name); + int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); + string a_expr = make_expr(cell->getPort("\\A")); + // Get the initial bit selector + string b_expr = make_expr(cell->getPort("\\B")); + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + + if (cell->getParam("\\B_SIGNED").as_bool()) { + // Use validif to constrain the selection (test the sign bit) + auto b_string = b_expr.c_str(); + int b_sign = cell->parameters.at("\\B_WIDTH").as_int() - 1; + b_expr = stringf("validif(not(bits(%s, %d, %d)), %s)", b_string, b_sign, b_sign, b_string); + } + string expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_expr.c_str()); + + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); + continue; + } + if (cell->type == "$shift") { + // assign y = a >> b; + // where b may be negative + + string y_id = make_id(cell->name); + int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); + string a_expr = make_expr(cell->getPort("\\A")); + string b_expr = make_expr(cell->getPort("\\B")); + auto b_string = b_expr.c_str(); + int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); + string expr; + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + + if (cell->getParam("\\B_SIGNED").as_bool()) { + // We generate a left or right shift based on the sign of b. + std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width); + std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); + expr = stringf("mux(%s < 0, %s, %s)", + b_string, + dshl.c_str(), + dshr.c_str() + ); + } else { + expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); + } + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); + continue; + } + log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); } for (auto conn : module->connections()) @@ -629,38 +791,53 @@ struct FirrtlBackend : public Backend { log(" write_firrtl [options] [filename]\n"); log("\n"); log("Write a FIRRTL netlist of the current design.\n"); + log("The following commands are executed by this command:\n"); + log(" pmuxtree\n"); log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - // if (args[argidx] == "-aig") { - // aig_mode = true; - // continue; - // } - break; + size_t argidx = args.size(); // We aren't expecting any arguments. + + // If we weren't explicitly passed a filename, use the last argument (if it isn't a flag). + if (filename == "") { + if (argidx > 0 && args[argidx - 1][0] != '-') { + // extra_args and friends need to see this argument. + argidx -= 1; + filename = args[argidx]; + } } extra_args(f, filename, args, argidx); - log_header(design, "Executing FIRRTL backend.\n"); + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); - Module *top = design->top_module(); + log_header(design, "Executing FIRRTL backend.\n"); + log_push(); - if (top == nullptr) - log_error("No top module found!\n"); + Pass::call(design, stringf("pmuxtree")); namecache.clear(); autoid_counter = 0; + // Get the top module, or a reasonable facsimile - we need something for the circuit name. + Module *top = design->top_module(); + Module *last = nullptr; + // Generate module and wire names. for (auto module : design->modules()) { make_id(module->name); + last = module; + if (top == nullptr && module->get_bool_attribute("\\top")) { + top = module; + } for (auto wire : module->wires()) if (wire->port_id) make_id(wire->name); } + if (top == nullptr) + top = last; + *f << stringf("circuit %s:\n", make_id(top->name)); for (auto module : design->modules()) -- cgit v1.2.3 From 3ac5b651973debe76d4d41aef86a9d6376bdae46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 11:51:21 -0800 Subject: write_xaiger to cope with unknown cells by transforming them to CI/CO --- backends/aiger/xaiger.cc | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4155c5281..433f1cdd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -46,6 +46,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; + pool ci_bits, co_bits; + dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -149,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } } } @@ -166,6 +168,8 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -187,6 +191,8 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -202,7 +208,27 @@ struct XAigerWriter continue; } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + unused_bits.erase(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + if (!w->port_output) + ci_bits.insert(O); + undriven_bits.erase(O); + } + else log_abort(); + if (!type_map.count(cell->type)) + type_map[cell->type] = type_map.size()+1; + } + //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : unused_bits) @@ -227,6 +253,12 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; + for (auto bit : ci_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + co_bits.erase(bit); + } + for (auto bit : input_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; @@ -292,6 +324,12 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); + for (auto bit : co_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + for (auto bit : output_bits) { aig_o++; ordered_outputs[bit] = aig_o-1; @@ -467,8 +505,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (!verbose_map && wire->name[0] == '$') - continue; + //if (!verbose_map && wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -482,12 +520,12 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input) { + if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output) { + if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From c245041bfe2ee0d5b5504fa5e9459ac52e836c33 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 15 Feb 2019 12:00:28 -0800 Subject: Removed unused variables, functions. --- backends/firrtl/firrtl.cc | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 7ca5dc756..0917ecba6 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -96,23 +96,6 @@ const char *make_id(IdString id) return namecache.at(id).c_str(); } -static std::vector Tokenize( const string str, const std::regex regex ) -{ - using namespace std; - - std::vector result; - - sregex_token_iterator it( str.begin(), str.end(), regex, -1 ); - sregex_token_iterator reg_end; - - for ( ; it != reg_end; ++it ) { - if ( !it->str().empty() ) //token could be empty:check - result.emplace_back( it->str() ); - } - - return result; -} - struct FirrtlWorker { Module *module; @@ -373,7 +356,6 @@ struct FirrtlWorker bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); - int a_padded_width = cell->parameters.at("\\A_WIDTH").as_int(); string b_expr = make_expr(cell->getPort("\\B")); int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); @@ -618,8 +600,6 @@ struct FirrtlWorker // This may be a parameterized module - paramod. if (cell->type.substr(0, 8) == "$paramod") { - auto paramod_module = log_id(module); - auto paramod_instance = log_id(cell); process_instance(cell, wire_exprs); continue; } -- cgit v1.2.3 From 486a2704156c51e1331e69cd5160965a1ef73506 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 15:22:18 -0800 Subject: Fixes needed for DFF circuits --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 433f1cdd6..27e156a98 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } continue; } @@ -220,8 +220,7 @@ struct XAigerWriter } else if (cell->output(c.first)) { SigBit O = sigmap(b); - if (!w->port_output) - ci_bits.insert(O); + ci_bits.insert(O); undriven_bits.erase(O); } else log_abort(); @@ -525,7 +524,7 @@ struct XAigerWriter input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { + if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From 2c1655ae9440c470a62ab7e493024a94f5d054ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:46:25 -0800 Subject: write_aiger() to perform CI/CO post-processing and fix symbols --- backends/aiger/xaiger.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 27e156a98..3d0968cad 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -216,12 +216,10 @@ struct XAigerWriter SigBit I = sigmap(b); if (!w->port_input) co_bits.insert(I); - unused_bits.erase(I); } else if (cell->output(c.first)) { SigBit O = sigmap(b); ci_bits.insert(O); - undriven_bits.erase(O); } else log_abort(); if (!type_map.count(cell->type)) @@ -230,6 +228,19 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + // Do some CI/CO post-processing: + // Erase all COs that are undriven + for (auto bit : undriven_bits) + co_bits.erase(bit); + // Erase all CIs that are also COs or POs + for (auto bit : co_bits) + ci_bits.erase(bit); + for (auto bit : output_bits) + ci_bits.erase(bit); + // CIs cannot be undriven + for (auto bit : ci_bits) + undriven_bits.erase(bit); + for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -255,7 +266,6 @@ struct XAigerWriter for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; - co_bits.erase(bit); } for (auto bit : input_bits) { @@ -429,8 +439,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->name[0] == '$') - continue; + //if (wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -443,7 +453,7 @@ struct XAigerWriter continue; } - if (wire->port_input) { + if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -452,7 +462,7 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (wire->port_output) { + if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { int o = ordered_outputs.at(SigSpec(wire, i)); if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); -- cgit v1.2.3 From 0c409e6d8cd51360b3099a725fdad6174a2dbb66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:48:33 -0800 Subject: Tidy up write_xaiger --- backends/aiger/xaiger.cc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d0968cad..c0bd9e921 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } @@ -151,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } } } @@ -168,8 +168,6 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -191,8 +189,6 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -229,9 +225,11 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all COs that are undriven - for (auto bit : undriven_bits) + // Erase all POs and COs that are undriven + for (auto bit : undriven_bits) { co_bits.erase(bit); + output_bits.erase(bit); + } // Erase all CIs that are also COs or POs for (auto bit : co_bits) ci_bits.erase(bit); -- cgit v1.2.3 From b9a305b85d17ce61880ee057e19e5ceafd7a6c05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 20:08:59 -0800 Subject: write_aiger -O to write dummy output as __dummy_o__ --- backends/aiger/xaiger.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c0bd9e921..25e03fa5f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -502,7 +502,7 @@ struct XAigerWriter f << stringf("c\nGenerated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map) + void write_map(std::ostream &f, bool verbose_map, bool omode) { dict input_lines; dict init_lines; @@ -564,6 +564,9 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + if (omode && output_bits.empty()) { + f << "output 0 0 __dummy_o__\n"; + } latch_lines.sort(); for (auto &it : latch_lines) @@ -675,7 +678,7 @@ struct XAigerBackend : public Backend { mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf, verbose_map); + writer.write_map(mapf, verbose_map, omode); } } } XAigerBackend; -- cgit v1.2.3 From 6a57de90137df146529d84a04f70269382df8795 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:00:39 -0800 Subject: write_xaiger to support non-bit cell connections, and cope with COs for -O --- backends/aiger/xaiger.cc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25e03fa5f..456f3f899 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -206,18 +206,20 @@ struct XAigerWriter for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); - } - else if (cell->output(c.first)) { - SigBit O = sigmap(b); - ci_bits.insert(O); + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + ci_bits.insert(O); + } + else log_abort(); } - else log_abort(); if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } @@ -343,7 +345,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -564,7 +566,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { f << "output 0 0 __dummy_o__\n"; } -- cgit v1.2.3 From 76c35f80f4d2ad3b2e686186c9febc2872f5c9ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:09:48 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 456f3f899..ae296d395 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -566,9 +566,8 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; - } latch_lines.sort(); for (auto &it : latch_lines) -- cgit v1.2.3 From 30f1204721ed592256ddde04f22dd40888b9e27c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 22:22:17 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae296d395..d4686736d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -521,7 +521,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) continue; int a = aig_map.at(sig[i]); @@ -529,13 +529,14 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { + RTLIL::SigBit b(wire, i); + if (wire->port_input || ci_bits.count(b)) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { - int o = ordered_outputs.at(sig[i]); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From 11480b4fa3ba031541e22b52d9ccd658a3e52ff1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 12:18:12 -0800 Subject: Instead of INIT param on cells, use initial statement with hier ref as per @cliffordwolf --- backends/verilog/verilog_backend.cc | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 4b5a13941..d351a6266 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -293,7 +293,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } -void dump_reg_init(std::ostream &f, SigSpec sig, bool write_equals = true) +void dump_reg_init(std::ostream &f, SigSpec sig) { Const initval; bool gotinit = false; @@ -308,7 +308,7 @@ void dump_reg_init(std::ostream &f, SigSpec sig, bool write_equals = true) } if (gotinit) { - if (write_equals) f << " = "; + f << " = "; dump_const(f, initval); } } @@ -1250,14 +1250,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) dump_attributes(f, indent, cell->attributes); f << stringf("%s" "%s", indent.c_str(), id(cell->type, false).c_str()); - std::string init; - if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { - std::stringstream ss; - dump_reg_init(ss, cell->getPort("\\Q"), false /* write_equals */); - init = ss.str(); - } - - if (!defparam && (cell->parameters.size() > 0 || !init.empty())) { + if (!defparam && cell->parameters.size() > 0) { f << stringf(" #("); for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { if (it != cell->parameters.begin()) @@ -1267,11 +1260,6 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) dump_const(f, it->second, -1, 0, false, is_signed); f << stringf(")"); } - if (!init.empty()) { - if (!cell->parameters.empty()) - f << stringf(","); - f << stringf("\n%s .INIT(%s)", indent.c_str(), init.c_str()); - } f << stringf("\n%s" ")", indent.c_str()); } @@ -1313,17 +1301,24 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } f << stringf("\n%s" ");\n", indent.c_str()); - if (defparam && (cell->parameters.size() > 0 || !init.empty())) { + if (defparam && cell->parameters.size() > 0) { for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { f << stringf("%sdefparam %s.%s = ", indent.c_str(), cell_name.c_str(), id(it->first).c_str()); bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; dump_const(f, it->second, -1, 0, false, is_signed); f << stringf(";\n"); } - if (!init.empty()) - f << stringf("%sdefparam %s.INIT = %s;\n", indent.c_str(), cell_name.c_str(), init.c_str()); } + if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { + std::stringstream ss; + dump_reg_init(ss, cell->getPort("\\Q")); + if (!ss.str().empty()) { + f << stringf("%sinitial %s.Q", indent.c_str(), cell_name.c_str()); + f << ss.str(); + f << ";\n"; + } + } } void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) -- cgit v1.2.3 From ef60ca171743292e88457684d53d632c680210e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 11:09:13 -0800 Subject: write_xaiger to not write latches, CO/PO fixes --- backends/aiger/xaiger.cc | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d4686736d..d125335f9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -174,15 +174,15 @@ struct XAigerWriter continue; } - if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - { - SigBit D = sigmap(cell->getPort("\\D").as_bit()); - SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - ff_map[Q] = D; - continue; - } + //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + //{ + // SigBit D = sigmap(cell->getPort("\\D").as_bit()); + // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + // unused_bits.erase(D); + // undriven_bits.erase(Q); + // ff_map[Q] = D; + // continue; + //} if (cell->type == "$_AND_") { @@ -240,6 +240,9 @@ struct XAigerWriter // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); + // POs override COs + for (auto bit : output_bits) + co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -521,29 +524,25 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) - continue; - - int a = aig_map.at(sig[i]); - - if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - RTLIL::SigBit b(wire, i); if (wire->port_input || ci_bits.count(b)) { + int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + continue; } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (ordered_latches.count(sig[i])) { @@ -552,6 +551,15 @@ struct XAigerWriter latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); else latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + continue; + } + + if (verbose_map) { + if (aig_map.count(sig[i]) == 0) + continue; + + int a = aig_map.at(sig[i]); + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); } } } @@ -567,6 +575,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; -- cgit v1.2.3 From f89b112fbf19a751070406449ab78f07b2c5e639 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 15:35:32 -0800 Subject: write_aiger: fix CI/CO and symbols --- backends/aiger/.xaiger.cc.swo | Bin 0 -> 36864 bytes backends/aiger/xaiger.cc | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 backends/aiger/.xaiger.cc.swo (limited to 'backends') diff --git a/backends/aiger/.xaiger.cc.swo b/backends/aiger/.xaiger.cc.swo new file mode 100644 index 000000000..a12729835 Binary files /dev/null and b/backends/aiger/.xaiger.cc.swo differ diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d125335f9..56d361fff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -232,17 +232,22 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs or POs - for (auto bit : co_bits) + // Erase all POs and CIs that are also PIs + for (auto bit : input_bits) { + output_bits.erase(bit); ci_bits.erase(bit); - for (auto bit : output_bits) + } + for (auto bit : output_bits) { + ci_bits.erase(bit); + // POs override COs + co_bits.erase(bit); + } + // Erase all CIs that are also COs + for (auto bit : co_bits) ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); - // POs override COs - for (auto bit : output_bits) - co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -525,7 +530,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (wire->port_input || ci_bits.count(b)) { + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); @@ -567,6 +572,7 @@ struct XAigerWriter input_lines.sort(); for (auto &it : input_lines) f << it.second; + log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); init_lines.sort(); for (auto &it : init_lines) -- cgit v1.2.3 From 01f8d50ba239e98de1e6a75aec314caeae297bc8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 16:17:01 -0800 Subject: Remove swap file --- backends/aiger/.xaiger.cc.swo | Bin 36864 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backends/aiger/.xaiger.cc.swo (limited to 'backends') diff --git a/backends/aiger/.xaiger.cc.swo b/backends/aiger/.xaiger.cc.swo deleted file mode 100644 index a12729835..000000000 Binary files a/backends/aiger/.xaiger.cc.swo and /dev/null differ -- cgit v1.2.3 From 2f96a0ed32799eba95837d0b64953b889e607c22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:15:25 -0800 Subject: write_xaiger to use original bit for co, not sigmap()-ed bit --- backends/aiger/xaiger.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 56d361fff..b0602dbd8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -210,9 +210,12 @@ struct XAigerWriter Wire *w = b.wire; if (!w) continue; if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.insert(b); + } } else if (cell->output(c.first)) { SigBit O = sigmap(b); -- cgit v1.2.3 From 085ed9f4878e5a376bed6b7c59dc99db46140b41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:40:13 -0800 Subject: Add attribution --- backends/aiger/xaiger.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b0602dbd8..dd174d5ee 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2019 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 From 5180338e8085bdf0bc653e2321559c7504c169f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 17:03:18 -0800 Subject: write_xaiger to write __dummy_o__ for -symbols too --- backends/aiger/xaiger.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dd174d5ee..2b7f52d30 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -368,7 +368,7 @@ struct XAigerWriter } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -449,6 +449,7 @@ struct XAigerWriter { dict> symbols; + bool output_seen = false; for (auto wire : module->wires()) { //if (wire->name[0] == '$') @@ -458,14 +459,8 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (sig[i].wire == nullptr) { - if (wire->port_output) - sig[i] = SigBit(wire, i); - else - continue; - } - - if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { + RTLIL::SigBit b(wire, i); + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -474,8 +469,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { - int o = ordered_outputs.at(SigSpec(wire, i)); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -502,6 +498,9 @@ struct XAigerWriter } } + if (omode && !output_seen) + symbols["o0"].push_back("__dummy_o__"); + symbols.sort(); for (auto &sym : symbols) { @@ -692,7 +691,7 @@ struct XAigerBackend : public Backend { log_error("Can't find top module in current design!\n"); XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; -- cgit v1.2.3 From 292f80d231174951b8ebda5b1f9b70b6b95a545a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:20:56 -0800 Subject: Cleanup abc9 code --- backends/aiger/xaiger.cc | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2b7f52d30..db0395d28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -157,8 +157,11 @@ struct XAigerWriter } } - for (auto bit : input_bits) + for (auto bit : input_bits) { undriven_bits.erase(bit); + // Erase POs that are also PIs + output_bits.erase(bit); + } for (auto bit : output_bits) unused_bits.erase(bit); @@ -215,12 +218,14 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.insert(b); + if (!output_bits.count(b)) + co_bits.insert(b); } } else if (cell->output(c.first)) { SigBit O = sigmap(b); - ci_bits.insert(O); + if (!input_bits.count(O) && !output_bits.count(O)) + ci_bits.insert(O); } else log_abort(); } @@ -236,16 +241,6 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all POs and CIs that are also PIs - for (auto bit : input_bits) { - output_bits.erase(bit); - ci_bits.erase(bit); - } - for (auto bit : output_bits) { - ci_bits.erase(bit); - // POs override COs - co_bits.erase(bit); - } // Erase all CIs that are also COs for (auto bit : co_bits) ci_bits.erase(bit); -- cgit v1.2.3 From 171c425cf9addb61ef3f03596fd26355ed8af76d Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Feb 2019 16:18:13 -0800 Subject: Fix FIRRTL to Verilog process instance subfield assignment. Don't emit subfield assignments: bits(x, y, z) <= ... - but instead, add them to the reverse-wire-map where they'll be treated at the end of the module. Enable tests which were disabled due to incorrect treatment of subfields. Assume the `$firrtl2verilog` variable contains any additional switches to control verilog generation (i.e. `--no-dedup -X mverilog`) --- backends/firrtl/firrtl.cc | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 0917ecba6..88c1038b7 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -169,7 +169,6 @@ struct FirrtlWorker return *str == '\\' ? str + 1 : str; } - std::string cellname(RTLIL::Cell *cell) { return fid(cell->name).c_str(); @@ -219,29 +218,42 @@ struct FirrtlWorker if (it->second.size() > 0) { const SigSpec &secondSig = it->second; const std::string firstName = cell_name + "." + make_id(it->first); - const std::string secondName = make_expr(secondSig); + const std::string secondExpr = make_expr(secondSig); // Find the direction for this port. FDirection dir = getPortFDirection(it->first, instModule); - std::string source, sink; + std::string sourceExpr, sinkExpr; + const SigSpec *sinkSig = nullptr; switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); case FD_OUT: - source = firstName; - sink = secondName; + sourceExpr = firstName; + sinkExpr = secondExpr; + sinkSig = &secondSig; break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); /* FALL_THROUGH */ case FD_IN: - source = secondName; - sink = firstName; + sourceExpr = secondExpr; + sinkExpr = firstName; break; default: log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); break; } - wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); + // Check for subfield assignment. + std::string bitsString = "bits("; + if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { + if (sinkSig == nullptr) + log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); + // Don't generate the assignment here. + // Add the source and sink to the "reverse_wire_map" and we'll output the assignment + // as part of the coalesced subfield assignments for this wire. + register_reverse_wire_map(sourceExpr, *sinkSig); + } else { + wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); + } } } wire_exprs.push_back(stringf("\n")); -- cgit v1.2.3 From c492a3a1c4a36c273cb3ce8266d974a7cb595808 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 18:39:36 -0800 Subject: write_xaiger duplicate inout port into out port with $inout.out suffix --- backends/aiger/xaiger.cc | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index db0395d28..2c4cdf080 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -213,7 +213,10 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (cell->input(c.first)) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { if (!w->port_input) { SigBit I = sigmap(b); if (I != b) @@ -222,12 +225,11 @@ struct XAigerWriter co_bits.insert(b); } } - else if (cell->output(c.first)) { + if (is_output) { SigBit O = sigmap(b); if (!input_bits.count(O) && !output_bits.count(O)) ci_bits.insert(O); } - else log_abort(); } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; @@ -260,6 +262,27 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + init_map.sort(); input_bits.sort(); output_bits.sort(); -- cgit v1.2.3 From 8e883d92edef57214093ae7c5d8be6edb8462c8d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:17:51 -0800 Subject: write_xaiger to behave for undriven/unused inouts --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2c4cdf080..a4ef89931 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -158,13 +158,15 @@ struct XAigerWriter } for (auto bit : input_bits) { - undriven_bits.erase(bit); + if (!bit.wire->port_output) + undriven_bits.erase(bit); // Erase POs that are also PIs output_bits.erase(bit); } for (auto bit : output_bits) - unused_bits.erase(bit); + if (!bit.wire->port_input) + unused_bits.erase(bit); for (auto cell : module->cells()) { @@ -237,6 +239,27 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { @@ -262,27 +285,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - for (auto bit : input_bits) { - RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output) { - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); - if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); - SigBit new_bit(new_wire, bit.offset); - module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); - } - } - init_map.sort(); input_bits.sort(); output_bits.sort(); -- cgit v1.2.3 From f570aa5e1d3ac201089da2198f8e5084185fd92f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 12:15:58 -0800 Subject: Fix smt2 code generation for partially initialized memowy words, fixes #831 Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 418f8d766..7f3cc94ca 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1103,20 +1103,27 @@ struct Smt2Worker break; Const initword = init_data.extract(i*width, width, State::Sx); + Const initmask = initword; bool gen_init_constr = false; - for (auto bit : initword.bits) - if (bit == State::S0 || bit == State::S1) + for (int k = 0; k < GetSize(initword); k++) { + if (initword[k] == State::S0 || initword[k] == State::S1) { gen_init_constr = true; + initmask[k] = State::S1; + } else { + initmask[k] = State::S0; + initword[k] = State::S0; + } + } if (gen_init_constr) { if (statebv) /* FIXME */; else - init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", + init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", get_id(module), arrayid, Const(i, abits).as_string().c_str(), - initword.as_string().c_str(), get_id(cell), i)); + initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i)); } } } -- cgit v1.2.3 From e2fc18f27b5e9f506724a486787c2106b9f7fb4f Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 26 Feb 2019 10:28:42 -0800 Subject: Reduce amount of trailing whitespace in code base --- backends/protobuf/protobuf.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index f56147cef..549fc73ae 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -48,7 +48,7 @@ struct ProtobufDesignSerializer ProtobufDesignSerializer(bool use_selection, bool aig_mode) : aig_mode_(aig_mode), use_selection_(use_selection) { } - + string get_name(IdString name) { return RTLIL::unescape_id(name); @@ -60,7 +60,7 @@ struct ProtobufDesignSerializer { for (auto ¶m : parameters) { std::string key = get_name(param.first); - + yosys::pb::Parameter pb_param; @@ -207,7 +207,7 @@ struct ProtobufDesignSerializer (*models)[aig.name] = pb_model; } } - + void serialize_design(yosys::pb::Design *pb, Design *design) { GOOGLE_PROTOBUF_VERIFY_VERSION; -- cgit v1.2.3 From 241901461ae02c6a41837e254088f277b8167476 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 14:56:55 -0800 Subject: Add "write_verilog -siminit" Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index d351a6266..6818edb7a 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -33,7 +33,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal; +bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit; int auto_name_counter, auto_name_offset, auto_name_digits; std::map auto_name_map; std::set reg_wires, reg_ct; @@ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } } - if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { + if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { std::stringstream ss; dump_reg_init(ss, cell->getPort("\\Q")); if (!ss.str().empty()) { @@ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend { log(" without this option all internal cells are converted to Verilog\n"); log(" expressions.\n"); log("\n"); + log(" -siminit\n"); + log(" add initial statements with hierarchical refs to initialize FFs when\n"); + log(" in -noexpr mode.\n"); + log("\n"); log(" -nodec\n"); log(" 32-bit constant values are by default dumped as decimal numbers,\n"); log(" not bit pattern. This option deactivates this feature and instead\n"); @@ -1663,6 +1667,7 @@ struct VerilogBackend : public Backend { nostr = false; defparam = false; decimal = false; + siminit = false; auto_prefix = ""; bool blackboxes = false; @@ -1739,6 +1744,10 @@ struct VerilogBackend : public Backend { decimal = true; continue; } + if (arg == "-siminit") { + siminit = true; + continue; + } if (arg == "-blackboxes") { blackboxes = true; continue; -- cgit v1.2.3 From 03237de68605bb6eae73b96379faab0af6f8ce73 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 1 Mar 2019 12:59:07 -0800 Subject: Fix "write_edif -gndvccy" Signed-off-by: Clifford Wolf --- backends/edif/edif.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 2d25f879d..7e30b67af 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -130,7 +130,7 @@ struct EdifBackend : public Backend { bool port_rename = false; bool attr_properties = false; std::map> lib_cell_ports; - bool nogndvcc = false, gndvccy = true; + bool nogndvcc = false, gndvccy = false; CellTypes ct(design); EdifNames edif_names; -- cgit v1.2.3 From d6c4dfb9020ee19eebe3adadca89b65627184d81 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 4 Mar 2019 13:23:58 -0800 Subject: Ensure fid() calls make_id() for consistency; tests/simple/dff_init.v fails Mark dff_init.v as expected to fail since it uses "initial value". --- backends/firrtl/firrtl.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 88c1038b7..eef6401b2 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -165,8 +165,7 @@ struct FirrtlWorker std::string fid(RTLIL::IdString internal_id) { - const char *str = internal_id.c_str(); - return *str == '\\' ? str + 1 : str; + return make_id(internal_id); } std::string cellname(RTLIL::Cell *cell) -- cgit v1.2.3 From 5dfc7becca1f1faf6e77fb3b5d07d97171613d90 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 11:31:46 -0800 Subject: Use SVA label in smt export if available Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 7f3cc94ca..a26bff57b 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -887,8 +887,8 @@ struct Smt2Worker string name_a = get_bool(cell->getPort("\\A")); string name_en = get_bool(cell->getPort("\\EN")); - decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, - cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell))); + string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : get_id(cell); + decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str())); if (cell->type == "$cover") decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n", -- cgit v1.2.3 From 94f995ee3784e1a94a484fd399be2be4793d4e41 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 9 Mar 2019 13:19:41 -0800 Subject: Fix signed $shift/$shiftx handling in write_smt2 Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index a26bff57b..688535f33 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -416,6 +416,7 @@ struct Smt2Worker for (char ch : expr) { if (ch == 'A') processed_expr += get_bv(sig_a); else if (ch == 'B') processed_expr += get_bv(sig_b); + else if (ch == 'P') processed_expr += get_bv(cell->getPort("\\B")); else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; else processed_expr += ch; @@ -554,7 +555,7 @@ struct Smt2Worker if (cell->type.in("$shift", "$shiftx")) { if (cell->getParam("\\B_SIGNED").as_bool()) { - return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) " + return export_bvop(cell, stringf("(ite (bvsge P #b%0*d) " "(bvlshr A B) (bvlshr A (bvneg B)))", GetSize(cell->getPort("\\B")), 0), 's'); } else { -- cgit v1.2.3 From 20c6a8c9b0abb384517c4cc6f58cd29a90bda6ff Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 11 Mar 2019 20:12:28 +0100 Subject: Improve determinism of IdString DB for similar scripts Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6818edb7a..83d83f488 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1673,6 +1673,8 @@ struct VerilogBackend : public Backend { bool blackboxes = false; bool selected = false; + auto_name_map.clear(); + reg_wires.clear(); reg_ct.clear(); reg_ct.insert("$dff"); @@ -1779,6 +1781,8 @@ struct VerilogBackend : public Backend { dump_module(*f, "", it->second); } + auto_name_map.clear(); + reg_wires.clear(); reg_ct.clear(); } } VerilogBackend; -- cgit v1.2.3 From ff15cf9b1f8208d8c6e22beb9aebedc8bdae213f Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 12 Mar 2019 17:55:47 -0400 Subject: Install launcher executable when running yosys-smtbmc on Windows. Signed-off-by: William D. Jones --- backends/smt2/Makefile.inc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc index dce82f01a..92941d4cf 100644 --- a/backends/smt2/Makefile.inc +++ b/backends/smt2/Makefile.inc @@ -3,14 +3,30 @@ OBJS += backends/smt2/smt2.o ifneq ($(CONFIG),mxe) ifneq ($(CONFIG),emcc) + +# MSYS targets support yosys-smtbmc, but require a launcher script +ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64)) +TARGETS += yosys-smtbmc.exe yosys-smtbmc-script.py +# Needed to find the Python interpreter for yosys-smtbmc scripts. +# Override if necessary, it is only used for msys2 targets. +PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3) + +yosys-smtbmc-script.py: backends/smt2/smtbmc.py + $(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' \ + -e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@ + +yosys-smtbmc.exe: misc/launcher.c yosys-smtbmc-script.py + $(P) gcc -DGUI=0 -O -s -o $@ $< +# Other targets +else TARGETS += yosys-smtbmc yosys-smtbmc: backends/smt2/smtbmc.py $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new $(Q) chmod +x $@.new $(Q) mv $@.new $@ +endif $(eval $(call add_share_file,share/python3,backends/smt2/smtio.py)) endif endif - -- cgit v1.2.3 From 04e920337b1b984929d3d69fb2ab1f8b1e92f032 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Mar 2019 17:50:20 +0100 Subject: Fix a syntax bug in ilang backend related to process case statements Signed-off-by: Clifford Wolf --- backends/ilang/ilang_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 4c58ea087..dc39e5e08 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -204,7 +204,7 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) - f << stringf(", "); + f << stringf(" , "); dump_sigspec(f, (*it)->compare[i]); } f << stringf("\n"); -- cgit v1.2.3 From bacca5753775bfabed955a9772a5d86d85007c58 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Mar 2019 19:27:17 +0100 Subject: Fix smtbmc.py handling of zero appended steps Signed-off-by: Clifford Wolf --- backends/smt2/smtbmc.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 94a5e2da0..445a42e0d 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -1484,11 +1484,11 @@ else: # not tempind, covermode smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i)) smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i)) smt_assert_consequent(get_constr_expr(constr_assumes, i)) - print_msg("Re-solving with appended steps..") - if smt_check_sat() == "unsat": - print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) - retstatus = False - break + print_msg("Re-solving with appended steps..") + if smt_check_sat() == "unsat": + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) + retstatus = False + break print_anyconsts(step) for i in range(step, last_check_step+1): print_failed_asserts(i) -- cgit v1.2.3 From e78f5a3055cae54c44303bab187ad2ef11205ca3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 23 Mar 2019 14:39:42 +0100 Subject: Fix BTOR output tags syntax in writye_btor Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 53359bd7b..96044e339 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -932,9 +932,8 @@ struct BtorWorker btorf_push(stringf("output %s", log_id(wire))); - int sid = get_bv_sid(GetSize(wire)); int nid = get_sig_nid(wire); - btorf("%d output %d %d %s\n", next_nid++, sid, nid, log_id(wire)); + btorf("%d output %d %s\n", next_nid++, nid, log_id(wire)); btorf_pop(stringf("output %s", log_id(wire))); } -- cgit v1.2.3 From 1eff8be8f018bd6b94efd14a959d6f1807dd056d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 23 Mar 2019 14:40:01 +0100 Subject: Add support for memory initialization to write_btor Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 96044e339..55c494996 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -615,6 +615,7 @@ struct BtorWorker { int abits = cell->getParam("\\ABITS").as_int(); int width = cell->getParam("\\WIDTH").as_int(); + int nwords = cell->getParam("\\SIZE").as_int(); int rdports = cell->getParam("\\RD_PORTS").as_int(); int wrports = cell->getParam("\\WR_PORTS").as_int(); @@ -641,6 +642,52 @@ struct BtorWorker int data_sid = get_bv_sid(width); int bool_sid = get_bv_sid(1); int sid = get_mem_sid(abits, width); + + Const initdata = cell->getParam("\\INIT"); + initdata.exts(nwords*width); + int nid_init_val = -1; + + if (!initdata.is_fully_undef()) + { + bool constword = true; + Const firstword = initdata.extract(0, width); + + for (int i = 1; i < nwords; i++) { + Const thisword = initdata.extract(i*width, width); + if (thisword != firstword) { + constword = false; + break; + } + } + + if (constword) + { + if (verbose) + btorf("; initval = %s\n", log_signal(firstword)); + nid_init_val = get_sig_nid(firstword); + } + else + { + int nid_init_val = next_nid++; + btorf("%d state %d\n", nid_init_val, sid); + + for (int i = 0; i < nwords; i++) { + Const thisword = initdata.extract(i*width, width); + if (thisword.is_fully_undef()) + continue; + Const thisaddr(i, abits); + int nid_thisword = get_sig_nid(thisword); + int nid_thisaddr = get_sig_nid(thisaddr); + int last_nid_init_val = nid_init_val; + nid_init_val = next_nid++; + if (verbose) + btorf("; initval[%d] = %s\n", i, log_signal(thisword)); + btorf("%d write %d %d %d %d\n", nid_init_val, sid, last_nid_init_val, nid_thisaddr, nid_thisword); + } + } + } + + int nid = next_nid++; int nid_head = nid; @@ -649,6 +696,12 @@ struct BtorWorker else btorf("%d state %d %s\n", nid, sid, log_id(cell)); + if (nid_init_val >= 0) + { + int nid_init = next_nid++; + btorf("%d init %d %d %d\n", nid_init, sid, nid, nid_init_val); + } + if (asyncwr) { for (int port = 0; port < wrports; port++) -- cgit v1.2.3 From 73b87e780798fe2c7958b75e4dfddc0dc2169d20 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 1 Apr 2019 15:02:12 -0700 Subject: Refine memory support to deal with general Verilog memory definitions. --- backends/firrtl/firrtl.cc | 203 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 173 insertions(+), 30 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index eef6401b2..ed6e9f8ee 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -106,6 +106,95 @@ struct FirrtlWorker RTLIL::Design *design; std::string indent; + // Define read/write ports and memories. + // We'll collect their definitions and emit the corresponding FIRRTL definitions at the appropriate point in module construction. + // For the moment, we don't handle $readmemh or $readmemb. + // These will be part of a subsequent PR. + struct read_port { + string name; + bool clk_enable; + bool clk_parity; + bool transparent; + RTLIL::SigSpec clk; + RTLIL::SigSpec ena; + RTLIL::SigSpec addr; + read_port(string name, bool clk_enable, bool clk_parity, bool transparent, RTLIL::SigSpec clk, RTLIL::SigSpec ena, RTLIL::SigSpec addr) : name(name), clk_enable(clk_enable), clk_parity(clk_parity), transparent(transparent), clk(clk), ena(ena), addr(addr) { + // Current (3/13/2019) conventions: + // generate a constant 0 for clock and a constant 1 for enable if they are undefined. + if (!clk.is_fully_def()) + this->clk = SigSpec(RTLIL::Const(0, 1)); + if (!ena.is_fully_def()) + this->ena = SigSpec(RTLIL::Const(1, 1)); + } + string gen_read(const char * indent) { + string addr_expr = make_expr(addr); + string ena_expr = make_expr(ena); + string clk_expr = make_expr(clk); + string addr_str = stringf("%s%s.addr <= %s\n", indent, name.c_str(), addr_expr.c_str()); + string ena_str = stringf("%s%s.en <= %s\n", indent, name.c_str(), ena_expr.c_str()); + string clk_str = stringf("%s%s.clk <= asClock(%s)\n", indent, name.c_str(), clk_expr.c_str()); + return addr_str + ena_str + clk_str; + } + }; + struct write_port : read_port { + RTLIL::SigSpec mask; + write_port(string name, bool clk_enable, bool clk_parity, bool transparent, RTLIL::SigSpec clk, RTLIL::SigSpec ena, RTLIL::SigSpec addr, RTLIL::SigSpec mask) : read_port(name, clk_enable, clk_parity, transparent, clk, ena, addr), mask(mask) { + if (!clk.is_fully_def()) + this->clk = SigSpec(RTLIL::Const(0)); + if (!ena.is_fully_def()) + this->ena = SigSpec(RTLIL::Const(0)); + if (!mask.is_fully_def()) + this->ena = SigSpec(RTLIL::Const(1)); + } + string gen_read(const char * /* indent */) { + log_error("gen_read called on write_port: %s\n", name.c_str()); + return stringf("gen_read called on write_port: %s\n", name.c_str()); + } + string gen_write(const char * indent) { + string addr_expr = make_expr(addr); + string ena_expr = make_expr(ena); + string clk_expr = make_expr(clk); + string mask_expr = make_expr(mask); + string mask_str = stringf("%s%s.mask <= %s\n", indent, name.c_str(), mask_expr.c_str()); + string addr_str = stringf("%s%s.addr <= %s\n", indent, name.c_str(), addr_expr.c_str()); + string ena_str = stringf("%s%s.en <= %s\n", indent, name.c_str(), ena_expr.c_str()); + string clk_str = stringf("%s%s.clk <= asClock(%s)\n", indent, name.c_str(), clk_expr.c_str()); + return addr_str + ena_str + clk_str + mask_str; + } + }; + /* Memories defined within this module. */ + struct memory { + string name; // memory name + int abits; // number of address bits + int size; // size (in units) of the memory + int width; // size (in bits) of each element + int read_latency; + int write_latency; + vector read_ports; + vector write_ports; + std::string init_file; + std::string init_file_srcFileSpec; + memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {} + memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + void add_memory_read_port(read_port &rp) { + read_ports.push_back(rp); + } + void add_memory_write_port(write_port &wp) { + write_ports.push_back(wp); + } + void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { + this->init_file = init_file; + this->init_file_srcFileSpec = init_file_srcFileSpec; + } + + }; + dict memories; + + void register_memory(memory &m) + { + memories[m.name] = m; + } + void register_reverse_wire_map(string id, SigSpec sig) { for (int i = 0; i < GetSize(sig); i++) @@ -116,7 +205,7 @@ struct FirrtlWorker { } - string make_expr(const SigSpec &sig) + static string make_expr(const SigSpec &sig) { string expr; @@ -515,6 +604,7 @@ struct FirrtlWorker int abits = cell->parameters.at("\\ABITS").as_int(); int width = cell->parameters.at("\\WIDTH").as_int(); int size = cell->parameters.at("\\SIZE").as_int(); + memory m(mem_id, abits, size, width); int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); @@ -531,33 +621,24 @@ struct FirrtlWorker if (offset != 0) log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(cell)); - cell_exprs.push_back(stringf(" mem %s:\n", mem_id.c_str())); - cell_exprs.push_back(stringf(" data-type => UInt<%d>\n", width)); - cell_exprs.push_back(stringf(" depth => %d\n", size)); - - for (int i = 0; i < rd_ports; i++) - cell_exprs.push_back(stringf(" reader => r%d\n", i)); - - for (int i = 0; i < wr_ports; i++) - cell_exprs.push_back(stringf(" writer => w%d\n", i)); - - cell_exprs.push_back(stringf(" read-latency => 0\n")); - cell_exprs.push_back(stringf(" write-latency => 1\n")); - cell_exprs.push_back(stringf(" read-under-write => undefined\n")); - for (int i = 0; i < rd_ports; i++) { if (rd_clk_enable[i] != State::S0) log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(cell)); + SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(i*abits, abits); SigSpec data_sig = cell->getPort("\\RD_DATA").extract(i*width, width); - string addr_expr = make_expr(cell->getPort("\\RD_ADDR").extract(i*abits, abits)); - - cell_exprs.push_back(stringf(" %s.r%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str())); - cell_exprs.push_back(stringf(" %s.r%d.en <= UInt<1>(1)\n", mem_id.c_str(), i)); - cell_exprs.push_back(stringf(" %s.r%d.clk <= asClock(UInt<1>(0))\n", mem_id.c_str(), i)); - - register_reverse_wire_map(stringf("%s.r%d.data", mem_id.c_str(), i), data_sig); + string addr_expr = make_expr(addr_sig); + string name(stringf("%s.r%d", m.name.c_str(), i)); + bool clk_enable = false; + bool clk_parity = true; + bool transparency = false; + SigSpec ena_sig = RTLIL::SigSpec(RTLIL::State::S1, 1); + SigSpec clk_sig = RTLIL::SigSpec(RTLIL::State::S0, 1); + read_port rp(name, clk_enable, clk_parity, transparency, clk_sig, ena_sig, addr_sig); + m.add_memory_read_port(rp); + cell_exprs.push_back(rp.gen_read(indent.c_str())); + register_reverse_wire_map(stringf("%s.data", name.c_str()), data_sig); } for (int i = 0; i < wr_ports; i++) @@ -568,9 +649,16 @@ struct FirrtlWorker if (wr_clk_polarity[i] != State::S1) log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(cell)); - string addr_expr = make_expr(cell->getPort("\\WR_ADDR").extract(i*abits, abits)); - string data_expr = make_expr(cell->getPort("\\WR_DATA").extract(i*width, width)); - string clk_expr = make_expr(cell->getPort("\\WR_CLK").extract(i)); + string name(stringf("%s.w%d", m.name.c_str(), i)); + bool clk_enable = true; + bool clk_parity = true; + bool transparency = false; + SigSpec addr_sig =cell->getPort("\\WR_ADDR").extract(i*abits, abits); + string addr_expr = make_expr(addr_sig); + SigSpec data_sig =cell->getPort("\\WR_DATA").extract(i*width, width); + string data_expr = make_expr(data_sig); + SigSpec clk_sig = cell->getPort("\\WR_CLK").extract(i); + string clk_expr = make_expr(clk_sig); SigSpec wen_sig = cell->getPort("\\WR_EN").extract(i*width, width); string wen_expr = make_expr(wen_sig[0]); @@ -579,13 +667,50 @@ struct FirrtlWorker if (wen_sig[0] != wen_sig[i]) log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(cell)); - cell_exprs.push_back(stringf(" %s.w%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str())); - cell_exprs.push_back(stringf(" %s.w%d.data <= %s\n", mem_id.c_str(), i, data_expr.c_str())); - cell_exprs.push_back(stringf(" %s.w%d.en <= %s\n", mem_id.c_str(), i, wen_expr.c_str())); - cell_exprs.push_back(stringf(" %s.w%d.mask <= UInt<1>(1)\n", mem_id.c_str(), i)); - cell_exprs.push_back(stringf(" %s.w%d.clk <= asClock(%s)\n", mem_id.c_str(), i, clk_expr.c_str())); + SigSpec mask_sig = RTLIL::SigSpec(RTLIL::State::S1, 1); + write_port wp(name, clk_enable, clk_parity, transparency, clk_sig, wen_sig[0], addr_sig, mask_sig); + m.add_memory_write_port(wp); + cell_exprs.push_back(stringf("%s%s.data <= %s\n", indent.c_str(), name.c_str(), data_expr.c_str())); + cell_exprs.push_back(wp.gen_write(indent.c_str())); } + register_memory(m); + continue; + } + if (cell->type.in("$memwr", "$memrd", "$meminit")) + { + std::string cell_type = fid(cell->type); + std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); + memory *mp = nullptr; + if (cell->type == "$meminit" ) { + log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); + } else { + // It's a $memwr or $memrd. Remember the read/write port parameters for the eventual FIRRTL memory definition. + auto addrSig = cell->getPort("\\ADDR"); + auto dataSig = cell->getPort("\\DATA"); + auto enableSig = cell->getPort("\\EN"); + auto clockSig = cell->getPort("\\CLK"); + Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); + Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); + + mp = &memories.at(mem_id); + int portNum = 0; + bool transparency = false; + string data_expr = make_expr(dataSig); + if (cell->type.in("$memwr")) { + portNum = (int) mp->write_ports.size(); + write_port wp(stringf("%s.w%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig, dataSig); + mp->add_memory_write_port(wp); + cell_exprs.push_back(stringf("%s%s.data <= %s\n", indent.c_str(), wp.name.c_str(), data_expr.c_str())); + cell_exprs.push_back(wp.gen_write(indent.c_str())); + } else if (cell->type.in("$memrd")) { + portNum = (int) mp->read_ports.size(); + read_port rp(stringf("%s.r%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig); + mp->add_memory_read_port(rp); + cell_exprs.push_back(rp.gen_read(indent.c_str())); + register_reverse_wire_map(stringf("%s.data", rp.name.c_str()), dataSig); + } + } continue; } @@ -763,6 +888,24 @@ struct FirrtlWorker f << stringf("\n"); + // If we have any memory definitions, output them. + for (auto kv : memories) { + memory m = kv.second; + f << stringf(" mem %s:\n", m.name.c_str()); + f << stringf(" data-type => UInt<%d>\n", m.width); + f << stringf(" depth => %d\n", m.size); + for (int i = 0; i < (int) m.read_ports.size(); i += 1) { + f << stringf(" reader => r%d\n", i); + } + for (int i = 0; i < (int) m.write_ports.size(); i += 1) { + f << stringf(" writer => w%d\n", i); + } + f << stringf(" read-latency => %d\n", m.read_latency); + f << stringf(" write-latency => %d\n", m.write_latency); + f << stringf(" read-under-write => undefined\n"); + } + f << stringf("\n"); + for (auto str : cell_exprs) f << str; -- cgit v1.2.3 From 2217d59e299ce0cc15887d53308d7b7cb6400c52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 18:06:33 -0700 Subject: Add non-input bits driven by unrecognised cells as ci_bits --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a4ef89931..bad9322bb 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -229,7 +229,7 @@ struct XAigerWriter } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O) && !output_bits.count(O)) + if (!input_bits.count(O)) ci_bits.insert(O); } } -- cgit v1.2.3 From c7483917307bd1c281b159fe15f0f79af4e305b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 14:13:11 -0700 Subject: WIP --- backends/aiger/xaiger.cc | 82 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 14 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bad9322bb..ce10028f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -61,6 +61,8 @@ struct XAigerWriter dict init_inputs; int initstate_ff = 0; + vector box_list; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -211,7 +213,7 @@ struct XAigerWriter } for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; + /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -219,30 +221,32 @@ struct XAigerWriter auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - if (!w->port_input) { + /*if (!w->port_input)*/ { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (!output_bits.count(b)) + /*if (!output_bits.count(b))*/ co_bits.insert(b); } } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O)) + /*if (!input_bits.count(O))*/ ci_bits.insert(O); } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + + box_list.emplace_back(cell); + log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing + // suffix, make it a PO driven by the existing inout, and inherit existing // inout's drivers if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); @@ -256,19 +260,19 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); + output_bits.insert(new_bit); } } // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { - co_bits.erase(bit); + //co_bits.erase(bit); output_bits.erase(bit); } // Erase all CIs that are also COs - for (auto bit : co_bits) - ci_bits.erase(bit); + //for (auto bit : co_bits) + // ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); @@ -491,7 +495,8 @@ struct XAigerWriter if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); - output_seen = !miter_mode; + if (output_seen && output_bits.count(b)) + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -532,7 +537,52 @@ struct XAigerWriter } } - f << stringf("c\nGenerated by %s\n", yosys_version_str); + f << "c"; + + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + int box_id = 0; + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + for (const auto &c : cell->connections()) + if (cell->input(c.first)) + box_inputs += c.second.size(); + else + box_outputs += c.second.size(); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id++); + write_h_buffer(0 /* OldBoxNum */); + } + std::string h_buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); +#else + int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); +#endif + f << "h"; + f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); + f.write(h_buffer_str.data(), h_buffer_str.size()); + + f << stringf("Generated by %s\n", yosys_version_str); } void write_map(std::ostream &f, bool verbose_map, bool omode) @@ -557,7 +607,11 @@ struct XAigerWriter int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; + + // Only continue if this input is not a CO, + // otherwise write as CO below + if (!co_bits.count(b)) + continue; } if (output_bits.count(b) || co_bits.count(b)) { @@ -606,7 +660,7 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) - f << "output 0 0 __dummy_o__\n"; + f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) -- cgit v1.2.3 From 686e772f0bb3129e7d6469dc25548497f107ebc5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 16:17:48 -0700 Subject: ci_bits and co_bits now a list, order is important for ABC --- backends/aiger/xaiger.cc | 58 ++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce10028f7..f67f7620b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -47,7 +47,7 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; - pool ci_bits, co_bits; + vector> ci_bits, co_bits; dict type_map; vector> aig_gates; @@ -226,13 +226,13 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ - co_bits.insert(b); + co_bits.emplace_back(b, 0); } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ - ci_bits.insert(O); + ci_bits.emplace_back(O, 0); } } if (!type_map.count(cell->type)) @@ -240,7 +240,7 @@ struct XAigerWriter } box_list.emplace_back(cell); - log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { @@ -274,8 +274,8 @@ struct XAigerWriter //for (auto bit : co_bits) // ci_bits.erase(bit); // CIs cannot be undriven - for (auto bit : ci_bits) - undriven_bits.erase(bit); + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -299,9 +299,10 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : ci_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } for (auto bit : input_bits) { @@ -369,15 +370,15 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); - for (auto bit : co_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + for (auto &c : co_bits) { + RTLIL::SigBit bit = c.first; + c.second = aig_o++; + ordered_outputs[bit] = c.second; aig_outputs.push_back(bit2aig(bit)); } for (auto bit : output_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -484,7 +485,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -493,10 +494,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); - if (output_seen && output_bits.count(b)) - output_seen = !miter_mode; + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -603,18 +603,13 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - - // Only continue if this input is not a CO, - // otherwise write as CO below - if (!co_bits.count(b)) - continue; } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); continue; @@ -646,6 +641,21 @@ struct XAigerWriter } } + for (const auto &c : ci_bits) { + RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; + int i = b.offset; + int a = c.second; + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + for (const auto &c : co_bits) { + RTLIL::SigBit b = c.first; + int o = c.second; + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + } + input_lines.sort(); for (auto &it : input_lines) f << it.second; -- cgit v1.2.3 From fe0b421212a17dae32cd30a09dc43c688a285f8c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:16:25 -0700 Subject: Output __const0__ and __const1__ CIs --- backends/aiger/xaiger.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f67f7620b..d3384e136 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,8 +215,6 @@ struct XAigerWriter for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); @@ -382,7 +380,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -561,11 +559,12 @@ struct XAigerWriter int box_id = 0; for (auto cell : box_list) { int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) + for (const auto &c : cell->connections()) { if (cell->input(c.first)) box_inputs += c.second.size(); - else + if (cell->output(c.first)) box_outputs += c.second.size(); + } write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id++); @@ -652,8 +651,12 @@ struct XAigerWriter for (const auto &c : co_bits) { RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; int o = c.second; - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + if (wire) + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); + else + output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); } input_lines.sort(); @@ -669,7 +672,7 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); - if (omode && output_lines.empty()) + if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); -- cgit v1.2.3 From 55a3638c71229e2730e1d0f7340f6c9d4087522d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 15:01:45 -0700 Subject: Port from xc7mux branch --- backends/aiger/xaiger.cc | 146 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 37 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d3384e136..66ab3878e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -212,6 +212,9 @@ struct XAigerWriter continue; } + RTLIL::Module* box_module = module->design->module(cell->type); + bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -224,20 +227,33 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ + if (abc_box) co_bits.emplace_back(b, 0); + else if (b.wire) { + output_bits.insert(b); + if (!b.wire->port_input) + unused_bits.erase(b); + } } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ + if (abc_box) ci_bits.emplace_back(O, 0); + else { + input_bits.insert(O); + if (!O.wire->port_output) + undriven_bits.erase(O); + } } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - box_list.emplace_back(cell); + if (abc_box) + box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -537,49 +553,105 @@ struct XAigerWriter f << "c"; - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { - // TODO: Don't assume we're on little endian + if (!box_list.empty()) { + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int i32_be = _byteswap_ulong(i32); #else - int i32_be = __builtin_bswap32(i32); + int i32_be = __builtin_bswap32(i32); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; - write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); - write_h_buffer(box_list.size()); - int box_id = 0; - for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) { - if (cell->input(c.first)) - box_inputs += c.second.size(); - if (cell->output(c.first)) - box_outputs += c.second.size(); + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + + RTLIL::Module *holes_module = nullptr; + holes_module = module->design->addModule("\\__holes__"); + + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + Cell *holes_cell = nullptr; + if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); + RTLIL::Wire *holes_wire; + int num_inputs = 0; + for (const auto &c : cell->connections()) { + if (cell->input(c.first)) { + box_inputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire->port_input = true; + } + ++num_inputs; + holes_cell->setPort(c.first, holes_wire); + } + } + if (cell->output(c.first)) { + box_outputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); + holes_wire->port_output = true; + holes_cell->setPort(c.first, holes_wire); + } + } + } + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id); + write_h_buffer(0 /* OldBoxNum */); } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_id++); - write_h_buffer(0 /* OldBoxNum */); - } - std::string h_buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian + + f << "h"; + std::string buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - f << "h"; - f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); - f.write(h_buffer_str.data(), h_buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + if (holes_module) { + holes_module->fixup_ports(); + + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); + + Pass::call(holes_module->design, "flatten; aigmap"); + + holes_module->design->selection_stack.pop_back(); + + std::stringstream a_buffer; + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + + f << "a"; + std::string buffer_str = a_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + holes_module->design->remove(holes_module); + } + } f << stringf("Generated by %s\n", yosys_version_str); } -- cgit v1.2.3 From e7a8955818b8b0fee02673607b429f1de0f7164e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 16:37:47 -0700 Subject: CIs before PIs; also sort each cell's connections before iterating --- backends/aiger/xaiger.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 66ab3878e..ce93ffb28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,6 +215,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -313,15 +314,15 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto &c : ci_bits) { + for (auto bit : input_bits) { aig_m++, aig_i++; - c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[bit] = 2*aig_m; } - for (auto bit : input_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -585,6 +586,7 @@ struct XAigerWriter holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; int num_inputs = 0; + // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { if (cell->input(c.first)) { box_inputs += c.second.size(); -- cgit v1.2.3 From 5c134980c4d0f5c1f961d50c9c1fe1752d966e48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 21:05:44 -0700 Subject: Optimise --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce93ffb28..06496dbc3 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -585,18 +585,17 @@ struct XAigerWriter if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; - int num_inputs = 0; // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { + log_assert(c.second.size() == 1); if (cell->input(c.first)) { box_inputs += c.second.size(); if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - ++num_inputs; holes_cell->setPort(c.first, holes_wire); } } -- cgit v1.2.3 From d59185f1d6bdc5f63704b41553bfc72eecd84223 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:08:42 -0700 Subject: Remove init* from xaiger, also topo-sort cells for box flow --- backends/aiger/xaiger.cc | 252 +++++++++++++++++++++++++++++------------------ 1 file changed, 157 insertions(+), 95 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 06496dbc3..ed0fc656f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,6 +20,8 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/utils.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -46,9 +48,8 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - pool initstate_bits; + //pool initstate_bits; vector> ci_bits, co_bits; - dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -58,11 +59,11 @@ struct XAigerWriter dict ordered_outputs; dict ordered_latches; - dict init_inputs; - int initstate_ff = 0; - vector box_list; + //dict init_inputs; + //int initstate_ff = 0; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -76,10 +77,10 @@ struct XAigerWriter { aig_map[bit] = -1; - if (initstate_bits.count(bit)) { - log_assert(initstate_ff > 0); - aig_map[bit] = initstate_ff; - } else + //if (initstate_bits.count(bit)) { + // log_assert(initstate_ff > 0); + // aig_map[bit] = initstate_ff; + //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -170,8 +171,35 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + dict> bit_drivers, bit_users; + TopoSort toposort; + bool abc_box_seen = false; + for (auto cell : module->cells()) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + // HACK!!! + if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) + continue; + + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -204,60 +232,94 @@ struct XAigerWriter continue; } - if (cell->type == "$initstate") - { - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - undriven_bits.erase(Y); - initstate_bits.insert(Y); - continue; - } + //if (cell->type == "$initstate") + //{ + // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + // undriven_bits.erase(Y); + // initstate_bits.insert(Y); + // continue; + //} RTLIL::Module* box_module = module->design->module(cell->type); - bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); - - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - if (abc_box) - co_bits.emplace_back(b, 0); - else if (b.wire) { + if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; output_bits.insert(b); - if (!b.wire->port_input) - unused_bits.erase(b); + unused_bits.erase(b); } } - } - if (is_output) { - SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - if (abc_box) - ci_bits.emplace_back(O, 0); - else { + if (is_output) { + SigBit O = sigmap(b); input_bits.insert(O); if (!O.wire->port_output) undriven_bits.erase(O); } } } - if (!type_map.count(cell->type)) - type_map[cell->type] = type_map.size()+1; } + else + abc_box_seen = true; - if (abc_box) - box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + if (abc_box_seen) { + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + toposort.sort(); + log_assert(!toposort.found_loops); + + for (auto cell_name : toposort.sorted) { + RTLIL::Cell *cell = module->cell(cell_name); + RTLIL::Module* box_module = module->design->module(cell->type); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; + + cell->connections_.sort(RTLIL::sort_by_id_str()); + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + /*if (!w->port_input)*/ { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + /*if (!output_bits.count(b))*/ + co_bits.emplace_back(b, 0); + } + } + if (is_output) { + SigBit O = sigmap(b); + /*if (!input_bits.count(O))*/ + ci_bits.emplace_back(O, 0); + } + } + } + + box_list.emplace_back(cell); + } + + // TODO: Free memory from toposort, bit_drivers, bit_users + } + for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; // If encountering an inout port, then create a new wire with $inout.out @@ -329,15 +391,15 @@ struct XAigerWriter aig_m++, aig_i++; } - if (zinit_mode) - { - for (auto it : ff_map) { - if (init_map.count(it.first)) - continue; - aig_m++, aig_i++; - init_inputs[it.first] = 2*aig_m; - } - } + //if (zinit_mode) + //{ + // for (auto it : ff_map) { + // if (init_map.count(it.first)) + // continue; + // aig_m++, aig_i++; + // init_inputs[it.first] = 2*aig_m; + // } + //} for (auto it : ff_map) { aig_m++, aig_l++; @@ -349,29 +411,29 @@ struct XAigerWriter aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); } - if (!initstate_bits.empty() || !init_inputs.empty()) { - aig_m++, aig_l++; - initstate_ff = 2*aig_m+1; - aig_latchinit.push_back(0); - } - - if (zinit_mode) - { - for (auto it : ff_map) - { - int l = ordered_latches[it.first]; - - if (aig_latchinit.at(l) == 1) - aig_map[it.first] ^= 1; - - if (aig_latchinit.at(l) == 2) - { - int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - } - } - } + //if (!initstate_bits.empty() || !init_inputs.empty()) { + // aig_m++, aig_l++; + // initstate_ff = 2*aig_m+1; + // aig_latchinit.push_back(0); + //} + + //if (zinit_mode) + //{ + // for (auto it : ff_map) + // { + // int l = ordered_latches[it.first]; + + // if (aig_latchinit.at(l) == 1) + // aig_map[it.first] ^= 1; + + // if (aig_latchinit.at(l) == 2) + // { + // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + // } + // } + //} for (auto it : ff_map) { int a = bit2aig(it.second); @@ -382,8 +444,8 @@ struct XAigerWriter aig_latchin.push_back(a); } - if (!initstate_bits.empty() || !init_inputs.empty()) - aig_latchin.push_back(1); + //if (!initstate_bits.empty() || !init_inputs.empty()) + // aig_latchin.push_back(1); for (auto &c : co_bits) { RTLIL::SigBit bit = c.first; @@ -518,14 +580,14 @@ struct XAigerWriter symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // if (GetSize(wire) != 1) + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + // else + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); @@ -687,12 +749,12 @@ struct XAigerWriter continue; } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + // continue; + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); -- cgit v1.2.3 From 2b860809e9dae557a435f01a3125e6dd4b4a8599 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:28:19 -0700 Subject: Stop topological sort at abc_flop_q --- backends/aiger/xaiger.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ed0fc656f..070d6d403 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,14 +180,20 @@ struct XAigerWriter toposort.node(cell->name); for (const auto &conn : cell->connections()) { - // HACK!!! - if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) - continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } -- cgit v1.2.3 From 1ec5f18346dd3f50e2340f4b79239a045ce7dd72 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 14:43:45 -0700 Subject: Cope with inout ports --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 070d6d403..14fa4fb7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -197,9 +197,12 @@ struct XAigerWriter continue; } - if (cell->input(conn.first)) + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); + } if (cell->output(conn.first)) for (auto bit : sigmap(conn.second)) @@ -287,7 +290,18 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); +#ifndef NDEBUG + toposort.analyze_loops = true; +#endif toposort.sort(); +#ifndef NDEBUG + for (auto &it : toposort.loops) { + log(" loop"); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif log_assert(!toposort.found_loops); for (auto cell_name : toposort.sorted) { -- cgit v1.2.3 From 23cd2e5de042949bf47a9c72b8dd8fae48e900ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 16:03:29 -0700 Subject: Fix $anyseq warning and cleanup --- backends/aiger/xaiger.cc | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 14fa4fb7f..582c49976 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -252,7 +252,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ + if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -271,8 +271,7 @@ struct XAigerWriter if (is_output) { SigBit O = sigmap(b); input_bits.insert(O); - if (!O.wire->port_output) - undriven_bits.erase(O); + undriven_bits.erase(O); } } } @@ -312,24 +311,19 @@ struct XAigerWriter cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - co_bits.emplace_back(b, 0); - } + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, 0); } if (is_output) { SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, 0); } } } @@ -367,9 +361,6 @@ struct XAigerWriter //co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs - //for (auto bit : co_bits) - // ci_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); -- cgit v1.2.3 From f4abc21d8ad79621cc24852bd76abf40a9d9f702 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 18 Apr 2019 17:42:12 +0200 Subject: Add "whitebox" attribute, add "read_verilog -wb" Signed-off-by: Clifford Wolf --- backends/blif/blif.cc | 6 +++--- backends/edif/edif.cc | 6 +++--- backends/intersynth/intersynth.cc | 2 +- backends/smt2/smt2.cc | 2 +- backends/smv/smv.cc | 2 +- backends/spice/spice.cc | 2 +- backends/table/table.cc | 2 +- backends/verilog/verilog_backend.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) (limited to 'backends') diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 0db5ff27c..b6dbd84cb 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -140,7 +140,7 @@ struct BlifDumper return "subckt"; if (!design->modules_.count(RTLIL::escape_id(cell_type))) return "gate"; - if (design->modules_.at(RTLIL::escape_id(cell_type))->get_bool_attribute("\\blackbox")) + if (design->modules_.at(RTLIL::escape_id(cell_type))->get_blackbox_attribute()) return "gate"; return "subckt"; } @@ -196,7 +196,7 @@ struct BlifDumper } f << stringf("\n"); - if (module->get_bool_attribute("\\blackbox")) { + if (module->get_blackbox_attribute()) { f << stringf(".blackbox\n"); f << stringf(".end\n"); return; @@ -640,7 +640,7 @@ struct BlifBackend : public Backend { for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; - if (module->get_bool_attribute("\\blackbox") && !config.blackbox_mode) + if (module->get_blackbox_attribute() && !config.blackbox_mode) continue; if (module->processes.size() != 0) diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 7e30b67af..6d9469538 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -178,7 +178,7 @@ struct EdifBackend : public Backend { for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; - if (module->get_bool_attribute("\\blackbox")) + if (module->get_blackbox_attribute()) continue; if (top_module_name.empty()) @@ -192,7 +192,7 @@ struct EdifBackend : public Backend { for (auto cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) { + if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) { lib_cell_ports[cell->type]; for (auto p : cell->connections()) lib_cell_ports[cell->type][p.first] = GetSize(p.second); @@ -302,7 +302,7 @@ struct EdifBackend : public Backend { *f << stringf(" (technology (numberDefinition))\n"); for (auto module : sorted_modules) { - if (module->get_bool_attribute("\\blackbox")) + if (module->get_blackbox_attribute()) continue; SigMap sigmap(module); diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 2eb08dbe9..b0e3cd252 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -127,7 +127,7 @@ struct IntersynthBackend : public Backend { RTLIL::Module *module = module_it.second; SigMap sigmap(module); - if (module->get_bool_attribute("\\blackbox")) + if (module->get_blackbox_attribute()) continue; if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) continue; diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 688535f33..e318a4051 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1543,7 +1543,7 @@ struct Smt2Backend : public Backend { for (auto module : sorted_modules) { - if (module->get_bool_attribute("\\blackbox") || module->has_memories_warn() || module->has_processes_warn()) + if (module->get_blackbox_attribute() || module->has_memories_warn() || module->has_processes_warn()) continue; log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index f379c9c48..d75456c1b 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -739,7 +739,7 @@ struct SmvBackend : public Backend { pool modules; for (auto module : design->modules()) - if (!module->get_bool_attribute("\\blackbox") && !module->has_memories_warn() && !module->has_processes_warn()) + if (!module->get_blackbox_attribute() && !module->has_memories_warn() && !module->has_processes_warn()) modules.insert(module); if (template_f.is_open()) diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index b6a3f1e77..6738a4bbd 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -212,7 +212,7 @@ struct SpiceBackend : public Backend { for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; - if (module->get_bool_attribute("\\blackbox")) + if (module->get_blackbox_attribute()) continue; if (module->processes.size() != 0) diff --git a/backends/table/table.cc b/backends/table/table.cc index b75169ea4..796f18059 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -67,7 +67,7 @@ struct TableBackend : public Backend { for (auto module : design->modules()) { - if (module->get_bool_attribute("\\blackbox")) + if (module->get_blackbox_attribute()) continue; SigMap sigmap(module); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 83d83f488..855409d0b 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1770,7 +1770,7 @@ struct VerilogBackend : public Backend { *f << stringf("/* Generated by %s */\n", yosys_version_str); for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { - if (it->second->get_bool_attribute("\\blackbox") != blackboxes) + if (it->second->get_blackbox_attribute() != blackboxes) continue; if (selected && !design->selected_whole_module(it->first)) { if (design->selected_module(it->first)) -- cgit v1.2.3 From 79881141e2f9354a12df81277b82e011f52994ae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:30:45 -0700 Subject: write_json to not write contents (cells/wires) of whiteboxes --- backends/json/json.cc | 115 ++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 56 deletions(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..b4f82a3fe 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,72 +130,75 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n },\n"); + f << stringf("\n }"); - f << stringf(" \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); + if (!module->get_blackbox_attribute()) { + f << stringf(",\n \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); + } } - } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + first2 = false; + } + f << stringf("\n },\n"); + } + f << stringf(" \"connections\": {"); bool first2 = true; for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); first2 = false; } - f << stringf("\n },\n"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf(" \"connections\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); - first2 = false; - } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; - } - f << stringf("\n },\n"); + f << stringf("\n },\n"); - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n }"); } - f << stringf("\n }\n"); + f << stringf("\n"); f << stringf(" }"); } -- cgit v1.2.3 From 4ef03e19a8eafc324d3442f0642abf858071fdd4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:30:45 -0700 Subject: write_json to not write contents (cells/wires) of whiteboxes --- backends/json/json.cc | 115 ++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 56 deletions(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..b4f82a3fe 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,72 +130,75 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n },\n"); + f << stringf("\n }"); - f << stringf(" \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); + if (!module->get_blackbox_attribute()) { + f << stringf(",\n \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); + } } - } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + first2 = false; + } + f << stringf("\n },\n"); + } + f << stringf(" \"connections\": {"); bool first2 = true; for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); first2 = false; } - f << stringf("\n },\n"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf(" \"connections\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); - first2 = false; - } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; - } - f << stringf("\n },\n"); + f << stringf("\n },\n"); - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n }"); } - f << stringf("\n }\n"); + f << stringf("\n"); f << stringf(" }"); } -- cgit v1.2.3 From 4c327cf316404fbedb1d26b0aebecaaf01d46f6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:32:41 -0700 Subject: Use new -wb flag for ABC flow --- backends/aiger/xaiger.cc | 60 +++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582c49976..975780488 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -103,7 +103,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -177,36 +177,38 @@ struct XAigerWriter for (auto cell : module->cells()) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + if (!ignore_boxes) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; - } + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); } if (cell->type == "$_NOT_") @@ -249,7 +251,7 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = module->design->module(cell->type); + RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; @@ -705,12 +707,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; -- cgit v1.2.3 From b531efd6d9febe679571c897a8e22dbeaedeb96e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:35:16 -0700 Subject: Spelling --- backends/aiger/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index dfe506c66..516e538a5 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -685,7 +685,7 @@ struct AigerBackend : public Backend { log("invariant constraints.\n"); log("\n"); log(" -ascii\n"); - log(" write ASCII version of AGIER format\n"); + log(" write ASCII version of AIGER format\n"); log("\n"); log(" -zinit\n"); log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); -- cgit v1.2.3 From 6bdf98d591a4ee5752d687d35238b454288e1d96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:43:13 -0700 Subject: Add flop support for write_xaiger --- backends/aiger/xaiger.cc | 94 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 975780488..587294a40 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -177,6 +178,9 @@ struct XAigerWriter for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + if (!ignore_boxes) { toposort.node(cell->name); for (const auto &conn : cell->connections()) @@ -189,7 +193,6 @@ struct XAigerWriter continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); @@ -251,8 +254,32 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; - if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + log_assert(inst_module); + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (!inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -311,6 +338,7 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { for (auto b : c.second.bits()) { @@ -394,10 +422,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -472,6 +510,12 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -629,7 +673,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -644,10 +688,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -700,6 +744,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); @@ -792,7 +864,7 @@ struct XAigerWriter RTLIL::SigBit b = c.first; RTLIL::Wire *wire = b.wire; int i = b.offset; - int a = c.second; + int a = bit2aig(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } @@ -845,7 +917,7 @@ struct XAigerBackend : public Backend { log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); - log(" write ASCII version of AGIER format\n"); + log(" write ASCII version of AIGER format\n"); log("\n"); log(" -zinit\n"); log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); -- cgit v1.2.3 From 8f93999129bfcd957dbb312d804c01525af6d07e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 23:05:59 -0700 Subject: Revert "write_json to not write contents (cells/wires) of whiteboxes" This reverts commit 4ef03e19a8eafc324d3442f0642abf858071fdd4. --- backends/json/json.cc | 115 ++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 59 deletions(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index b4f82a3fe..f5c687981 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,75 +130,72 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n }"); + f << stringf("\n },\n"); - if (!module->get_blackbox_attribute()) { - f << stringf(",\n \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); - } - } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); - first2 = false; - } - f << stringf("\n },\n"); + f << stringf(" \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); } - f << stringf(" \"connections\": {"); + } + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); bool first2 = true; for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); first2 = false; } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf("\n },\n"); } - f << stringf("\n },\n"); - - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"connections\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + first2 = false; } - f << stringf("\n }"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n },\n"); + + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf("\n"); + f << stringf("\n }\n"); f << stringf(" }"); } -- cgit v1.2.3 From 3544a7cd7b6b2595d25c56c5b1c3fbf6c9cccf7e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:37:10 -0700 Subject: ignore_boxes -> holes_mode --- backends/aiger/xaiger.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 587294a40..71aaebfd9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,7 +104,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -181,7 +181,7 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (!ignore_boxes) { + if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { @@ -398,7 +398,7 @@ struct XAigerWriter for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { + if (!undriven_bits.empty() && !holes_mode) { undriven_bits.sort(); for (auto bit : undriven_bits) { log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); @@ -511,7 +511,6 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; aig_o++; aig_outputs.push_back(ff_aig_map.at(f.second)); } @@ -779,12 +778,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; -- cgit v1.2.3 From 35f44f3ae8618b5e5da068c3df3d35b2fdc3d1aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:44:53 -0700 Subject: Do not assume inst_module is always present --- backends/aiger/xaiger.cc | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 71aaebfd9..31b74f9aa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -193,12 +193,13 @@ struct XAigerWriter continue; } - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); + if (inst_module) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + } } if (cell->input(conn.first)) { @@ -254,7 +255,6 @@ struct XAigerWriter // continue; //} - log_assert(inst_module); if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { @@ -279,7 +279,7 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (!inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -386,15 +386,12 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all POs and COs that are undriven - for (auto bit : undriven_bits) { - //co_bits.erase(bit); + // Erase all POs that are undriven + for (auto bit : undriven_bits) output_bits.erase(bit); - } // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); - for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 148caecca30ec4e8ebd459993f28560438131cb8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Apr 2019 21:17:12 +0200 Subject: Change "ne" to "neq" in btor2 output we need to do this because they changed the parser: https://github.com/Boolector/btor2tools/commit/e97fc9cedabadeec4f621de22096e514f862c690 Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 55c494996..91f238fa5 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -340,7 +340,7 @@ struct BtorWorker if (cell->type == "$lt") btor_op = "lt"; if (cell->type == "$le") btor_op = "lte"; if (cell->type.in("$eq", "$eqx")) btor_op = "eq"; - if (cell->type.in("$ne", "$nex")) btor_op = "ne"; + if (cell->type.in("$ne", "$nex")) btor_op = "neq"; if (cell->type == "$ge") btor_op = "gte"; if (cell->type == "$gt") btor_op = "gt"; log_assert(!btor_op.empty()); -- cgit v1.2.3 From 76bba4918205445e9129895f071d35e42e23efec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 15:47:36 -0700 Subject: Fixes for simple_abc9 tests --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 31b74f9aa..e93fd35f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,13 +180,14 @@ struct XAigerWriter { RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { + if (known_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -279,7 +280,10 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + abc_box_seen = true; + } + else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -305,8 +309,6 @@ struct XAigerWriter } } } - else - abc_box_seen = true; //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -381,6 +383,8 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); + else + alias_map[new_bit] = bit; output_bits.insert(new_bit); } } -- cgit v1.2.3 From 0e0c80fac883a6f512a94aecdc3c915b8cacb562 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 19:44:10 +0200 Subject: Add support for zero-width signals to Verilog back-end, fixes #948 Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 855409d0b..9967482d6 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -187,6 +187,10 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o { if (width < 0) width = data.bits.size() - offset; + if (width == 0) { + f << "\"\""; + return; + } if (nostr) goto dump_hex; if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) { @@ -340,6 +344,10 @@ void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decima void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) { + if (GetSize(sig) == 0) { + f << "\"\""; + return; + } if (sig.is_chunk()) { dump_sigchunk(f, sig.as_chunk()); } else { -- cgit v1.2.3 From b780c0a7de3b0f095099461af1434624d2af0c32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:22:29 -0700 Subject: Allow POs to be PIs in XAIG --- backends/aiger/xaiger.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e93fd35f7..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -161,12 +161,8 @@ struct XAigerWriter } } - for (auto bit : input_bits) { - if (!bit.wire->port_output) - undriven_bits.erase(bit); - // Erase POs that are also PIs - output_bits.erase(bit); - } + for (auto bit : input_bits) + undriven_bits.erase(bit); for (auto bit : output_bits) if (!bit.wire->port_input) @@ -275,7 +271,8 @@ struct XAigerWriter } } } - if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); undriven_bits.erase(q); -- cgit v1.2.3 From eaf3c247729365cec776e147f380ce59f7dccd4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:54:19 -0700 Subject: Temporarily remove 'r' extension --- backends/aiger/xaiger.cc | 84 ++++-------------------------------------------- 1 file changed, 7 insertions(+), 77 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..d6438a297 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; - vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -175,7 +174,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -252,32 +250,7 @@ struct XAigerWriter // continue; //} - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - d = b; - } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - - ff_bits.emplace_back(d, q); - undriven_bits.erase(q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -420,20 +393,10 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - auto bit = f.second; - aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - auto r = aig_map.insert(std::make_pair(c.first, c.second)); - if (!r.second) { - ff_aig_map[c.first] = c.second; - } + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -508,11 +471,6 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto &f : ff_bits) { - aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); - } - if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -670,7 +628,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -685,10 +643,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -741,34 +699,6 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } - if (holes_module) { holes_module->fixup_ports(); -- cgit v1.2.3 From 8f30019b68c68258979137a9d9fbbe68794781c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:41:21 -0700 Subject: Revert "Temporarily remove 'r' extension" This reverts commit eaf3c247729365cec776e147f380ce59f7dccd4d. --- backends/aiger/xaiger.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -174,6 +175,7 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -250,7 +252,32 @@ struct XAigerWriter // continue; //} - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -393,10 +420,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -471,6 +508,11 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -628,7 +670,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -643,10 +685,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -699,6 +741,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); -- cgit v1.2.3 From 0bf9d0087c43f9db3d56cb2bed17268def21eb67 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 09:35:14 +0200 Subject: Add support for $assert/$assume/$cover to write_verilog Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 9967482d6..1c65e79b7 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1242,6 +1242,16 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type.in("$assert", "$assume", "$cover")) + { + f << stringf("%s" "always @* if (", indent.c_str()); + dump_sigspec(f, cell->getPort("\\EN")); + f << stringf(") %s(", cell->type.c_str()+1); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(");\n"); + return true; + } + // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_ // FIXME: $sr, $dlatch, $memrd, $memwr, $fsm -- cgit v1.2.3 From 846eb5ea98594daed7bf80a3e9c077a1ce7cf6f2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 09:49:55 +0200 Subject: Add $specify2/$specify3 support to write_verilog Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 1c65e79b7..6bb08fdb2 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1252,6 +1252,53 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type.in("$specify2", "$specify3")) + { + f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); + + SigSpec en = cell->getPort("\\EN"); + if (en != State::S1) { + f << stringf("if ("); + dump_sigspec(f, cell->getPort("\\EN")); + f << stringf(") "); + } + + f << "("; + if (cell->type == "$specify3" && cell->getParam("\\EDGE_EN").as_bool()) + f << (cell->getParam("\\EDGE_POL").as_bool() ? "posedge ": "negedge "); + + dump_sigspec(f, cell->getPort("\\SRC")); + + f << " "; + if (cell->getParam("\\SRC_DST_PEN").as_bool()) + f << (cell->getParam("\\SRC_DST_POL").as_bool() ? "+": "-"); + f << (cell->getParam("\\FULL").as_bool() ? "*> ": "=> "); + + if (cell->type == "$specify3") { + f << "("; + dump_sigspec(f, cell->getPort("\\DST")); + f << " "; + if (cell->getParam("\\DAT_DST_PEN").as_bool()) + f << (cell->getParam("\\DAT_DST_POL").as_bool() ? "+": "-"); + f << ": "; + dump_sigspec(f, cell->getPort("\\DAT")); + f << ")"; + } else { + dump_sigspec(f, cell->getPort("\\DST")); + } + + f << stringf(") = (%d:%d:%d, %d:%d:%d);\n", + cell->getParam("\\T_RISE_MIN").as_int(), + cell->getParam("\\T_RISE_AVG").as_int(), + cell->getParam("\\T_RISE_MAX").as_int(), + cell->getParam("\\T_FALL_MIN").as_int(), + cell->getParam("\\T_FALL_AVG").as_int(), + cell->getParam("\\T_FALL_MAX").as_int()); + + f << stringf("%s" "endspecify\n", indent.c_str()); + return true; + } + // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_ // FIXME: $sr, $dlatch, $memrd, $memwr, $fsm -- cgit v1.2.3 From e807e88b607834170692f56a5538b89fd4175a36 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 09:52:47 +0200 Subject: Rename T_{RISE,FALL}_AVG to T_{RISE,FALL}_TYP to better match verilog std nomenclature Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6bb08fdb2..93eaa8feb 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1289,10 +1289,10 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf(") = (%d:%d:%d, %d:%d:%d);\n", cell->getParam("\\T_RISE_MIN").as_int(), - cell->getParam("\\T_RISE_AVG").as_int(), + cell->getParam("\\T_RISE_TYP").as_int(), cell->getParam("\\T_RISE_MAX").as_int(), cell->getParam("\\T_FALL_MIN").as_int(), - cell->getParam("\\T_FALL_AVG").as_int(), + cell->getParam("\\T_FALL_TYP").as_int(), cell->getParam("\\T_FALL_MAX").as_int()); f << stringf("%s" "endspecify\n", indent.c_str()); -- cgit v1.2.3 From bfd71e09906096c72039beebb1b3b6a79dd6b36c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..504a66086 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -133,6 +133,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -151,8 +153,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -338,10 +342,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -354,7 +360,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -750,7 +758,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } -- cgit v1.2.3 From ac2aff9e28a087a9a2697cd6ccf754af738903a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..7126002f6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -134,6 +134,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -152,8 +154,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -365,10 +369,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -381,7 +387,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -820,7 +828,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } -- cgit v1.2.3 From eec314e2621d3d055d7810f4b7e573a99e0239b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 24 Apr 2019 21:06:53 -0700 Subject: Remove topo sort no-loop assertion, with test --- backends/aiger/xaiger.cc | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 504a66086..f9d874e2d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -294,20 +294,7 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); -#ifndef NDEBUG - toposort.analyze_loops = true; -#endif toposort.sort(); -#ifndef NDEBUG - for (auto &it : toposort.loops) { - log(" loop"); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); - } -#endif - log_assert(!toposort.found_loops); - for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); -- cgit v1.2.3 From 38f5424f92389d6f4fdf020b214023b2b6efa71a Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 1 May 2019 13:16:01 -0700 Subject: Fix #938 - Crash occurs in case when use write_firrtl command Add missing memory initialization. Sanity-check memory parameters. Add Cell pointer to memory object (for error reporting). --- backends/firrtl/firrtl.cc | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index ed6e9f8ee..a8a1bb078 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -164,6 +164,7 @@ struct FirrtlWorker }; /* Memories defined within this module. */ struct memory { + Cell *pCell; // for error reporting string name; // memory name int abits; // number of address bits int size; // size (in units) of the memory @@ -174,8 +175,37 @@ struct FirrtlWorker vector write_ports; std::string init_file; std::string init_file_srcFileSpec; - memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {} - memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + string srcLine; + memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { + // Provide defaults for abits or size if one (but not the other) is specified. + if (this->abits == 0 && this->size != 0) { + this->abits = ceil_log2(this->size); + } else if (this->abits != 0 && this->size == 0) { + this->size = 1 << this->abits; + } + // Sanity-check this construction. + if (this->name == "") { + log_error("Nameless memory%s\n", this->atLine()); + } + if (this->abits == 0 && this->size == 0) { + log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine()); + } + if (this->width == 0) { + log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); + } + } + // We need a default constructor for the dict insert. + memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + + const char *atLine() { + if (srcLine == "") { + if (pCell) { + auto p = pCell->attributes.find("\\src"); + srcLine = " at " + p->second.decode_string(); + } + } + return srcLine.c_str(); + } void add_memory_read_port(read_port &rp) { read_ports.push_back(rp); } @@ -604,7 +634,7 @@ struct FirrtlWorker int abits = cell->parameters.at("\\ABITS").as_int(); int width = cell->parameters.at("\\WIDTH").as_int(); int size = cell->parameters.at("\\SIZE").as_int(); - memory m(mem_id, abits, size, width); + memory m(cell, mem_id, abits, size, width); int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); @@ -681,6 +711,8 @@ struct FirrtlWorker { std::string cell_type = fid(cell->type); std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); + int abits = cell->parameters.at("\\ABITS").as_int(); + int width = cell->parameters.at("\\WIDTH").as_int(); memory *mp = nullptr; if (cell->type == "$meminit" ) { log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); @@ -693,6 +725,11 @@ struct FirrtlWorker Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); + // Do we already have an entry for this memory? + if (memories.count(mem_id) == 0) { + memory m(cell, mem_id, abits, 0, width); + register_memory(m); + } mp = &memories.at(mem_id); int portNum = 0; bool transparency = false; @@ -890,7 +927,7 @@ struct FirrtlWorker // If we have any memory definitions, output them. for (auto kv : memories) { - memory m = kv.second; + memory &m = kv.second; f << stringf(" mem %s:\n", m.name.c_str()); f << stringf(" data-type => UInt<%d>\n", m.width); f << stringf(" depth => %d\n", m.size); -- cgit v1.2.3 From 6ea09caf01cf06ad7f93eb62fa85ec9361b7e5a1 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 1 May 2019 16:21:13 -0700 Subject: Re-indent firrtl.cc:struct memory - no functional change. --- backends/firrtl/firrtl.cc | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index a8a1bb078..9feff71c6 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -163,20 +163,20 @@ struct FirrtlWorker } }; /* Memories defined within this module. */ - struct memory { - Cell *pCell; // for error reporting - string name; // memory name - int abits; // number of address bits - int size; // size (in units) of the memory - int width; // size (in bits) of each element - int read_latency; - int write_latency; - vector read_ports; - vector write_ports; - std::string init_file; - std::string init_file_srcFileSpec; - string srcLine; - memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { + struct memory { + Cell *pCell; // for error reporting + string name; // memory name + int abits; // number of address bits + int size; // size (in units) of the memory + int width; // size (in bits) of each element + int read_latency; + int write_latency; + vector read_ports; + vector write_ports; + std::string init_file; + std::string init_file_srcFileSpec; + string srcLine; + memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { // Provide defaults for abits or size if one (but not the other) is specified. if (this->abits == 0 && this->size != 0) { this->abits = ceil_log2(this->size); @@ -206,18 +206,18 @@ struct FirrtlWorker } return srcLine.c_str(); } - void add_memory_read_port(read_port &rp) { - read_ports.push_back(rp); - } - void add_memory_write_port(write_port &wp) { - write_ports.push_back(wp); - } - void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { - this->init_file = init_file; - this->init_file_srcFileSpec = init_file_srcFileSpec; - } + void add_memory_read_port(read_port &rp) { + read_ports.push_back(rp); + } + void add_memory_write_port(write_port &wp) { + write_ports.push_back(wp); + } + void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { + this->init_file = init_file; + this->init_file_srcFileSpec = init_file_srcFileSpec; + } - }; + }; dict memories; void register_memory(memory &m) -- cgit v1.2.3 From 87426f5a06b0cf9d1fe44efda65e3c048d89d322 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 4 May 2019 08:46:24 +0200 Subject: Improve write_verilog specify support Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 86 ++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 15 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 93eaa8feb..9fd4ccbc8 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -183,8 +183,9 @@ bool is_reg_wire(RTLIL::SigSpec sig, std::string ®_name) return true; } -void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false, bool escape_comment = false) +void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool escape_comment = false) { + bool set_signed = (data.flags & RTLIL::CONST_FLAG_SIGNED) != 0; if (width < 0) width = data.bits.size() - offset; if (width == 0) { @@ -275,7 +276,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } } else { - f << stringf("\""); + if ((data.flags & RTLIL::CONST_FLAG_REAL) == 0) + f << stringf("\""); std::string str = data.decode_string(); for (size_t i = 0; i < str.size(); i++) { if (str[i] == '\n') @@ -293,7 +295,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o else f << str[i]; } - f << stringf("\""); + if ((data.flags & RTLIL::CONST_FLAG_REAL) == 0) + f << stringf("\""); } } @@ -373,7 +376,7 @@ void dump_attributes(std::ostream &f, std::string indent, dictsecond == Const(1, 1) || it->second == Const(1))) f << stringf(" 1 "); else - dump_const(f, it->second, -1, 0, false, false, attr2comment); + dump_const(f, it->second, -1, 0, false, attr2comment); f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); } } @@ -1287,13 +1290,68 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) dump_sigspec(f, cell->getPort("\\DST")); } - f << stringf(") = (%d:%d:%d, %d:%d:%d);\n", - cell->getParam("\\T_RISE_MIN").as_int(), - cell->getParam("\\T_RISE_TYP").as_int(), - cell->getParam("\\T_RISE_MAX").as_int(), - cell->getParam("\\T_FALL_MIN").as_int(), - cell->getParam("\\T_FALL_TYP").as_int(), - cell->getParam("\\T_FALL_MAX").as_int()); + bool bak_decimal = decimal; + decimal = 1; + + f << ") = ("; + dump_const(f, cell->getParam("\\T_RISE_MIN")); + f << ":"; + dump_const(f, cell->getParam("\\T_RISE_TYP")); + f << ":"; + dump_const(f, cell->getParam("\\T_RISE_MAX")); + f << ", "; + dump_const(f, cell->getParam("\\T_FALL_MIN")); + f << ":"; + dump_const(f, cell->getParam("\\T_FALL_TYP")); + f << ":"; + dump_const(f, cell->getParam("\\T_FALL_MAX")); + f << ");\n"; + + decimal = bak_decimal; + + f << stringf("%s" "endspecify\n", indent.c_str()); + return true; + } + + if (cell->type == "$specrule") + { + f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); + + string spec_type = cell->getParam("\\TYPE").decode_string(); + f << stringf("%s(", spec_type.c_str()); + + if (cell->getParam("\\SRC_PEN").as_bool()) + f << (cell->getParam("\\SRC_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\SRC")); + + if (cell->getPort("\\SRC_EN") != State::S1) { + f << " &&& "; + dump_sigspec(f, cell->getPort("\\SRC_EN")); + } + + f << ", "; + if (cell->getParam("\\DST_PEN").as_bool()) + f << (cell->getParam("\\DST_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\DST")); + + if (cell->getPort("\\DST_EN") != State::S1) { + f << " &&& "; + dump_sigspec(f, cell->getPort("\\DST_EN")); + } + + bool bak_decimal = decimal; + decimal = 1; + + f << ", "; + dump_const(f, cell->getParam("\\T_LIMIT")); + + if (spec_type == "$setuphold" || spec_type == "$recrem" || spec_type == "$fullskew") { + f << ", "; + dump_const(f, cell->getParam("\\T_LIMIT2")); + } + + f << ");\n"; + decimal = bak_decimal; f << stringf("%s" "endspecify\n", indent.c_str()); return true; @@ -1321,8 +1379,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (it != cell->parameters.begin()) f << stringf(","); f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str()); - bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; - dump_const(f, it->second, -1, 0, false, is_signed); + dump_const(f, it->second); f << stringf(")"); } f << stringf("\n%s" ")", indent.c_str()); @@ -1369,8 +1426,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (defparam && cell->parameters.size() > 0) { for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { f << stringf("%sdefparam %s.%s = ", indent.c_str(), cell_name.c_str(), id(it->first).c_str()); - bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; - dump_const(f, it->second, -1, 0, false, is_signed); + dump_const(f, it->second); f << stringf(";\n"); } } -- cgit v1.2.3 From 1cd1b5fc1adeb3ef62f061e27f5d8433d5c7dce6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 6 May 2019 12:00:40 +0200 Subject: Add "real" keyword to ilang format Signed-off-by: Clifford Wolf --- backends/ilang/ilang_backend.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index dc39e5e08..04d1ee311 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -160,7 +160,10 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: } f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); for (auto &it : cell->parameters) { - f << stringf("%s parameter%s %s ", indent.c_str(), (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it.first.c_str()); + f << stringf("%s parameter%s%s %s ", indent.c_str(), + (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", + (it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", + it.first.c_str()); dump_const(f, it.second); f << stringf("\n"); } -- cgit v1.2.3 From 33738c174560c718723b6c860af002d1a8a91cea Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 7 May 2019 19:55:36 +0200 Subject: Fix handling of partial init attributes in write_verilog, fixes #997 Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 9fd4ccbc8..827af5d85 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1618,7 +1618,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) SigSpec sig = active_sigmap(wire); Const val = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(sig) && i < GetSize(val); i++) - active_initdata[sig[i]] = val.bits.at(i); + if (val[i] == State::S0 || val[i] == State::S1) + active_initdata[sig[i]] = val[i]; } if (!module->processes.empty()) -- cgit v1.2.3 From 30c762d3a148afa9e27a93c1fa098b7c478511a4 Mon Sep 17 00:00:00 2001 From: Kristoffer Ellersgaard Koch Date: Sun, 5 May 2019 10:00:27 +0200 Subject: Fix all warnings that occurred when compiling with gcc9 --- backends/firrtl/firrtl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 9feff71c6..fe6bdb8f6 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -344,6 +344,7 @@ struct FirrtlWorker switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); + /* FALLTHRU */ case FD_OUT: sourceExpr = firstName; sinkExpr = secondExpr; @@ -351,7 +352,7 @@ struct FirrtlWorker break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); - /* FALL_THROUGH */ + /* FALLTHRU */ case FD_IN: sourceExpr = secondExpr; sinkExpr = firstName; -- cgit v1.2.3 From a5131e28966757c3c8b79bee838005c0246f6331 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 21 May 2019 13:04:56 -0700 Subject: Fix static shift operands, neg result type, minor formatting Static shift operands must be constants. The result of FIRRTL's neg operator is signed. Fix poor indentation for gen_read(). --- backends/firrtl/firrtl.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index fe6bdb8f6..1c7a7351f 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -146,7 +146,7 @@ struct FirrtlWorker if (!mask.is_fully_def()) this->ena = SigSpec(RTLIL::Const(1)); } - string gen_read(const char * /* indent */) { + string gen_read(const char * /* indent */) { log_error("gen_read called on write_port: %s\n", name.c_str()); return stringf("gen_read called on write_port: %s\n", name.c_str()); } @@ -449,8 +449,10 @@ struct FirrtlWorker string primop; bool always_uint = false; if (cell->type == "$not") primop = "not"; - else if (cell->type == "$neg") primop = "neg"; - else if (cell->type == "$logic_not") { + else if (cell->type == "$neg") { + primop = "neg"; + is_signed = true; // Result of "neg" is signed (an SInt). + } else if (cell->type == "$logic_not") { primop = "eq"; a_expr = stringf("%s, UInt(0)", a_expr.c_str()); } @@ -562,6 +564,7 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; + b_expr = std::to_string(b_sig.as_int()); } else { primop = "dshl"; // Convert from FIRRTL left shift semantics. @@ -575,6 +578,7 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shr"; + b_expr = std::to_string(b_sig.as_int()); } else { primop = "dshr"; } -- cgit v1.2.3 From 0f094fba08b69baa2329e749daf19f41a624a0a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 16:19:23 -0700 Subject: Pad all boxes so that all input/output connections specified --- backends/aiger/xaiger.cc | 89 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 22 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f9d874e2d..676311440 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -301,6 +301,35 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Fully pad all unused input connections of this box cell with S0 + // Fully pad all undriven output connections of thix box cell with anonymous wires + for (const auto w : box_module->wires()) { + if (w->port_input) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + } + if (w->port_output) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); + } + } + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { @@ -646,37 +675,53 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); + log_assert(holes_module); + dict> box_io; for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + RTLIL::Module* box_module = module->design->module(cell->type); + int box_id = box_module->attributes.at("\\abc_box_id").as_int(); Cell *holes_cell = nullptr; - if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + int box_inputs = 0, box_outputs = 0; + + auto it = box_io.find(cell->type); + if (it == box_io.end()) { holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - RTLIL::Wire *holes_wire; - // NB: cell->connections_ already sorted from before - for (const auto &c : cell->connections()) { - log_assert(c.second.size() == 1); - if (cell->input(c.first)) { - box_inputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; + + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + } + port_wire.append(holes_wire); } - holes_cell->setPort(c.first, holes_wire); + holes_cell->setPort(w->name, holes_wire); } - } - if (cell->output(c.first)) { - box_outputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); - holes_wire->port_output = true; - holes_cell->setPort(c.first, holes_wire); + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); + } + holes_cell->setPort(w->name, holes_wire); } } + box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } + else + std::tie(box_inputs,box_outputs) = it->second; + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id); -- cgit v1.2.3 From b7dd7c2dcd8e3e9b10407799f2978872a80f1860 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 24 May 2019 16:22:34 +0200 Subject: Add proper error message for btor recursion_guard Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 91f238fa5..511a11942 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -129,7 +129,13 @@ struct BtorWorker void export_cell(Cell *cell) { - log_assert(cell_recursion_guard.count(cell) == 0); + if (cell_recursion_guard.count(cell)) { + string cell_list; + for (auto c : cell_recursion_guard) + cell_list += stringf("\n %s", log_id(c)); + log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list.c_str()); + } + cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); -- cgit v1.2.3 From 6352df42ae3f41880c309d00df2db2eba9126d42 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 25 May 2019 17:45:14 +0200 Subject: Fix handling of offset and upto module ports in write_blif, fixes #1040 Signed-off-by: Clifford Wolf --- backends/blif/blif.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index b6dbd84cb..a1761b662 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -409,12 +409,26 @@ struct BlifDumper f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type)); for (auto &conn : cell->connections()) - for (int i = 0; i < conn.second.size(); i++) { - if (conn.second.size() == 1) - f << stringf(" %s", cstr(conn.first)); - else - f << stringf(" %s[%d]", cstr(conn.first), i); - f << stringf("=%s", cstr(conn.second.extract(i, 1))); + { + if (conn.second.size() == 1) { + f << stringf(" %s=%s", cstr(conn.first), cstr(conn.second[0])); + continue; + } + + Module *m = design->module(cell->type); + Wire *w = m ? m->wire(conn.first) : nullptr; + + if (w == nullptr) { + for (int i = 0; i < GetSize(conn.second); i++) + f << stringf(" %s[%d]=%s", cstr(conn.first), i, cstr(conn.second[i])); + } else { + for (int i = 0; i < std::min(GetSize(conn.second), GetSize(w)); i++) { + SigBit sig(w, i); + f << stringf(" %s[%d]=%s", cstr(conn.first), sig.wire->upto ? + sig.wire->start_offset+sig.wire->width-sig.offset-1 : + sig.wire->start_offset+sig.offset, cstr(conn.second[i])); + } + } } f << stringf("\n"); -- cgit v1.2.3 From 01684643b6edd4290701b2e08114cb731db5f446 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 25 May 2019 22:34:50 -0700 Subject: Fix "write_xaiger", and to write each box contents into holes --- backends/aiger/xaiger.cc | 101 +++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 39 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 676311440..7e674cb87 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -385,8 +385,9 @@ struct XAigerWriter // Do some CI/CO post-processing: // Erase all POs that are undriven - for (auto bit : undriven_bits) - output_bits.erase(bit); + if (!holes_mode) + for (auto bit : undriven_bits) + output_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); @@ -676,55 +677,45 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); - dict> box_io; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); - int box_id = box_module->attributes.at("\\abc_box_id").as_int(); - Cell *holes_cell = nullptr; int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = holes_module->addCell(cell->name, cell->type); - auto it = box_io.find(cell->type); - if (it == box_io.end()) { - holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - - RTLIL::Wire *holes_wire; - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { - RTLIL::SigSpec port_wire; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - } - port_wire.append(holes_wire); + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; } - holes_cell->setPort(w->name, holes_wire); + port_wire.append(holes_wire); } - if (w->port_output) { - box_outputs += GetSize(w); - for (int i = 0; i < GetSize(w); i++) { - if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); - else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); - holes_wire->port_output = true; - port_wire.append(holes_wire); - } - holes_cell->setPort(w->name, holes_wire); + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); } + holes_cell->setPort(w->name, port_wire); } - box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } - else - std::tie(box_inputs,box_outputs) = it->second; write_h_buffer(box_inputs); write_h_buffer(box_outputs); - write_h_buffer(box_id); + write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); write_h_buffer(0 /* OldBoxNum */); } @@ -746,7 +737,16 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); + + Pass::call(holes_module->design, "flatten -wb;"); + + // TODO: Should techmap all lib_whitebox-es once + Pass::call(holes_module->design, "techmap;"); + + Pass::call(holes_module->design, "aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -766,6 +766,29 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } + + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(0); + + f << "r"; + buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); -- cgit v1.2.3 From 32a4c10c0df7e82c69b0d96a63be0c5267d33257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 02:44:36 -0700 Subject: Fix "a" extension --- backends/aiger/xaiger.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e674cb87..3d275214b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -681,9 +681,12 @@ struct XAigerWriter for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = holes_module->addCell(cell->name, cell->type); + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) + holes_cell = holes_module->addCell(cell->name, cell->type); RTLIL::Wire *holes_wire; + // TODO: Only sort once box_module->wires_.sort(RTLIL::sort_by_id_str()); for (const auto w : box_module->wires()) { RTLIL::SigSpec port_wire; @@ -695,9 +698,11 @@ struct XAigerWriter holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } if (w->port_output) { box_outputs += GetSize(w); @@ -707,9 +712,13 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, RTLIL::S0); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -741,12 +750,13 @@ struct XAigerWriter // each box type once... Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb;"); + Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - Pass::call(holes_module->design, "techmap;"); + //Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap; clean -purge"); + Pass::call(holes_module->design, "aigmap"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); -- cgit v1.2.3 From 67f7c64a778e46882f884fd7058dc7bc07c5ca1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 11:26:38 -0700 Subject: Fix padding, remove CIs from undriven_bits before erasing undriven POs --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d275214b..618a6500d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -302,16 +302,13 @@ struct XAigerWriter continue; // Fully pad all unused input connections of this box cell with S0 - // Fully pad all undriven output connections of thix box cell with anonymous wires + // Fully pad all undriven output connections of this box cell with anonymous wires for (const auto w : box_module->wires()) { if (w->port_input) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); @@ -319,11 +316,8 @@ struct XAigerWriter if (w->port_output) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); @@ -384,13 +378,13 @@ struct XAigerWriter } // Do some CI/CO post-processing: + // CIs cannot be undriven + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) output_bits.erase(bit); - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 3c8368454f5f9643425bab0065158587b03e2716 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 14:14:13 -0700 Subject: Fix "a" connectivity --- backends/aiger/xaiger.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 618a6500d..6cf0cb026 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -398,8 +398,25 @@ struct XAigerWriter } init_map.sort(); - input_bits.sort(); - output_bits.sort(); + if (holes_mode) { +#ifndef NDEBUG + RTLIL::SigBit last_bit; + for (auto bit : input_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } + last_bit = RTLIL::SigBit(); + for (auto bit : output_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } +#endif + } + else { + input_bits.sort(); + output_bits.sort(); + } + not_map.sort(); ff_map.sort(); and_map.sort(); @@ -415,7 +432,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -672,6 +689,7 @@ struct XAigerWriter holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); + int port_id = 1; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -691,6 +709,8 @@ struct XAigerWriter if (!holes_wire) { holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); } if (holes_cell) port_wire.append(holes_wire); @@ -706,6 +726,8 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); if (holes_cell) port_wire.append(holes_wire); else @@ -734,7 +756,9 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - holes_module->fixup_ports(); + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); holes_module->design->selection_stack.emplace_back(false); RTLIL::Selection& sel = holes_module->design->selection_stack.back(); @@ -750,7 +774,8 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + //TODO: clean will mess up port_ids + //Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); -- cgit v1.2.3 From 03b289a851c62eb2a7e3592432876bfa8a56770b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 11:38:52 -0700 Subject: Add 'cinput' and 'coutput' to symbols file for boxes --- backends/aiger/xaiger.cc | 58 ++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6cf0cb026..582e8e076 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -49,7 +49,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; //pool initstate_bits; - vector> ci_bits, co_bits; + vector> ci_bits; + vector> co_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -327,6 +328,7 @@ struct XAigerWriter // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { + int offset = 0; for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); @@ -335,11 +337,11 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.emplace_back(b, 0); + co_bits.emplace_back(b, cell, c.first, offset++, 0); } if (is_output) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, cell, c.first, offset++); } } } @@ -380,7 +382,7 @@ struct XAigerWriter // Do some CI/CO post-processing: // CIs cannot be undriven for (const auto &c : ci_bits) - undriven_bits.erase(c.first); + undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) @@ -399,18 +401,13 @@ struct XAigerWriter init_map.sort(); if (holes_mode) { -#ifndef NDEBUG - RTLIL::SigBit last_bit; - for (auto bit : input_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } - last_bit = RTLIL::SigBit(); - for (auto bit : output_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } -#endif + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); } else { input_bits.sort(); @@ -431,8 +428,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; - c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[std::get<0>(c)] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -496,9 +492,9 @@ struct XAigerWriter // aig_latchin.push_back(1); for (auto &c : co_bits) { - RTLIL::SigBit bit = c.first; - c.second = aig_o++; - ordered_outputs[bit] = c.second; + RTLIL::SigBit bit = std::get<0>(c); + std::get<4>(c) = aig_o++; + ordered_outputs[bit] = std::get<4>(c); aig_outputs.push_back(bit2aig(bit)); } @@ -774,8 +770,7 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - //TODO: clean will mess up port_ids - //Pass::call(holes_module->design, "clean -purge"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -880,22 +875,17 @@ struct XAigerWriter } for (const auto &c : ci_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int i = b.offset; + RTLIL::SigBit b = std::get<0>(c); + int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } for (const auto &c : co_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int o = c.second; - if (wire) - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); - else - output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); + int i = std::get<3>(c); + int o = std::get<4>(c); + output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } input_lines.sort(); -- cgit v1.2.3 From 234156c01a4086a69ff9ac9f6ae668d64734d525 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:16:10 -0700 Subject: Instantiate cell type (from sym file) otherwise 'clean' warnings --- backends/aiger/xaiger.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582e8e076..3c96f6c9e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -879,13 +879,15 @@ struct XAigerWriter int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } for (const auto &c : co_bits) { int i = std::get<3>(c); int o = std::get<4>(c); - output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } input_lines.sort(); -- cgit v1.2.3 From 3f60061615a8b5df3ad05b997407f195c8197754 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:10:59 -0700 Subject: Map file to include boxes not CI/CO --- backends/aiger/xaiger.cc | 83 ++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 45 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3c96f6c9e..2bc059dc5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -304,48 +304,52 @@ struct XAigerWriter // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires - for (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + auto it = cell->connections_.find(port_name); if (w->port_input) { - auto it = cell->connections_.find(w->name); + RTLIL::SigSpec rhs; if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + cell->setPort(port_name, rhs); + } + + int offset = 0; + for (const auto &b : rhs.bits()) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, cell, port_name, offset++, 0); } - else - cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); } if (w->port_output) { + RTLIL::SigSpec rhs; auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); + rhs = it->second; } - else - cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); - } - } - - // Box ordering is alphabetical - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - int offset = 0; - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - co_bits.emplace_back(b, cell, c.first, offset++, 0); + else { + rhs = module->addWire(NEW_ID, GetSize(w)); + cell->setPort(port_name, rhs); } - if (is_output) { + + int offset = 0; + for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, c.first, offset++); + ci_bits.emplace_back(O, cell, port_name, offset++); } } } - box_list.emplace_back(cell); } @@ -686,6 +690,7 @@ struct XAigerWriter log_assert(holes_module); int port_id = 1; + int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -737,7 +742,7 @@ struct XAigerWriter write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(0 /* OldBoxNum */); + write_h_buffer(box_count++); } f << "h"; @@ -844,7 +849,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); continue; } @@ -874,35 +879,23 @@ struct XAigerWriter } } - for (const auto &c : ci_bits) { - RTLIL::SigBit b = std::get<0>(c); - int i = std::get<3>(c); - int a = bit2aig(b); - log_assert((a & 1) == 0); - RTLIL::Cell* cell = std::get<1>(c); - input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - - for (const auto &c : co_bits) { - int i = std::get<3>(c); - int o = std::get<4>(c); - RTLIL::Cell* cell = std::get<1>(c); - output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - input_lines.sort(); for (auto &it : input_lines) f << it.second; - log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); + log_assert(input_lines.size() == input_bits.size()); init_lines.sort(); for (auto &it : init_lines) f << it.second; + int box_count = 0; + for (auto cell : box_list) + f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); + output_lines.sort(); for (auto &it : output_lines) f << it.second; - log_assert(output_lines.size() == output_bits.size() + co_bits.size()); + log_assert(output_lines.size() == output_bits.size()); if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; -- cgit v1.2.3 From 914074a07c14709523cc72084e1673bd3c2eaf30 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:35:45 -0700 Subject: Update from master --- backends/json/json.cc | 115 ++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 59 deletions(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index b4f82a3fe..f5c687981 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,75 +130,72 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n }"); + f << stringf("\n },\n"); - if (!module->get_blackbox_attribute()) { - f << stringf(",\n \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); - } - } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); - first2 = false; - } - f << stringf("\n },\n"); + f << stringf(" \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); } - f << stringf(" \"connections\": {"); + } + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); bool first2 = true; for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); first2 = false; } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf("\n },\n"); } - f << stringf("\n },\n"); - - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"connections\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + first2 = false; } - f << stringf("\n }"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n },\n"); + + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf("\n"); + f << stringf("\n }\n"); f << stringf(" }"); } -- cgit v1.2.3 From 13e233217cd0caceeb5d30d2eefa5238ffc5bfc9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 11:29:59 -0700 Subject: Small improvement --- backends/aiger/xaiger.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2bc059dc5..5919b2302 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -328,6 +328,7 @@ struct XAigerWriter if (I != b) alias_map[b] = I; co_bits.emplace_back(b, cell, port_name, offset++, 0); + unused_bits.erase(b); } } if (w->port_output) { @@ -347,6 +348,7 @@ struct XAigerWriter for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); ci_bits.emplace_back(O, cell, port_name, offset++); + undriven_bits.erase(O); } } } @@ -383,10 +385,6 @@ struct XAigerWriter } } - // Do some CI/CO post-processing: - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) -- cgit v1.2.3 From b4321a31bbd9f215e753563d5d031b2c24f1b371 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 12:42:17 -0700 Subject: Fix for abc9_test022 --- backends/aiger/xaiger.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5919b2302..2ffd460dd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -277,8 +277,10 @@ struct XAigerWriter } } if (is_output) { + input_bits.insert(b); SigBit O = sigmap(b); - input_bits.insert(O); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } @@ -346,8 +348,10 @@ struct XAigerWriter int offset = 0; for (const auto &b : rhs.bits()) { + ci_bits.emplace_back(b, cell, port_name, offset++); SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, port_name, offset++); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } -- cgit v1.2.3 From 1423384367d4fa31f09c6c7b69c1b89edc3dd066 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:24:09 -0700 Subject: Fix abc_test024 --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2ffd460dd..bf696bfd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,10 +152,11 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - if (wire->port_input) - input_bits.insert(bit); - else if (keep) + if (wire->port_input || keep) { + if (bit != wirebit) + alias_map[bit] = wirebit; input_bits.insert(wirebit); + } if (wire->port_output || keep) { if (bit != wirebit) @@ -166,7 +167,7 @@ struct XAigerWriter } for (auto bit : input_bits) - undriven_bits.erase(bit); + undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) if (!bit.wire->port_input) -- cgit v1.2.3 From fdfc18be91123e2939f134dafc12e1e0c1a82f7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 01:23:36 -0700 Subject: Carry in/out to be the last input/output for chains to be preserved --- backends/aiger/xaiger.cc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf696bfd6..25de7daba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -298,6 +298,8 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); + pool abc_carry_modules; + toposort.sort(); for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); @@ -305,6 +307,42 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; + RTLIL::Wire* last_in = nullptr, *last_out = nullptr; + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_input) { + if (w->attributes.count("\\abc_carry_in")) { + log_assert(!carry_in); + carry_in = w; + } + log_assert(!last_in || last_in->port_id < w->port_id); + last_in = w; + } + if (w->port_output) { + if (w->attributes.count("\\abc_carry_out")) { + log_assert(!carry_out); + carry_out = w; + } + log_assert(!last_out || last_out->port_id < w->port_id); + last_out = w; + } + } + + if (carry_in) { + log_assert(last_in); + std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); + std::swap(carry_in->port_id, last_in->port_id); + } + if (carry_out) { + log_assert(last_out); + std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); + std::swap(carry_out->port_id, last_out->port_id); + } + } + // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires // NB: Assume box_module->ports are sorted alphabetically -- cgit v1.2.3 From e3c8132d7acaae328adeb8d4db1857275b5e8323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 12:26:51 -0700 Subject: Do not re-sort box_module ports --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25de7daba..efdd1844b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -739,10 +739,12 @@ struct XAigerWriter if (box_module->get_bool_attribute("\\whitebox")) holes_cell = holes_module->addCell(cell->name, cell->type); - RTLIL::Wire *holes_wire; - // TODO: Only sort once - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; RTLIL::SigSpec port_wire; if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { -- cgit v1.2.3 From 887c31f33b82e5cb3f50523873d41ceb0cb8e7f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 16:03:22 -0700 Subject: Fix issue where keep signal became PI, but also box was adding CI driver --- backends/aiger/xaiger.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index efdd1844b..cd15b6160 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -392,6 +392,12 @@ struct XAigerWriter if (O != b) alias_map[O] = b; undriven_bits.erase(O); + + auto jt = input_bits.find(b); + if (jt != input_bits.end()) { + log_assert(b.wire->attributes.count("\\keep")); + input_bits.erase(b); + } } } } @@ -409,9 +415,10 @@ struct XAigerWriter if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { log_assert(input_bits.count(bit) && output_bits.count(bit)); - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; + RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); if (not_map.count(bit)) @@ -468,12 +475,15 @@ struct XAigerWriter for (auto bit : input_bits) { aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } for (auto &c : ci_bits) { + RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - aig_map[std::get<0>(c)] = 2*aig_m; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -538,8 +548,7 @@ struct XAigerWriter for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = aig_o++; - ordered_outputs[bit] = std::get<4>(c); + std::get<4>(c) = ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -720,10 +729,15 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", num_outputs + co_bits.size()); write_h_buffer(num_outputs + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", num_outputs); write_h_buffer(num_outputs); + log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; -- cgit v1.2.3 From 4623177655892c4aaf68757efff89aa748090c58 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 15:23:33 -0700 Subject: ABC9 to understand flops --- backends/aiger/xaiger.cc | 73 ++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 46 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7a139f68f..90fea2db1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,7 +181,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -258,22 +257,28 @@ struct XAigerWriter // continue; //} + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + RTLIL::Wire* port = inst_module->wire(c.first); for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (is_input && port->attributes.count("\\abc_flop_d")) { d = b; + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; + if (is_output && port->attributes.count("\\abc_flop_q")) { + q = b; + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); } } } @@ -281,7 +286,6 @@ struct XAigerWriter abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); - undriven_bits.erase(q); } else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; @@ -507,8 +511,9 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; + RTLIL::SigBit bit = f.second; aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } @@ -516,12 +521,9 @@ struct XAigerWriter for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - //auto r = aig_map.insert(std::make_pair(c.first, c.second)); - //if (!r.second) { - // ff_aig_map[std::get<0>(c)] = 2*aig_m; - //} + auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); + if (!r.second) + ff_aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -597,7 +599,8 @@ struct XAigerWriter for (auto &f : ff_bits) { aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); + RTLIL::SigBit bit = f.second; + aig_outputs.push_back(ff_aig_map.at(bit)); } if (omode && output_bits.empty()) { @@ -778,8 +781,8 @@ struct XAigerWriter write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %d\n", num_outputs); - write_h_buffer(num_outputs); + log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -856,7 +859,7 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { + /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; auto write_r_buffer = [&r_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -867,6 +870,7 @@ struct XAigerWriter #endif r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) @@ -923,29 +927,6 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } - - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(0); - - f << "r"; - buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); -- cgit v1.2.3 From 257f7ff5f63635f0a754f34cf8af93ed06632b5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:30:54 -0700 Subject: When creating new holes cell, inherit parameters too --- backends/aiger/xaiger.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 90fea2db1..818caebba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -796,8 +796,10 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) + if (box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) -- cgit v1.2.3 From 1b836c93bbaa3c85d4730b0251aed64cdf207422 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 11:56:58 -0700 Subject: Only toposort builtin and abc types --- backends/aiger/xaiger.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 818caebba..4d45bb650 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,14 +181,17 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool known_type = yosys_celltypes.cell_known(cell->type); + bool builtin_type = yosys_celltypes.cell_known(cell->type); + bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); if (!holes_mode) { toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { + for (const auto &conn : cell->connections()) { + if (!builtin_type && !abc_type) + continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { - if (known_type) { + if (builtin_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -199,8 +202,8 @@ struct XAigerWriter RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) + continue; } } -- cgit v1.2.3 From 7b186740d33972612cfc9f2ebe31258edb0cca2b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 12:01:25 -0700 Subject: Add log_assert to ensure no loops --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d45bb650..bf2f9f1bc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -334,7 +334,21 @@ struct XAigerWriter pool abc_carry_modules; - toposort.sort(); +#if 0 + toposort.analyze_loops = true; +#endif + bool no_loops = toposort.sort(); +#if 0 + unsigned i = 0; + for (auto &it : toposort.loops) { + log(" loop %d", i++); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif + log_assert(no_loops); + for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); -- cgit v1.2.3 From b21d29598a59f0f137a42f00a000b7937dabb402 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:40:51 -0700 Subject: Consistency --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf2f9f1bc..730f50f5b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2019 Eddie Hung + * 2019 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 From 4be417f6e15ee3f3d8da8cd75d8405b90d5b32ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:53:14 -0700 Subject: Cleanup write_xaiger --- backends/aiger/xaiger.cc | 98 +++--------------------------------------------- 1 file changed, 6 insertions(+), 92 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 730f50f5b..fd0620cac 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -624,14 +624,9 @@ struct XAigerWriter aig_o++; aig_outputs.push_back(0); } - - if (bmode) { - //aig_b++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -708,73 +703,6 @@ struct XAigerWriter } } - if (symbols_mode) - { - dict> symbols; - - bool output_seen = false; - for (auto wire : module->wires()) - { - //if (wire->name[0] == '$') - // continue; - - SigSpec sig = sigmap(wire); - - for (int i = 0; i < GetSize(wire); i++) - { - RTLIL::SigBit b(wire, i); - if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); - } - - if (output_bits.count(b)) { - int o = ordered_outputs.at(b); - output_seen = !miter_mode; - if (GetSize(wire) != 1) - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); - } - - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // if (GetSize(wire) != 1) - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - // else - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; - if (GetSize(wire) != 1) - symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); - else - symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); - } - } - } - - if (omode && !output_seen) - symbols["o0"].push_back("__dummy_o__"); - - symbols.sort(); - - for (auto &sym : symbols) { - f << sym.first; - std::sort(sym.second.begin(), sym.second.end()); - for (auto &s : sym.second) - f << " " << s; - f << std::endl; - } - } - f << "c"; if (!box_list.empty() || !ff_bits.empty()) { @@ -931,8 +859,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); f << "a"; std::string buffer_str = a_buffer.str(); @@ -1055,9 +983,6 @@ struct XAigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -symbols\n"); - log(" include a symbol table in the generated AIGER file\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -1074,12 +999,9 @@ struct XAigerBackend : public Backend { { bool ascii_mode = false; bool zinit_mode = false; - bool miter_mode = false; - bool symbols_mode = false; bool verbose_map = false; bool imode = false; bool omode = false; - bool bmode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1095,10 +1017,6 @@ struct XAigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-symbols") { - symbols_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1116,10 +1034,6 @@ struct XAigerBackend : public Backend { omode = true; continue; } - if (args[argidx] == "-B") { - bmode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1129,8 +1043,8 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); + XAigerWriter writer(top_module, zinit_mode, imode, omode); + writer.write_aiger(*f, ascii_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; -- cgit v1.2.3 From 14e870d4c47e18abf45f82f2d9329d1488e0650c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 10:00:57 -0700 Subject: More write_xaiger cleanup --- backends/aiger/xaiger.cc | 52 +++++++++++------------------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fd0620cac..af9a30135 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -543,10 +543,6 @@ struct XAigerWriter ff_aig_map[bit] = 2*aig_m; } - if (imode && input_bits.empty()) { - aig_m++, aig_i++; - } - //if (zinit_mode) //{ // for (auto it : ff_map) { @@ -620,13 +616,9 @@ struct XAigerWriter aig_outputs.push_back(ff_aig_map.at(bit)); } - if (omode && output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -716,18 +708,15 @@ struct XAigerWriter #endif h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -859,8 +848,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/); f << "a"; std::string buffer_str = a_buffer.str(); @@ -879,7 +868,7 @@ struct XAigerWriter f << stringf("Generated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map, bool omode) + void write_map(std::ostream &f, bool verbose_map) { dict input_lines; dict init_lines; @@ -952,8 +941,6 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) @@ -989,19 +976,12 @@ struct XAigerBackend : public Backend { log(" -vmap \n"); log(" like -map, but more verbose\n"); log("\n"); - log(" -I, -O, -B\n"); - log(" If the design contains no input/output/assert then create one\n"); - log(" dummy input/output/bad_state pin to make the tools reading the\n"); - log(" AIGER file happy.\n"); - log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; bool zinit_mode = false; bool verbose_map = false; - bool imode = false; - bool omode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1026,14 +1006,6 @@ struct XAigerBackend : public Backend { verbose_map = true; continue; } - if (args[argidx] == "-I") { - imode = true; - continue; - } - if (args[argidx] == "-O") { - omode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1043,15 +1015,15 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode); - writer.write_aiger(*f, ascii_mode, omode); + XAigerWriter writer(top_module, zinit_mode); + writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { std::ofstream mapf; mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf, verbose_map, omode); + writer.write_map(mapf, verbose_map); } } } XAigerBackend; -- cgit v1.2.3 From 2e7b3eee400a4d845398be8e15ca023672f05270 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:43:43 -0700 Subject: Add a couple more tests --- backends/aiger/xaiger.cc | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index af9a30135..3dbff5496 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,14 +142,6 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire == nullptr) { - if (wire->port_output) { - aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); - } - continue; - } - undriven_bits.insert(bit); unused_bits.insert(bit); @@ -160,8 +152,10 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) + if (bit != wirebit) { alias_map[wirebit] = bit; + undriven_bits.insert(wirebit); + } output_bits.insert(wirebit); } } @@ -169,7 +163,6 @@ struct XAigerWriter for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); - for (auto bit : output_bits) if (!bit.wire->port_input) unused_bits.erase(bit); @@ -178,8 +171,7 @@ struct XAigerWriter TopoSort toposort; bool abc_box_seen = false; - for (auto cell : module->cells()) - { + for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); bool builtin_type = yosys_celltypes.cell_known(cell->type); bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); @@ -296,14 +288,15 @@ struct XAigerWriter else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - if (!w->port_input) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + + if (is_input) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (!w->port_output) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; @@ -311,7 +304,11 @@ struct XAigerWriter unused_bits.erase(b); } } - if (is_output) { + } + if (is_output) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; input_bits.insert(b); SigBit O = sigmap(b); if (O != b) -- cgit v1.2.3 From fb2758aade4561d8c379e8b9d97ee871b1bbfde3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:44:30 -0700 Subject: write_xaiger to preserve POs even if driven by constant --- backends/aiger/xaiger.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3dbff5496..3a4b353e2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,8 +142,10 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - undriven_bits.insert(bit); - unused_bits.insert(bit); + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); + } if (wire->port_input || keep) { if (bit != wirebit) @@ -154,7 +156,8 @@ struct XAigerWriter if (wire->port_output || keep) { if (bit != wirebit) { alias_map[wirebit] = bit; - undriven_bits.insert(wirebit); + if (!bit.wire) + undriven_bits.insert(wirebit); } output_bits.insert(wirebit); } @@ -480,10 +483,6 @@ struct XAigerWriter } } - // Erase all POs that are undriven - if (!holes_mode) - for (auto bit : undriven_bits) - output_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 8374eb1cb4dcb99b2125543a3d5f9f6adbdd6b7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:55:02 -0700 Subject: Remove unnecessary undriven_bits.insert --- backends/aiger/xaiger.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3a4b353e2..fcf9a7bf1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -154,11 +154,8 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) { + if (bit != wirebit) alias_map[wirebit] = bit; - if (!bit.wire) - undriven_bits.insert(wirebit); - } output_bits.insert(wirebit); } } -- cgit v1.2.3 From 95665730540c0fd7c76690f28d0fd6b5f13f2223 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 14 Jun 2019 12:02:12 +0100 Subject: ecp5: Add abc9 option Signed-off-by: David Shah --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5fa20c9c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -833,8 +833,7 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - //Pass::call(holes_module->design, "techmap"); - + Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); Pass::call(holes_module->design, "clean -purge"); -- cgit v1.2.3 From 1948e7c846ea318d003148974945d917701a4452 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:13:17 -0700 Subject: Cleanup/optimise toposort in write_xaiger --- backends/aiger/xaiger.cc | 101 ++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 54 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5a26548b8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -167,51 +167,12 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - dict> bit_drivers, bit_users; - TopoSort toposort; + SigMap topomap; + topomap.database = sigmap.database; + bool abc_box_seen = false; for (auto cell : module->cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - bool builtin_type = yosys_celltypes.cell_known(cell->type); - bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); - - if (!holes_mode) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (!builtin_type && !abc_type) - continue; - - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (builtin_type) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") - continue; - } - - if (inst_module) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - - if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) - continue; - } - } - - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -219,6 +180,8 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; + if (!holes_mode) + topomap.add(Y, A); continue; } @@ -241,6 +204,10 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); + if (!holes_mode) { + topomap.add(Y, A); + topomap.add(Y, B); + } continue; } @@ -252,6 +219,7 @@ struct XAigerWriter // continue; //} + RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; @@ -322,20 +290,46 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen) { + if (abc_box_seen && !holes_mode) { + TopoSort toposort; + dict> bit_drivers, bit_users; + + for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) + continue; + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : topomap(conn.second)) + if (bit.wire) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + for (auto bit : topomap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } + } + for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - -#if 0 +#if 1 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 0 +#if 1 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -346,13 +340,14 @@ struct XAigerWriter #endif log_assert(no_loops); + pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc_box_id")) - continue; + log_assert(box_module); + log_assert(box_module->attributes.count("\\abc_box_id")); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -448,8 +443,6 @@ struct XAigerWriter } box_list.emplace_back(cell); } - - // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { -- cgit v1.2.3 From 1656c44373dbf7375c068d5626e38a76b5a83c4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:29:27 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bba0ec713..daefd3a73 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,7 +20,6 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" #include "kernel/utils.h" USING_YOSYS_NAMESPACE -- cgit v1.2.3 From ee428f73abdbbde95601e583db186d86a8fa6b91 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:37:52 -0700 Subject: Remove WIP ABC9 flop support --- backends/aiger/xaiger.cc | 66 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index daefd3a73..1e70f3230 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -219,37 +219,37 @@ struct XAigerWriter //} RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - RTLIL::Wire* port = inst_module->wire(c.first); - for (auto b : c.second.bits()) { - if (is_input && port->attributes.count("\\abc_flop_d")) { - d = b; - SigBit I = sigmap(d); - if (I != d) - alias_map[I] = d; - unused_bits.erase(d); - } - if (is_output && port->attributes.count("\\abc_flop_q")) { - q = b; - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - - ff_bits.emplace_back(d, q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + //if (inst_flop) { + // SigBit d, q; + // for (const auto &c : cell->connections()) { + // auto is_input = cell->input(c.first); + // auto is_output = cell->output(c.first); + // log_assert(is_input || is_output); + // RTLIL::Wire* port = inst_module->wire(c.first); + // for (auto b : c.second.bits()) { + // if (is_input && port->attributes.count("\\abc_flop_d")) { + // d = b; + // SigBit I = sigmap(d); + // if (I != d) + // alias_map[I] = d; + // unused_bits.erase(d); + // } + // if (is_output && port->attributes.count("\\abc_flop_q")) { + // q = b; + // SigBit O = sigmap(q); + // if (O != q) + // alias_map[O] = q; + // undriven_bits.erase(O); + // } + // } + // } + // if (!abc_box_seen) + // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + // ff_bits.emplace_back(d, q); + //} + /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -310,8 +310,8 @@ struct XAigerWriter if (cell->output(conn.first)) { RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + //if (inst_module_port->attributes.count("\\abc_flop_q")) + // continue; for (auto bit : topomap(conn.second)) bit_drivers[bit].insert(cell->name); } -- cgit v1.2.3 From 97d265637505a239e3d328a3ee7e26c6fd5d6744 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:00:02 -0700 Subject: Resolve comments from @daveshah1 --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1e70f3230..42a2233e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -683,16 +683,18 @@ struct XAigerWriter f << "c"; if (!box_list.empty() || !ff_bits.empty()) { - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { + auto write_buffer = [](std::stringstream &buffer, int i32) { // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int32_t i32_be = _byteswap_ulong(i32); #else - int i32_be = __builtin_bswap32(i32); + int32_t i32_be = __builtin_bswap32(i32); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); @@ -782,15 +784,7 @@ struct XAigerWriter /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; -- cgit v1.2.3 From a48b5bfaa5c55bfe4e5ff859b453ee00a1dd68c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:25:06 -0700 Subject: Further cleanup based on @daveshah1 --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42a2233e4..7e22dca7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,20 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +inline int32_t to_big_endian(int32_t i32) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#ifdef _WIN32 + return _byteswap_ulong(i32); +#else + return __builtin_bswap32(i32); +#endif +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return i32; +#else +#error "Unknown endianness" +#endif +} + void aiger_encode(std::ostream &f, int x) { log_assert(x >= 0); @@ -684,12 +698,7 @@ struct XAigerWriter if (!box_list.empty() || !ff_bits.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int32_t i32_be = _byteswap_ulong(i32); -#else - int32_t i32_be = __builtin_bswap32(i32); -#endif + int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; @@ -773,12 +782,7 @@ struct XAigerWriter f << "h"; std::string buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); @@ -787,18 +791,13 @@ struct XAigerWriter auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); + //int mergeability_class = 1; + //for (auto cell : ff_bits) + // write_r_buffer(mergeability_class++); f << "r"; std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); } @@ -831,12 +830,7 @@ struct XAigerWriter f << "a"; std::string buffer_str = a_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); -- cgit v1.2.3 From 7876b5b8bef1ff8460e48232e68bb5136f04e7b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:40:51 -0700 Subject: Cover __APPLE__ too for little to big endian --- backends/aiger/xaiger.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e22dca7f..7cb311736 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -18,6 +18,15 @@ * */ +// https://stackoverflow.com/a/46137633 +#ifdef _MSC_VER +#include +#define __builtin_bswap32 _byteswap_ulong +#elif defined(__APPLE__) +#include +#define __builtin_bswap32 OSSwapInt32 +#endif + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/utils.h" @@ -27,11 +36,7 @@ PRIVATE_NAMESPACE_BEGIN inline int32_t to_big_endian(int32_t i32) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#ifdef _WIN32 - return _byteswap_ulong(i32); -#else return __builtin_bswap32(i32); -#endif #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return i32; #else -- cgit v1.2.3 From 2d85725604271c658382e8fdd8ff28275fb94b03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:07:56 -0700 Subject: Get rid of compiler warnings --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cb311736..3f7edc627 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -190,7 +190,7 @@ struct XAigerWriter bool abc_box_seen = false; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -312,7 +312,7 @@ struct XAigerWriter TopoSort toposort; dict> bit_drivers, bit_users; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) continue; -- cgit v1.2.3 From 0fa6a441f1a222b039975cf622ddca479a65cf24 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:08:38 -0700 Subject: Check that whiteboxes are synthesisable --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3f7edc627..bc722e492 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -722,7 +722,7 @@ struct XAigerWriter write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; - holes_module = module->design->addModule("\\__holes__"); + holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); int port_id = 1; @@ -822,17 +822,21 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap all lib_whitebox-es once + // TODO: Should techmap/AIG all lib_whitebox-es once Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - holes_module->design->selection_stack.pop_back(); + Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); + holes_module->design->selection_stack.pop_back(); + f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); -- cgit v1.2.3 From 746f70a9ce163f921b0e55b21042c59769bbcba9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:10:46 -0700 Subject: Update comment --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bc722e492..0c2ae62e6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -822,7 +822,8 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/AIG all lib_whitebox-es once + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) -- cgit v1.2.3 From 9b55e69755a00a46c97104f344c0ee7065a8f13c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: Revert "Cleanup/optimise toposort in write_xaiger" This reverts commit 1948e7c846ea318d003148974945d917701a4452. Restores old toposort with optimisations --- backends/aiger/xaiger.cc | 84 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0c2ae62e6..1d502a748 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,9 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - SigMap topomap; - topomap.database = sigmap.database; - + dict> bit_drivers, bit_users; + TopoSort toposort; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -198,8 +197,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) - topomap.add(Y, A); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -223,12 +225,16 @@ struct XAigerWriter undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); if (!holes_mode) { - topomap.add(Y, A); - topomap.add(Y, B); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); } continue; } + log_assert(!holes_mode); + //if (cell->type == "$initstate") //{ // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); @@ -265,11 +271,26 @@ struct XAigerWriter // } // if (!abc_box_seen) // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); //} /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; + + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } } else { for (const auto &c : cell->connections()) { @@ -309,45 +330,19 @@ struct XAigerWriter } if (abc_box_seen && !holes_mode) { - TopoSort toposort; - dict> bit_drivers, bit_users; - - for (auto cell : module->selected_cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) - continue; - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : topomap(conn.second)) - if (bit.wire) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - //if (inst_module_port->attributes.count("\\abc_flop_q")) - // continue; - for (auto bit : topomap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + pool abc_carry_modules; -#if 1 +#if 0 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 1 +#if 0 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -358,14 +353,13 @@ struct XAigerWriter #endif log_assert(no_loops); - pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - log_assert(box_module); - log_assert(box_module->attributes.count("\\abc_box_id")); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; - if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -461,6 +455,8 @@ struct XAigerWriter } box_list.emplace_back(cell); } + + // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { -- cgit v1.2.3 From 46e69ee934a6a954b73bb7a5669b6ee6d3047247 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:31:18 -0700 Subject: Remove redundant condition --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1d502a748..4d8bb7f00 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -329,7 +329,7 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen && !holes_mode) { + if (abc_box_seen) { for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) -- cgit v1.2.3 From 7ff8330d1e159173f9ed3494b85b83cb97208ab5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:34:40 -0700 Subject: Leave breadcrumb behind --- backends/aiger/xaiger.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d8bb7f00..df970e341 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,6 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + // TODO: Speed up toposort -- ultimately we care about + // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; bool abc_box_seen = false; -- cgit v1.2.3 From 357d36ef4fcc63db8c14b86dbeb10059030cc602 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 09:07:03 -0700 Subject: write_xaiger to treat abc_flop boxes as boxff for ABC --- backends/aiger/xaiger.cc | 227 ++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 122 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index df970e341..4810e0113 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -66,7 +66,6 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - //pool initstate_bits; vector> ci_bits; vector> co_bits; vector> ff_bits; @@ -97,10 +96,6 @@ struct XAigerWriter { aig_map[bit] = -1; - //if (initstate_bits.count(bit)) { - // log_assert(initstate_ff > 0); - // aig_map[bit] = initstate_ff; - //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -207,16 +202,6 @@ struct XAigerWriter continue; } - //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - //{ - // SigBit D = sigmap(cell->getPort("\\D").as_bit()); - // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - // unused_bits.erase(D); - // undriven_bits.erase(Q); - // ff_map[Q] = D; - // continue; - //} - if (cell->type == "$_AND_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -237,61 +222,62 @@ struct XAigerWriter log_assert(!holes_mode); - //if (cell->type == "$initstate") + // FIXME: Should short here, rather than provide $_DFF_[NP]_ + // to ABC as a user cell + //if (cell->type.in(/*"$_FF_",*/ "$_DFF_N_", "$_DFF_P_")) //{ - // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - // undriven_bits.erase(Y); - // initstate_bits.insert(Y); + // SigBit D = sigmap(cell->getPort("\\D").as_bit()); + // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + // alias_map[Q] = D; // continue; //} - RTLIL::Module* inst_module = module->design->module(cell->type); - //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - //if (inst_flop) { - // SigBit d, q; - // for (const auto &c : cell->connections()) { - // auto is_input = cell->input(c.first); - // auto is_output = cell->output(c.first); - // log_assert(is_input || is_output); - // RTLIL::Wire* port = inst_module->wire(c.first); - // for (auto b : c.second.bits()) { - // if (is_input && port->attributes.count("\\abc_flop_d")) { - // d = b; - // SigBit I = sigmap(d); - // if (I != d) - // alias_map[I] = d; - // unused_bits.erase(d); - // } - // if (is_output && port->attributes.count("\\abc_flop_q")) { - // q = b; - // SigBit O = sigmap(q); - // if (O != q) - // alias_map[O] = q; - // undriven_bits.erase(O); - // } - // } - // } - // if (!abc_box_seen) - // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); - //} - /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { - abc_box_seen = true; + RTLIL::Module* inst_module = !holes_mode ? module->design->module(cell->type) : nullptr; + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + if (inst_flop) { + toposort.node(cell->name); - if (!holes_mode) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } + SigBit d, q; + for (const auto &c : cell->connections()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + RTLIL::Wire* port = inst_module->wire(c.first); + if (is_input && port->attributes.count("\\abc_flop_d")) { + d = c.second; + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); + } + if (is_output && port->attributes.count("\\abc_flop_q")) { + q = c.second; + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); + } + } + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + } + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + abc_box_seen = true; - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } } else { @@ -555,17 +541,17 @@ struct XAigerWriter // } //} - for (auto it : ff_map) { - aig_m++, aig_l++; - aig_map[it.first] = 2*aig_m; - ordered_latches[it.first] = aig_l-1; - if (init_map.count(it.first) == 0) - aig_latchinit.push_back(2); - else - aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - } + //for (auto it : ff_map) { + // aig_m++, aig_l++; + // aig_map[it.first] = 2*aig_m; + // ordered_latches[it.first] = aig_l-1; + // if (init_map.count(it.first) == 0) + // aig_latchinit.push_back(2); + // else + // aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); + //} - //if (!initstate_bits.empty() || !init_inputs.empty()) { + //if (!init_inputs.empty()) { // aig_m++, aig_l++; // initstate_ff = 2*aig_m+1; // aig_latchinit.push_back(0); @@ -589,16 +575,16 @@ struct XAigerWriter // } //} - for (auto it : ff_map) { - int a = bit2aig(it.second); - int l = ordered_latches[it.first]; - if (zinit_mode && aig_latchinit.at(l) == 1) - aig_latchin.push_back(a ^ 1); - else - aig_latchin.push_back(a); - } + //for (auto it : ff_map) { + // int a = bit2aig(it.second); + // int l = ordered_latches[it.first]; + // if (zinit_mode && aig_latchinit.at(l) == 1) + // aig_latchin.push_back(a ^ 1); + // else + // aig_latchin.push_back(a); + //} - //if (!initstate_bits.empty() || !init_inputs.empty()) + //if (!init_inputs.empty()) // aig_latchin.push_back(1); for (auto &c : co_bits) { @@ -617,7 +603,6 @@ struct XAigerWriter RTLIL::SigBit bit = f.second; aig_outputs.push_back(ff_aig_map.at(bit)); } - } void write_aiger(std::ostream &f, bool ascii_mode) @@ -639,14 +624,14 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - } + //for (int i = 0; i < aig_l; i++) { + // if (zinit_mode || aig_latchinit.at(i) == 0) + // f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 1) + // f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 2) + // f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); + //} for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -665,14 +650,14 @@ struct XAigerWriter } else { - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d 1\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - } + //for (int i = 0; i < aig_l; i++) { + // if (zinit_mode || aig_latchinit.at(i) == 0) + // f << stringf("%d\n", aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 1) + // f << stringf("%d 1\n", aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 2) + // f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); + //} for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -789,21 +774,19 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - /*if (!ff_bits.empty())*/ { - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %zu\n", ff_bits.size()); - write_r_buffer(ff_bits.size()); - //int mergeability_class = 1; - //for (auto cell : ff_bits) - // write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + log_debug("flopNum = %zu\n", ff_bits.size()); + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + buffer_str = r_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { // NB: fixup_ports() will sort ports by name @@ -885,14 +868,14 @@ struct XAigerWriter // continue; //} - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - else - latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - continue; - } + //if (ordered_latches.count(sig[i])) { + // int l = ordered_latches.at(sig[i]); + // if (zinit_mode && (aig_latchinit.at(l) == 1)) + // latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); + // else + // latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + // continue; + //} if (verbose_map) { if (aig_map.count(sig[i]) == 0) -- cgit v1.2.3 From 6d74b3e004455a98d785bd27c4276b787af637a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 09:36:02 -0700 Subject: Update comment --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4810e0113..09f80fee8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -224,7 +224,7 @@ struct XAigerWriter // FIXME: Should short here, rather than provide $_DFF_[NP]_ // to ABC as a user cell - //if (cell->type.in(/*"$_FF_",*/ "$_DFF_N_", "$_DFF_P_")) + //if (cell->type.in("$_FF_" /*, "$_DFF_N_", "$_DFF_P_"*/)) //{ // SigBit D = sigmap(cell->getPort("\\D").as_bit()); // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); -- cgit v1.2.3 From c2f3f116d041b97b0d8b6ed28c87810bf6c2630e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 18:16:14 -0700 Subject: Use $__ABC_FF_ instead of $_FF_ --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 09f80fee8..c3a4e69c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -222,8 +222,8 @@ struct XAigerWriter log_assert(!holes_mode); - // FIXME: Should short here, rather than provide $_DFF_[NP]_ - // to ABC as a user cell + // FIXME: Should short here, rather than provide $__ABC_FF_ + // to ABC like a user cell //if (cell->type.in("$_FF_" /*, "$_DFF_N_", "$_DFF_P_"*/)) //{ // SigBit D = sigmap(cell->getPort("\\D").as_bit()); -- cgit v1.2.3 From 0debea25a731d83449b08152c7c6158e37e63d75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 18:24:04 -0700 Subject: Update comment --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c3a4e69c2..ce2f6e571 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -224,7 +224,7 @@ struct XAigerWriter // FIXME: Should short here, rather than provide $__ABC_FF_ // to ABC like a user cell - //if (cell->type.in("$_FF_" /*, "$_DFF_N_", "$_DFF_P_"*/)) + //if (cell->type == "$__ABC_FF_") //{ // SigBit D = sigmap(cell->getPort("\\D").as_bit()); // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); -- cgit v1.2.3 From 2309459605b262040f7bea84e6d935d2838686d5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 19:36:55 -0700 Subject: Do not treat $__ABC_FF_ as a user cell --- backends/aiger/xaiger.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce2f6e571..923ba3da8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -222,15 +222,15 @@ struct XAigerWriter log_assert(!holes_mode); - // FIXME: Should short here, rather than provide $__ABC_FF_ - // to ABC like a user cell - //if (cell->type == "$__ABC_FF_") - //{ - // SigBit D = sigmap(cell->getPort("\\D").as_bit()); - // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - // alias_map[Q] = D; - // continue; - //} + if (cell->type == "$__ABC_FF_") + { + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + unused_bits.erase(D); + undriven_bits.erase(Q); + alias_map[Q] = D; + continue; + } RTLIL::Module* inst_module = !holes_mode ? module->design->module(cell->type) : nullptr; bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; -- cgit v1.2.3 From bd2690e9b940c055a4aa3443e7f1435d66d875f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 22:41:13 -0700 Subject: Preserve init of flops, and write into XAIG --- backends/aiger/xaiger.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 923ba3da8..8210d013e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -258,8 +258,8 @@ struct XAigerWriter undriven_bits.erase(O); } } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + log_assert(inst_module->attributes.count("\\abc_box_id")); + abc_box_seen = true; ff_bits.emplace_back(d, q); } @@ -696,7 +696,7 @@ struct XAigerWriter log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size() + co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); @@ -780,7 +780,7 @@ struct XAigerWriter write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); + write_r_buffer(mergeability_class); f << "r"; buffer_str = r_buffer.str(); @@ -788,6 +788,27 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + std::stringstream s_buffer; + auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); + write_s_buffer(ff_bits.size()); + for (auto &f : ff_bits) { + RTLIL::SigBit q = f.second; + auto it = q.wire->attributes.find("\\init"); + if (it != q.wire->attributes.end()) { + auto init = it->second[q.offset]; + if (init == RTLIL::S1) { + write_s_buffer(1); + continue; + } + } + write_s_buffer(0); + } + f << "s"; + buffer_str = s_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + if (holes_module) { // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); @@ -857,7 +878,11 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); + int init = 2; + auto it = init_map.find(b); + if (it != init_map.end()) + init = it->second ? 1 : 0; + output_lines[o] += stringf("output %lu %d %s %d\n", o - co_bits.size(), i, log_id(wire), init); continue; } -- cgit v1.2.3 From 6852c83bbe5c1c862527b78910e7d29dc73a6ee5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 22:50:15 -0700 Subject: Cleanup write_xaiger --- backends/aiger/xaiger.cc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8210d013e..dbf9b9750 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -68,7 +68,7 @@ struct XAigerWriter dict> and_map; vector> ci_bits; vector> co_bits; - vector> ff_bits; + vector ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -237,31 +237,29 @@ struct XAigerWriter if (inst_flop) { toposort.node(cell->name); - SigBit d, q; for (const auto &c : cell->connections()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); RTLIL::Wire* port = inst_module->wire(c.first); if (is_input && port->attributes.count("\\abc_flop_d")) { - d = c.second; + SigBit d = c.second; SigBit I = sigmap(d); if (I != d) alias_map[I] = d; unused_bits.erase(d); } if (is_output && port->attributes.count("\\abc_flop_q")) { - q = c.second; + SigBit q = c.second; SigBit O = sigmap(q); if (O != q) alias_map[O] = q; undriven_bits.erase(O); + ff_bits.emplace_back(q); } } log_assert(inst_module->attributes.count("\\abc_box_id")); abc_box_seen = true; - - ff_bits.emplace_back(d, q); } else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; @@ -515,8 +513,7 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - RTLIL::SigBit bit = f.second; + for (auto bit : ff_bits) { aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; @@ -598,9 +595,8 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto &f : ff_bits) { + for (auto bit : ff_bits) { aig_o++; - RTLIL::SigBit bit = f.second; aig_outputs.push_back(ff_aig_map.at(bit)); } } @@ -791,11 +787,10 @@ struct XAigerWriter std::stringstream s_buffer; auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); write_s_buffer(ff_bits.size()); - for (auto &f : ff_bits) { - RTLIL::SigBit q = f.second; - auto it = q.wire->attributes.find("\\init"); - if (it != q.wire->attributes.end()) { - auto init = it->second[q.offset]; + for (auto bit : ff_bits) { + auto it = bit.wire->attributes.find("\\init"); + if (it != bit.wire->attributes.end()) { + auto init = it->second[bit.offset]; if (init == RTLIL::S1) { write_s_buffer(1); continue; -- cgit v1.2.3 From fb90d8c18c9e8bfad1356e3b4387d77eeb2e9377 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 09:34:26 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 253 +++++------------------------------------------ 1 file changed, 25 insertions(+), 228 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index df970e341..1485e2b0c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -59,31 +59,23 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; - bool zinit_mode; SigMap sigmap; - dict init_map; pool input_bits, output_bits; - dict not_map, ff_map, alias_map; + dict not_map, alias_map; dict> and_map; - //pool initstate_bits; vector> ci_bits; vector> co_bits; - vector> ff_bits; vector> aig_gates; - vector aig_latchin, aig_latchinit, aig_outputs; + vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; dict ordered_outputs; - dict ordered_latches; vector box_list; - //dict init_inputs; - //int initstate_ff = 0; - int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -97,10 +89,6 @@ struct XAigerWriter { aig_map[bit] = -1; - //if (initstate_bits.count(bit)) { - // log_assert(initstate_ff > 0); - // aig_map[bit] = initstate_ff; - //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -123,7 +111,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -145,14 +133,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) - if (initval[i] == State::S0 || initval[i] == State::S1) - init_map[initsig[i]] = initval[i] == State::S1; - } - bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -207,16 +187,6 @@ struct XAigerWriter continue; } - //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - //{ - // SigBit D = sigmap(cell->getPort("\\D").as_bit()); - // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - // unused_bits.erase(D); - // undriven_bits.erase(Q); - // ff_map[Q] = D; - // continue; - //} - if (cell->type == "$_AND_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -237,45 +207,8 @@ struct XAigerWriter log_assert(!holes_mode); - //if (cell->type == "$initstate") - //{ - // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - // undriven_bits.erase(Y); - // initstate_bits.insert(Y); - // continue; - //} - RTLIL::Module* inst_module = module->design->module(cell->type); - //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - //if (inst_flop) { - // SigBit d, q; - // for (const auto &c : cell->connections()) { - // auto is_input = cell->input(c.first); - // auto is_output = cell->output(c.first); - // log_assert(is_input || is_output); - // RTLIL::Wire* port = inst_module->wire(c.first); - // for (auto b : c.second.bits()) { - // if (is_input && port->attributes.count("\\abc_flop_d")) { - // d = b; - // SigBit I = sigmap(d); - // if (I != d) - // alias_map[I] = d; - // unused_bits.erase(d); - // } - // if (is_output && port->attributes.count("\\abc_flop_q")) { - // q = b; - // SigBit O = sigmap(q); - // if (O != q) - // alias_map[O] = q; - // undriven_bits.erase(O); - // } - // } - // } - // if (!abc_box_seen) - // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); - //} - /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -501,7 +434,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -517,7 +449,6 @@ struct XAigerWriter } not_map.sort(); - ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -529,78 +460,12 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - RTLIL::SigBit bit = f.second; - aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; - } - - //if (zinit_mode) - //{ - // for (auto it : ff_map) { - // if (init_map.count(it.first)) - // continue; - // aig_m++, aig_i++; - // init_inputs[it.first] = 2*aig_m; - // } - //} - - for (auto it : ff_map) { - aig_m++, aig_l++; - aig_map[it.first] = 2*aig_m; - ordered_latches[it.first] = aig_l-1; - if (init_map.count(it.first) == 0) - aig_latchinit.push_back(2); - else - aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - } - - //if (!initstate_bits.empty() || !init_inputs.empty()) { - // aig_m++, aig_l++; - // initstate_ff = 2*aig_m+1; - // aig_latchinit.push_back(0); - //} - - //if (zinit_mode) - //{ - // for (auto it : ff_map) - // { - // int l = ordered_latches[it.first]; - - // if (aig_latchinit.at(l) == 1) - // aig_map[it.first] ^= 1; - - // if (aig_latchinit.at(l) == 2) - // { - // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - // } - // } - //} - - for (auto it : ff_map) { - int a = bit2aig(it.second); - int l = ordered_latches[it.first]; - if (zinit_mode && aig_latchinit.at(l) == 1) - aig_latchin.push_back(a ^ 1); - else - aig_latchin.push_back(a); + aig_map[bit] = 2*aig_m; } - //if (!initstate_bits.empty() || !init_inputs.empty()) - // aig_latchin.push_back(1); - for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -611,13 +476,6 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - - for (auto &f : ff_bits) { - aig_o++; - RTLIL::SigBit bit = f.second; - aig_outputs.push_back(ff_aig_map.at(bit)); - } - } void write_aiger(std::ostream &f, bool ascii_mode) @@ -627,8 +485,6 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); - log_assert(aig_l == GetSize(aig_latchin)); - log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -639,15 +495,6 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -665,15 +512,6 @@ struct XAigerWriter } else { - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d 1\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -699,7 +537,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -708,14 +546,14 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); - write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); + write_h_buffer(input_bits.size()); + log_debug("poNum = %zu\n", output_bits.size()); + write_h_buffer(output_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -789,21 +627,15 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - /*if (!ff_bits.empty())*/ { - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %zu\n", ff_bits.size()); - write_r_buffer(ff_bits.size()); - //int mergeability_class = 1; - //for (auto cell : ff_bits) - // write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + write_r_buffer(0); + + f << "r"; + buffer_str = r_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { // NB: fixup_ports() will sort ports by name @@ -831,7 +663,7 @@ struct XAigerWriter Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); holes_module->design->selection_stack.pop_back(); @@ -851,9 +683,7 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; - dict init_lines; dict output_lines; - dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -878,22 +708,6 @@ struct XAigerWriter continue; } - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - // continue; - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - else - latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - continue; - } - if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; @@ -909,10 +723,6 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); - init_lines.sort(); - for (auto &it : init_lines) - f << it.second; - int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); @@ -922,10 +732,6 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size()); - latch_lines.sort(); - for (auto &it : latch_lines) - f << it.second; - wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -946,10 +752,6 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); - log(" -zinit\n"); - log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); - log(" uninitialized FFs.\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -960,7 +762,6 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -973,10 +774,6 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } - if (args[argidx] == "-zinit") { - zinit_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -995,7 +792,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From 0c59bc0b75ba2985e6ae0806d410fe2fa1c94e37 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 10:42:00 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 69 +++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 39 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dbf9b9750..87dca014d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -233,49 +233,40 @@ struct XAigerWriter } RTLIL::Module* inst_module = !holes_mode ? module->design->module(cell->type) : nullptr; - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (inst_flop) { - toposort.node(cell->name); - - for (const auto &c : cell->connections()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - RTLIL::Wire* port = inst_module->wire(c.first); - if (is_input && port->attributes.count("\\abc_flop_d")) { - SigBit d = c.second; - SigBit I = sigmap(d); - if (I != d) - alias_map[I] = d; - unused_bits.erase(d); - } - if (is_output && port->attributes.count("\\abc_flop_q")) { - SigBit q = c.second; - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - ff_bits.emplace_back(q); - } - } - log_assert(inst_module->attributes.count("\\abc_box_id")); - abc_box_seen = true; - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } + auto abc_flop_d = inst_module->attributes.at("\\abc_flop_d", RTLIL::Const()); + if (abc_flop_d.size() == 0) { + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } + else { + auto abc_flop_q = inst_module->attributes.at("\\abc_flop_q"); + + SigBit d = cell->getPort(RTLIL::escape_id(abc_flop_d.decode_string())); + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); + + SigBit q = cell->getPort(RTLIL::escape_id(abc_flop_q.decode_string())); + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); + ff_bits.emplace_back(q); } } else { -- cgit v1.2.3 From c23bbc429103ca84cb8a9cfb674aacf7d14109c6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 16 Jun 2019 23:12:03 +0200 Subject: Add timescale and generated-by header to yosys-smtbmc MkVcd Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ab20a4af2..cea0fc56c 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1023,6 +1023,8 @@ class MkVcd: assert t >= self.t if t != self.t: if self.t == -1: + print("$version Generated by Yosys-SMTBMC $end", file=self.f) + print("$timescale 1ns $end", file=self.f) print("$var integer 32 t smt_step $end", file=self.f) print("$var event 1 ! smt_clock $end", file=self.f) -- cgit v1.2.3 From 4a18e19fb86f5729ca764d5b0ee338f558f90a43 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 17 Jun 2019 14:45:48 -0700 Subject: Support filename rewrite in backends Signed-off-by: Ben Widawsky --- backends/aiger/aiger.cc | 1 + backends/ilang/ilang_backend.cc | 1 + backends/json/json.cc | 1 + backends/protobuf/protobuf.cc | 1 + 4 files changed, 4 insertions(+) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index dfe506c66..d685c5638 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -776,6 +776,7 @@ struct AigerBackend : public Backend { writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { + rewrite_filename(filename); std::ofstream mapf; mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 04d1ee311..b4ba2b03f 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -483,6 +483,7 @@ struct DumpPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc); if (ff->fail()) { diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..5022d5da1 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -525,6 +525,7 @@ struct JsonPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), std::ofstream::trunc); if (ff->fail()) { diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index 549fc73ae..fff110bb0 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -336,6 +336,7 @@ struct ProtobufPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), std::ofstream::trunc); if (ff->fail()) { -- cgit v1.2.3 From f2d541962e92fedce0fbb34d4cf5c1985c7cda40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: write_xaiger to skip POs driven by 1'bx --- backends/aiger/xaiger.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1485e2b0c..12b23cfe9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,9 +152,13 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (bit != RTLIL::Sx) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + else + log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); } } } -- cgit v1.2.3 From 4e5836a5fb009751a6f3bd7ec3eba20e223861f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:47:20 -0700 Subject: Handle COs driven by 1'bx --- backends/aiger/xaiger.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 12b23cfe9..42f54209b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -355,10 +355,16 @@ struct XAigerWriter } int offset = 0; - for (const auto &b : rhs.bits()) { + for (auto b : rhs.bits()) { SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (b == RTLIL::Sx) + b = RTLIL::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = RTLIL::S0; + else + alias_map[b] = I; + } co_bits.emplace_back(b, cell, port_name, offset++, 0); unused_bits.erase(b); } -- cgit v1.2.3 From 9faeba7a66c34d57bcae6ad83580e640ee5907e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:27:00 -0700 Subject: Fix broken abc9.v test due to inout being 1'bx --- backends/aiger/xaiger.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42f54209b..f0a9ccdb9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -75,6 +75,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + bool omode = false; int mkgate(int a0, int a1) { @@ -409,9 +410,9 @@ struct XAigerWriter // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(input_bits.count(bit) && output_bits.count(bit)); + log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) @@ -486,6 +487,12 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } + + if (output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + omode = true; + } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -741,6 +748,8 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + if (omode && output_bits.empty()) + f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From ad36eb24c05b578ec8610c9f199280aacefebe54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:31:22 -0700 Subject: Fix different abc9 test --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f0a9ccdb9..55a95d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -406,13 +406,14 @@ struct XAigerWriter } for (auto bit : input_bits) { + if (!output_bits.count(bit)) + continue; RTLIL::Wire *wire = bit.wire; // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) -- cgit v1.2.3 From 8e56cfb6bbaa4e61b201c123b04a4eb4ca3403cf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:40:17 -0700 Subject: write_xaiger to flatten 1'bx/1'bz to 1'b0 again --- backends/aiger/xaiger.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 55a95d835..82f0f24b2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,8 +104,10 @@ struct XAigerWriter aig_map[bit] = bit2aig(alias_map.at(bit)); } - if (bit == State::Sx || bit == State::Sz) - log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + aig_map[bit] = 0; + } } log_assert(aig_map.at(bit) >= 0); -- cgit v1.2.3 From c4ea6fff65d6b2e69a31649af7e10b129c6ae0f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: Fix gcc invalidation behaviour for write_aiger --- backends/aiger/aiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index d685c5638..6863b40fa 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -89,7 +89,8 @@ struct AigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) -- cgit v1.2.3 From 32f8014e121cd3338d6786269455c8b3fe9f1631 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:55:08 -0700 Subject: Fix gcc error, due to dict invalidation during recursion --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 82f0f24b2..32c3f9045 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -101,12 +101,13 @@ struct XAigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) { log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = 0; + aig_map[bit] = aig_map.at(State::S0); } } -- cgit v1.2.3 From 4422b7311b8d672df386f993b413d32baad8550b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: Fix gcc invalidation behaviour for write_aiger --- backends/aiger/aiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 4c2ea511a..4fb47f0d6 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -89,7 +89,8 @@ struct AigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) -- cgit v1.2.3 From e21f01d9380607ba0fb10466273d2dfc3d806282 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:09:13 -0700 Subject: Refactor bit2aig for less lookups --- backends/aiger/xaiger.cc | 51 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32c3f9045..48e902666 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,33 +86,36 @@ struct XAigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; + } - if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = aig_map.at(State::S0); - } + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + a = aig_map.at(State::S0); } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + log_assert(a >= 0); + aig_map[bit] = a; + return a; } XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) -- cgit v1.2.3 From 6a336ca23ef5d98b3d68dac2f05de49360237149 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:29:40 -0700 Subject: Fix spacing --- backends/aiger/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 4fb47f0d6..2815abda8 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -89,7 +89,7 @@ struct AigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); aig_map[bit] = a; } -- cgit v1.2.3 From f15def325c7f2621cf8299ca61b5eeb3ddd3667e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 21 Jun 2019 15:22:17 +0200 Subject: Added JSON upto and offset Signed-off-by: Clifford Wolf --- backends/json/json.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index 5022d5da1..1781a28cd 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -189,6 +189,10 @@ struct JsonWriter f << stringf(" %s: {\n", get_name(w->name).c_str()); f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + if (w->start_offset) + f << stringf(" \"offset\": %d,\n", w->start_offset); + if (w->upto) + f << stringf(" \"upto\": 1,\n"); f << stringf(" \"attributes\": {"); write_parameters(w->attributes); f << stringf("\n }\n"); -- cgit v1.2.3 From 50e72210772f3a1c34f5fe80b19c65f6d304b71a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 19:47:25 +0200 Subject: Add upto and offset to JSON ports --- backends/json/json.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index 1781a28cd..eb59e5eba 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -127,6 +127,10 @@ struct JsonWriter f << stringf(" %s: {\n", get_name(n).c_str()); f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output"); f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); + if (w->start_offset) + f << stringf(" \"offset\": %d,\n", w->start_offset); + if (w->upto) + f << stringf(" \"upto\": 1,\n"); f << stringf(" }"); first = false; } -- cgit v1.2.3 From fde90f7f8eb4150c7f806ab4baa53057a56bc160 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 20:01:40 +0200 Subject: Fix json formatting --- backends/json/json.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index eb59e5eba..dda4dfedd 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -126,11 +126,11 @@ struct JsonWriter f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(n).c_str()); f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output"); - f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); if (w->start_offset) f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); + f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); f << stringf(" }"); first = false; } -- cgit v1.2.3 From 70c93ea0c4ce023d61553df11198aa0b7e518455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: Move comment --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 48e902666..aa10aa55e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,14 +86,15 @@ struct XAigerWriter int bit2aig(SigBit bit) { - // NB: Cannot use iterator returned from aig_map.insert() - // since this function is called recursively auto it = aig_map.find(bit); if (it != aig_map.end()) { log_assert(it->second >= 0); return it->second; } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + int a = -1; if (not_map.count(bit)) { a = bit2aig(not_map.at(bit)) ^ 1; -- cgit v1.2.3 From bd7ec673dd5b542031698074e1043dcc32af2168 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:46:55 -0700 Subject: No point logging constant bit --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index aa10aa55e..6718e4f2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -110,7 +110,7 @@ struct XAigerWriter } if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n"); a = aig_map.at(State::S0); } -- cgit v1.2.3 From 65c1199acd52f90de86106652dbbca86d4ac5ebc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: One more workaround for gcc-4.8 --- backends/aiger/xaiger.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6718e4f2c..637c54ff9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -429,12 +429,13 @@ struct XAigerWriter module->connect(new_bit, bit); if (not_map.count(bit)) not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); + else if (and_map.count(bit)) { + //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 + and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + } else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else - //log_abort(); alias_map[new_bit] = bit; output_bits.erase(bit); output_bits.insert(new_bit); -- cgit v1.2.3 From 7074ec9cd5d5b5c01e3bbaa8ee45dbae1272f185 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: Add log_push()/log_pop() inside write_xaiger --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 637c54ff9..2070cae8f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -664,6 +664,8 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { + log_push(); + // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); holes_module->check(); @@ -700,6 +702,8 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); + + log_pop(); } } -- cgit v1.2.3 From fddb027cabedff92441b912a6cc472650aa9f74d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:45:51 -0700 Subject: Replace assert with error message --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2070cae8f..23132f108 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -244,7 +244,8 @@ struct XAigerWriter if (c.second.is_fully_const()) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); - log_assert(is_input || is_output); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { for (auto b : c.second.bits()) { -- cgit v1.2.3 From 7903ebe3e004c03e7870f1b21c4fb478481756eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:18:42 -0700 Subject: Carry in/out box ordering now move to end, not swap with end --- backends/aiger/xaiger.cc | 60 +++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 23132f108..7cfe8272c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -309,38 +309,46 @@ struct XAigerWriter if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - RTLIL::Wire* last_in = nullptr, *last_out = nullptr; - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); + auto &ports = box_module->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*it); log_assert(w); - if (w->port_input) { - if (w->attributes.count("\\abc_carry_in")) { - log_assert(!carry_in); - carry_in = w; - } - log_assert(!last_in || last_in->port_id < w->port_id); - last_in = w; + if (w->port_input && w->attributes.count("\\abc_carry_in")) { + if (carry_in) + log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); + carry_in = w; + it = ports.erase(it); + continue; } - if (w->port_output) { - if (w->attributes.count("\\abc_carry_out")) { - log_assert(!carry_out); - carry_out = w; - } - log_assert(!last_out || last_out->port_id < w->port_id); - last_out = w; + if (w->port_output && w->attributes.count("\\abc_carry_out")) { + if (carry_out) + log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); + carry_out = w; + it = ports.erase(it); + continue; } + ++it; } - if (carry_in) { - log_assert(last_in); - std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); - std::swap(carry_in->port_id, last_in->port_id); - } - if (carry_out) { - log_assert(last_out); - std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); - std::swap(carry_out->port_id, last_out->port_id); + if (!carry_in) + log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); + if (!carry_out) + log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); + + for (const auto port_name : ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 -- cgit v1.2.3 From 080a5ca536bcd7140ea3dc12483e49a8f076cd92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:02:38 -0700 Subject: Improve debugging message for comb loops --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cfe8272c..92df899c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -293,10 +293,12 @@ struct XAigerWriter #if 0 unsigned i = 0; for (auto &it : toposort.loops) { - log(" loop %d", i++); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); + log(" loop %d\n", i++); + for (auto cell_name : it) { + auto cell = module->cell(cell_name); + log_assert(cell); + log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); + } } #endif log_assert(no_loops); -- cgit v1.2.3 From 6c256b8cda66e2ba128d5fa3ba344fe4717711f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:20:15 -0700 Subject: Merge origin/master --- backends/btor/btor.cc | 30 +++++++++++++++++++++++++++--- backends/smt2/smtio.py | 5 ++++- 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 511a11942..a507b120b 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -17,6 +17,11 @@ * */ +// [[CITE]] Btor2 , BtorMC and Boolector 3.0 +// Aina Niemetz, Mathias Preiner, Clifford Wolf, Armin Biere +// Computer Aided Verification - 30th International Conference, CAV 2018 +// https://cs.stanford.edu/people/niemetz/publication/2018/niemetzpreinerwolfbiere-cav18/ + #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -875,9 +880,28 @@ struct BtorWorker else { if (bit_cell.count(bit) == 0) - log_error("No driver for signal bit %s.\n", log_signal(bit)); - export_cell(bit_cell.at(bit)); - log_assert(bit_nid.count(bit)); + { + SigSpec s = bit; + + while (i+GetSize(s) < GetSize(sig) && sig[i+GetSize(s)].wire != nullptr && + bit_cell.count(sig[i+GetSize(s)]) == 0) + s.append(sig[i+GetSize(s)]); + + log_warning("No driver for signal %s.\n", log_signal(s)); + + int sid = get_bv_sid(GetSize(s)); + int nid = next_nid++; + btorf("%d input %d %s\n", nid, sid); + nid_width[nid] = GetSize(s); + + i += GetSize(s)-1; + continue; + } + else + { + export_cell(bit_cell.at(bit)); + log_assert(bit_nid.count(bit)); + } } } diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index cea0fc56c..ae7968a1b 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1043,7 +1043,10 @@ class MkVcd: scope = scope[:-1] while uipath[:-1] != scope: - print("$scope module %s $end" % uipath[len(scope)], file=self.f) + scopename = uipath[len(scope)] + if scopename.startswith("$"): + scopename = "\\" + scopename + print("$scope module %s $end" % scopename, file=self.f) scope.append(uipath[len(scope)]) if path in self.clocks and self.clocks[path][1] == "event": -- cgit v1.2.3 From 9398921af1d21b47aa291d240a1f274418adcaf2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:07:14 -0700 Subject: Refactor for one "abc_carry" attribute on module --- backends/aiger/xaiger.cc | 82 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 92df899c2..ae690ec49 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -284,8 +284,6 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - #if 0 toposort.analyze_loops = true; #endif @@ -303,54 +301,54 @@ struct XAigerWriter #endif log_assert(no_loops); + pool seen_boxes; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); + log_assert(cell); + RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { - RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - auto &ports = box_module->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = box_module->wire(*it); - log_assert(w); - if (w->port_input && w->attributes.count("\\abc_carry_in")) { - if (carry_in) - log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); - carry_in = w; - it = ports.erase(it); - continue; - } - if (w->port_output && w->attributes.count("\\abc_carry_out")) { - if (carry_out) - log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); - carry_out = w; - it = ports.erase(it); - continue; + if (seen_boxes.insert(cell->type).second) { + auto it = box_module->attributes.find("\\abc_carry"); + if (it != box_module->attributes.end()) { + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + auto carry_in_out = it->second.decode_string(); + auto pos = carry_in_out.find(','); + if (pos == std::string::npos) + log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + carry_in = box_module->wire(carry_in_name); + if (!carry_in || !carry_in->port_input) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); + + auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + carry_out = box_module->wire(carry_out_name); + if (!carry_out || !carry_out->port_output) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); + + auto &ports = box_module->ports; + for (auto jt = ports.begin(); jt != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*jt); + log_assert(w); + if (w == carry_in || w == carry_out) { + jt = ports.erase(jt); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++jt; } - ++it; - } - - if (!carry_in) - log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); - if (!carry_out) - log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); - - for (const auto port_name : ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 -- cgit v1.2.3 From 36e2eb06bb63714d852b758062471222022930c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:51:43 -0700 Subject: Fix more potential for undefined behaviour due to container invalidation --- backends/aiger/xaiger.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae690ec49..d373ca77e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -436,14 +436,18 @@ struct XAigerWriter new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); + if (not_map.count(bit)) { + auto a = not_map.at(bit); + not_map[new_bit] = a; + } else if (and_map.count(bit)) { - //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 - and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + auto a = and_map.at(bit); + and_map[new_bit] = a; + } + else if (alias_map.count(bit)) { + auto a = alias_map.at(bit); + alias_map[new_bit] = a; } - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); else alias_map[new_bit] = bit; output_bits.erase(bit); -- cgit v1.2.3 From 524af2131741ae2c74a810cab3b925d5ce950e6e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:55:07 -0700 Subject: Also fix write_aiger for UB --- backends/aiger/aiger.cc | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 2815abda8..7c851bb91 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -70,35 +70,35 @@ struct AigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (initstate_bits.count(bit)) { - log_assert(initstate_ff > 0); - aig_map[bit] = initstate_ff; - } else - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; + } - if (bit == State::Sx || bit == State::Sz) - log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + if (bit == State::Sx || bit == State::Sz) + log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + + log_assert(a >= 0); + aig_map[bit] = a; + return a; } AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) -- cgit v1.2.3 From 38d8806bd74b9bb448c7488ec571e197fe2f96d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:59:47 -0700 Subject: Add generic __builtin_bswap32 function --- backends/aiger/xaiger.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d373ca77e..eb3d47569 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,21 @@ #elif defined(__APPLE__) #include #define __builtin_bswap32 OSSwapInt32 +#elif !defined(__GNUC__) +#include +inline uint32_t __builtin_bswap32(uint32_t x) +{ + // https://stackoverflow.com/a/27796212 + register uint32_t value = number_to_be_reversed; + uint8_t lolo = (value >> 0) & 0xFF; + uint8_t lohi = (value >> 8) & 0xFF; + uint8_t hilo = (value >> 16) & 0xFF; + uint8_t hihi = (value >> 24) & 0xFF; + return (hihi << 24) + | (hilo << 16) + | (lohi << 8) + | (lolo << 0); +} #endif #include "kernel/yosys.h" -- cgit v1.2.3 From a31e17182d7f9437fb78f5018dfccbd66d9704ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:50:34 -0700 Subject: Refactor and cope with new abc_flop format --- backends/aiger/xaiger.cc | 54 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 16 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8a35e06fa..19e6c8369 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -211,6 +211,7 @@ struct XAigerWriter // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; + dict> flop_data; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -264,36 +265,57 @@ struct XAigerWriter abc_box_seen = true; toposort.node(cell->name); - auto abc_flop_d = inst_module->attributes.at("\\abc_flop_d", RTLIL::Const()); - if (abc_flop_d.size() == 0) { - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + auto r = flop_data.insert(std::make_pair(cell->type, std::make_pair(IdString(), IdString()))); + if (r.second) { + auto it = inst_module->attributes.find("\\abc_flop"); + if (it != inst_module->attributes.end()) { + std::string abc_flop = it->second.decode_string(); + size_t start, end; + end = abc_flop.find(','); // Ignore original module + log_assert(end != std::string::npos); + start = end + 1; + end = abc_flop.find(',', start + 1); + log_assert(start != std::string::npos && end != std::string::npos); + auto abc_flop_d = RTLIL::escape_id(abc_flop.substr(start, end-start)); + start = end + 1; + end = abc_flop.find(',', start + 1); + log_assert(start != std::string::npos && end != std::string::npos); + auto abc_flop_q = RTLIL::escape_id(abc_flop.substr(start, end-start)); + r.first->second = std::make_pair(abc_flop_d, abc_flop_q); } } - else { - auto abc_flop_q = inst_module->attributes.at("\\abc_flop_q"); - SigBit d = cell->getPort(RTLIL::escape_id(abc_flop_d.decode_string())); + auto abc_flop_d = r.first->second.first; + if (abc_flop_d != IdString()) { + SigBit d = cell->getPort(abc_flop_d); SigBit I = sigmap(d); if (I != d) alias_map[I] = d; unused_bits.erase(d); - SigBit q = cell->getPort(RTLIL::escape_id(abc_flop_q.decode_string())); + auto abc_flop_q = r.first->second.second; + SigBit q = cell->getPort(abc_flop_q); SigBit O = sigmap(q); if (O != q) alias_map[O] = q; undriven_bits.erase(O); ff_bits.emplace_back(q); + + } + else { + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } } } else { -- cgit v1.2.3 From 69f4c039ce615c6a6c788e7b0da53e37467d32f6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 12:21:03 -0700 Subject: Safe side: all flops have different mergeability class --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 19e6c8369..632a5c8d5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -843,7 +843,7 @@ struct XAigerWriter write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) - write_r_buffer(mergeability_class); + write_r_buffer(mergeability_class++); f << "r"; buffer_str = r_buffer.str(); -- cgit v1.2.3 From 10524064e94b9fe21483092e2733b1b71ae60b4e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:14:30 -0700 Subject: write_xaiger to treat unknown cell connections as keep-s --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index eb3d47569..869b741a6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -138,6 +138,7 @@ struct XAigerWriter { pool undriven_bits; pool unused_bits; + pool keep_bits; // promote public wires for (auto wire : module->wires()) @@ -168,6 +169,9 @@ struct XAigerWriter unused_bits.insert(bit); } + if (keep) + keep_bits.insert(bit); + if (wire->port_input || keep) { if (bit != wirebit) alias_map[bit] = wirebit; @@ -235,7 +239,7 @@ struct XAigerWriter log_assert(!holes_mode); RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -255,10 +259,11 @@ struct XAigerWriter } } else { + bool cell_known = cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); + auto is_input = !cell_known || cell->input(c.first); + auto is_output = !cell_known || cell->output(c.first); if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); @@ -266,12 +271,15 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (!w->port_output) { + if (!w->port_output || !cell_known) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; output_bits.insert(b); unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); } } } @@ -424,7 +432,7 @@ struct XAigerWriter auto jt = input_bits.find(b); if (jt != input_bits.end()) { - log_assert(b.wire->attributes.count("\\keep")); + log_assert(keep_bits.count(O)); input_bits.erase(b); } } @@ -444,7 +452,7 @@ struct XAigerWriter // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) - || wire->attributes.count("\\keep")) { + || keep_bits.count(bit)) { RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) -- cgit v1.2.3 From 93bc5affd3fc635dafec3a37bf4c5b94c252036f Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 11:34:58 +0000 Subject: Allow attributes on individual switch cases in RTLIL. The parser changes are slightly awkward. Consider the following IL: process $0 switch \foo case 1'1 assign \bar \baz ... case end end Before this commit, attributes are valid in , and iff it is immediately followed by a `switch`. (They are essentially attached to the switch.) But, after this commit, and because switch cases do not have an ending delimiter, becomes ambiguous: the attribute could attach to either the following `case`, or to the following `switch`. This isn't expressible in LALR(1) and results in a reduce/reduce conflict. To address this, attributes inside processes are now valid anywhere inside the process: in and a part of case body, and in as a separate rule. As a consequence, attributes can now precede `assign`s, which is made illegal in the same way it is illegal to attach attributes to `connect`. Attributes are tracked separately from the parser state, so this does not affect collection of attributes at all, other than allowing them on `case`s. The grammar change serves purely to allow attributes in more syntactic places. --- backends/ilang/ilang_backend.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'backends') diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index b4ba2b03f..313af7d5c 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -204,6 +204,11 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) { + f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str()); + dump_const(f, ait->second); + f << stringf("\n"); + } f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) -- cgit v1.2.3 From 55c1f4027794a89971055b705254832b189a1c83 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 12:48:50 +0000 Subject: verilog_backend: dump attributes on CaseRule, as comments. Attributes are not permitted in that position by Verilog grammar. --- backends/verilog/verilog_backend.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 827af5d85..18c92521f 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -364,20 +364,22 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) } } -void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false) +void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false, bool as_comment = false) { if (noattr) return; + if (attr2comment) + as_comment = true; for (auto it = attributes.begin(); it != attributes.end(); ++it) { - f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str()); + f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); f << stringf(" = "); if (modattr && (it->second == Const(0, 1) || it->second == Const(0))) f << stringf(" 0 "); else if (modattr && (it->second == Const(1, 1) || it->second == Const(1))) f << stringf(" 1 "); else - dump_const(f, it->second, -1, 0, false, attr2comment); - f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); + dump_const(f, it->second, -1, 0, false, as_comment); + f << stringf(" %s%c", as_comment ? "*/" : "*)", term); } } @@ -1511,7 +1513,9 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":\n"); + f << stringf(":"); + dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); + f << stringf("\n"); dump_case_body(f, indent + " ", *it); } @@ -1662,7 +1666,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } } - dump_attributes(f, indent, module->attributes, '\n', true); + dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true); f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { -- cgit v1.2.3 From 628437b01cd37b95c020b2f4c4e2f2d8f0e9bf8b Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 15:11:29 +0000 Subject: verilog_backend: dump attributes on SwitchRule. This appears to be an omission. --- backends/verilog/verilog_backend.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 18c92521f..6288502a5 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1494,6 +1494,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw return; } + dump_attributes(f, indent, sw->attributes); f << stringf("%s" "casez (", indent.c_str()); dump_sigspec(f, sw->signal); f << stringf(")\n"); -- cgit v1.2.3 From 5a0f2e43c796ed91693d60261bd75a489f778a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:35:09 -0700 Subject: Rename __builtin_bswap32 -> bswap32 --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 869b741a6..69f63486c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -21,13 +21,15 @@ // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include -#define __builtin_bswap32 _byteswap_ulong +#define bswap32 _byteswap_ulong #elif defined(__APPLE__) #include -#define __builtin_bswap32 OSSwapInt32 -#elif !defined(__GNUC__) +#define bswap32 OSSwapInt32 +#elif defined(__GNUC__) +#define bswap32 __builtin_bswap32 +#else #include -inline uint32_t __builtin_bswap32(uint32_t x) +inline static uint32_t bswap32(uint32_t x) { // https://stackoverflow.com/a/27796212 register uint32_t value = number_to_be_reversed; -- cgit v1.2.3 From 6a29e1f5b7e8ac36fcf8c5f00c509ebeaa5257e5 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 18:30:24 +0000 Subject: write_verilog: write RTLIL::Sa aka - as Verilog ?. Currently, the only ways (determined by grepping for regex \bSa\b) to end up with RTLIL::Sa in a netlist is by reading a Verilog constant with ? in it as a part of case, or by running certain FSM passes. Both of these cases should be round-tripped back to ? in Verilog. --- backends/verilog/verilog_backend.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6288502a5..1c68288ce 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -222,7 +222,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o case RTLIL::S1: bin_digits.push_back('1'); break; case RTLIL::Sx: bin_digits.push_back('x'); break; case RTLIL::Sz: bin_digits.push_back('z'); break; - case RTLIL::Sa: bin_digits.push_back('z'); break; + case RTLIL::Sa: bin_digits.push_back('?'); break; case RTLIL::Sm: log_error("Found marker state in final netlist."); } } @@ -251,6 +251,12 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o hex_digits.push_back('z'); continue; } + if (bit_3 == '?' || bit_2 == '?' || bit_1 == '?' || bit_0 == '?') { + if (bit_3 != '?' || bit_2 != '?' || bit_1 != '?' || bit_0 != '?') + goto dump_bin; + hex_digits.push_back('?'); + continue; + } int val = 8*(bit_3 - '0') + 4*(bit_2 - '0') + 2*(bit_1 - '0') + (bit_0 - '0'); hex_digits.push_back(val < 10 ? '0' + val : 'a' + val - 10); } @@ -270,7 +276,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o case RTLIL::S1: f << stringf("1"); break; case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sz: f << stringf("z"); break; - case RTLIL::Sa: f << stringf("z"); break; + case RTLIL::Sa: f << stringf("?"); break; case RTLIL::Sm: log_error("Found marker state in final netlist."); } } -- cgit v1.2.3 From 37bb6b5e96fcedc1126c31aac84b8c029e192f5f Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 19:14:03 +0000 Subject: write_verilog: fix placement of case attributes. NFC. --- backends/verilog/verilog_backend.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6288502a5..087c6fec6 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1501,6 +1501,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw bool got_default = false; for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true); if ((*it)->compare.size() == 0) { if (got_default) continue; @@ -1514,9 +1515,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":"); - dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); - f << stringf("\n"); + f << stringf(":\n"); dump_case_body(f, indent + " ", *it); } -- cgit v1.2.3 From a092c48f036b71cc4014ec6f2865297d49589d40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 17:34:51 -0700 Subject: Use split_tokens() --- backends/aiger/xaiger.cc | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a1085addf..ba0e36ce1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -276,18 +276,12 @@ struct XAigerWriter if (r.second) { auto it = inst_module->attributes.find("\\abc_flop"); if (it != inst_module->attributes.end()) { - std::string abc_flop = it->second.decode_string(); - size_t start, end; - end = abc_flop.find(','); // Ignore original module - log_assert(end != std::string::npos); - start = end + 1; - end = abc_flop.find(',', start + 1); - log_assert(start != std::string::npos && end != std::string::npos); - auto abc_flop_d = RTLIL::escape_id(abc_flop.substr(start, end-start)); - start = end + 1; - end = abc_flop.find(',', start + 1); - log_assert(start != std::string::npos && end != std::string::npos); - auto abc_flop_q = RTLIL::escape_id(abc_flop.substr(start, end-start)); + auto abc_flop = it->second.decode_string(); + auto tokens = split_tokens(abc_flop, ","); + if (tokens.size() != 4) + log_error("'abc_flop' attribute on module '%s' does not contain exactly four comma-separated tokens.\n", log_id(cell->type)); + auto abc_flop_d = RTLIL::escape_id(tokens[1]); + auto abc_flop_q = RTLIL::escape_id(tokens[2]); r.first->second = std::make_pair(abc_flop_d, abc_flop_q); } } @@ -404,15 +398,15 @@ struct XAigerWriter if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; auto carry_in_out = it->second.decode_string(); - auto pos = carry_in_out.find(','); - if (pos == std::string::npos) - log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); - auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + auto tokens = split_tokens(carry_in_out, ","); + if (tokens.size() != 2) + log_error("'abc_carry' attribute on module '%s' does not contain exactly two comma-separated tokens.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(tokens[0]); carry_in = box_module->wire(carry_in_name); if (!carry_in || !carry_in->port_input) log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); - auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + auto carry_out_name = RTLIL::escape_id(tokens[1]); carry_out = box_module->wire(carry_out_name); if (!carry_out || !carry_out->port_output) log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); -- cgit v1.2.3 From 4a995c5d80735baf1431a088c2faf81eb75fdaf6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 17:54:56 -0700 Subject: Change how to specify flops to ABC again --- backends/aiger/xaiger.cc | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ba0e36ce1..53b6ff97a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -273,17 +273,27 @@ struct XAigerWriter toposort.node(cell->name); auto r = flop_data.insert(std::make_pair(cell->type, std::make_pair(IdString(), IdString()))); - if (r.second) { - auto it = inst_module->attributes.find("\\abc_flop"); - if (it != inst_module->attributes.end()) { - auto abc_flop = it->second.decode_string(); - auto tokens = split_tokens(abc_flop, ","); - if (tokens.size() != 4) - log_error("'abc_flop' attribute on module '%s' does not contain exactly four comma-separated tokens.\n", log_id(cell->type)); - auto abc_flop_d = RTLIL::escape_id(tokens[1]); - auto abc_flop_q = RTLIL::escape_id(tokens[2]); - r.first->second = std::make_pair(abc_flop_d, abc_flop_q); + if (r.second && inst_module->attributes.count("\\abc_flop")) { + IdString abc_flop_d, abc_flop_q; + for (auto port_name : inst_module->ports) { + auto wire = inst_module->wire(port_name); + log_assert(wire); + if (wire->attributes.count("\\abc_flop_d")) { + if (abc_flop_d != IdString()) + log_error("More than one port has the 'abc_flop_d' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_d = port_name; + } + if (wire->attributes.count("\\abc_flop_q")) { + if (abc_flop_q != IdString()) + log_error("More than one port has the 'abc_flop_q' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_q = port_name; + } } + if (abc_flop_d == IdString()) + log_error("'abc_flop_d' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + if (abc_flop_q == IdString()) + log_error("'abc_flop_q' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + r.first->second = std::make_pair(abc_flop_d, abc_flop_q); } auto abc_flop_d = r.first->second.first; -- cgit v1.2.3 From e603d719d650722e4fcd1b65b46c64da19c92f81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 19:04:22 -0700 Subject: Fix spacing --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 53b6ff97a..9a448c2a0 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -679,7 +679,7 @@ struct XAigerWriter aig_o++; aig_outputs.push_back(0); omode = true; - } + } } void write_aiger(std::ostream &f, bool ascii_mode) -- cgit v1.2.3 From ea6ffea2cd580542cbb5cc349f5268af0700e292 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 20:10:20 -0700 Subject: Fix clk_pol for FD*_1 --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 9a448c2a0..82c28549c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -311,7 +311,6 @@ struct XAigerWriter alias_map[O] = q; undriven_bits.erase(O); ff_bits.emplace_back(q); - } else { for (const auto &conn : cell->connections()) { -- cgit v1.2.3 From 375fcbe5113db80a92b950e5aca7df17add67acf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 20:26:09 -0700 Subject: abc_flop to also get topologically sorted --- backends/aiger/xaiger.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 82c28549c..5eeae3b82 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -312,19 +312,18 @@ struct XAigerWriter undriven_bits.erase(O); ff_bits.emplace_back(q); } - else { - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } } else { -- cgit v1.2.3 From ab4b9e8db481cd24b61cc0dc14bb5bf74d08006d Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Mon, 15 Jul 2019 23:33:18 +0800 Subject: smt: handle failure of setrlimit syscall --- backends/smt2/smtio.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ae7968a1b..bac68ac70 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -43,7 +43,11 @@ if os.name == "posix": if current_rlimit_stack[1] != resource.RLIM_INFINITY: smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) if current_rlimit_stack[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) + try: + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) + except ValueError: + # couldn't get more stack, just run with what we have + pass # currently running solvers (so we can kill them) -- cgit v1.2.3 From 4ff44d85a5cb63c7b3f67c2f2398e62db7f199eb Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 16 Jul 2019 20:57:05 +0000 Subject: write_verilog: dump zero width constants correctly. Before this commit, zero width constants were dumped as "" (empty string). Unfortunately, 1364-2005 5.2.3.3 indicates that an empty string is equivalent to "\0", and is 8 bits wide, so that's wrong. After this commit, a replication operation with a count of zero is used instead, which is explicitly permitted per 1364-2005 5.1.14, and is defined to have size zero. (Its operand has to have a non-zero size for it to be legal, though.) Fixes #948 (again). --- backends/verilog/verilog_backend.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a020d82b6..48404b34c 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -189,7 +189,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o if (width < 0) width = data.bits.size() - offset; if (width == 0) { - f << "\"\""; + // See IEEE 1364-2005 Clause 5.1.14. + f << "{0{1'b0}}"; return; } if (nostr) -- cgit v1.2.3 From 56c00e871fbb73649d3b6f7ccee31c90942a020c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 Jul 2019 11:49:04 +0200 Subject: Remove old $pmux_safe code from write_verilog Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a020d82b6..778f9b855 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -788,7 +788,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == "$pmux" || cell->type == "$pmux_safe") + if (cell->type == "$pmux") { int width = cell->parameters["\\WIDTH"].as_int(); int s_width = cell->getPort("\\S").size(); @@ -800,18 +800,17 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" " input [%d:0] s;\n", indent.c_str(), s_width-1); dump_attributes(f, indent + " ", cell->attributes); - if (cell->type != "$pmux_safe" && !noattr) + if (!noattr) f << stringf("%s" " (* parallel_case *)\n", indent.c_str()); f << stringf("%s" " casez (s)", indent.c_str()); - if (cell->type != "$pmux_safe") - f << stringf(noattr ? " // synopsys parallel_case\n" : "\n"); + f << stringf(noattr ? " // synopsys parallel_case\n" : "\n"); for (int i = 0; i < s_width; i++) { f << stringf("%s" " %d'b", indent.c_str(), s_width); for (int j = s_width-1; j >= 0; j--) - f << stringf("%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?'); + f << stringf("%c", j == i ? '1' : '?'); f << stringf(":\n"); f << stringf("%s" " %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width); -- cgit v1.2.3 From 7e298084e458c3fcccece565df305271db51aec8 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 24 Jul 2019 13:33:16 -0700 Subject: Call log_error() instead of log_warning() on unsupported cell type in FIRRTL backend. --- backends/firrtl/firrtl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 1c7a7351f..b7a798b85 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -833,7 +833,7 @@ struct FirrtlWorker register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } - log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); } for (auto conn : module->connections()) -- cgit v1.2.3 From 35d28de47892d7905d8b37538a581950d4eb54c7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 31 Jul 2019 09:10:24 +0200 Subject: Visual Studio build fix --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 69f63486c..6aa9cde54 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN inline int32_t to_big_endian(int32_t i32) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return __builtin_bswap32(i32); + return bswap32(i32); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return i32; #else -- cgit v1.2.3 From 3b8c917025e1be9695468588082e9175e918c9e9 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 31 Jul 2019 09:27:38 -0700 Subject: Support explicit FIRRTL properties for better accommodation of FIRRTL/Verilog semantic differences. Use FIRRTL spec vlaues for definition of FIRRTL widths. Added support for '$pos`, `$pow` and `$xnor` cells. Enable tests/simple/operators.v since all operators tested there are now supported. Disable FIRRTL tests of tests/simple/{defvalue.sv,implicit_ports.v,wandwor.v} since they currently generate FIRRTL compilation errors. --- backends/firrtl/firrtl.cc | 296 +++++++++++++++++++++++++++++++--------------- 1 file changed, 203 insertions(+), 93 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 1c7a7351f..9ef6e311a 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -381,10 +381,10 @@ struct FirrtlWorker // Given an expression for a shift amount, and a maximum width, // generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics. - std::string gen_dshl(const string b_expr, const int b_padded_width) + std::string gen_dshl(const string b_expr, const int b_width) { string result = b_expr; - if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { + if (b_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1; string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<cells()) { - bool extract_y_bits = false; // Assume no extraction of final bits will be required. + static Const ndef(0, 0); + // Is this cell is a module instance? if (cell->type[0] != '$') { process_instance(cell, wire_exprs); continue; } + // Not a module instance. Set up cell properties + bool extract_y_bits = false; // Assume no extraction of final bits will be required. + int a_width = cell->parameters.at("\\A_WIDTH", ndef).as_int(); // The width of "A" + int b_width = cell->parameters.at("\\B_WIDTH", ndef).as_int(); // The width of "A" + const int y_width = cell->parameters.at("\\Y_WIDTH", ndef).as_int(); // The width of the result + const bool a_signed = cell->parameters.at("\\A_SIGNED", ndef).as_bool(); + const bool b_signed = cell->parameters.at("\\B_SIGNED", ndef).as_bool(); + bool firrtl_is_signed = a_signed; // The result is signed (subsequent code may change this). + int firrtl_width = 0; + string primop; + bool always_uint = false; + string y_id = make_id(cell->name); + if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { - string y_id = make_id(cell->name); - bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->parameters.at("\\A_SIGNED").as_bool()) { + if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; } @@ -446,12 +457,13 @@ struct FirrtlWorker a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); } - string primop; - bool always_uint = false; + // Assume the FIRRTL width is a single bit. + firrtl_width = 1; if (cell->type == "$not") primop = "not"; else if (cell->type == "$neg") { primop = "neg"; - is_signed = true; // Result of "neg" is signed (an SInt). + firrtl_is_signed = true; // Result of "neg" is signed (an SInt). + firrtl_width = a_width; } else if (cell->type == "$logic_not") { primop = "eq"; a_expr = stringf("%s, UInt(0)", a_expr.c_str()); @@ -466,14 +478,12 @@ struct FirrtlWorker else if (cell->type == "$reduce_bool") { primop = "neq"; // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. - bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int a_width = cell->parameters.at("\\A_WIDTH").as_int(); a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width); } string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str()); - if ((is_signed && !always_uint)) + if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); @@ -481,81 +491,121 @@ struct FirrtlWorker continue; } - if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx", + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", - "$logic_and", "$logic_or")) + "$logic_and", "$logic_or", "$pow")) { - string y_id = make_id(cell->name); - bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); - int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->parameters.at("\\A_SIGNED").as_bool()) { + if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; - } - // Shift amount is always unsigned, and needn't be padded to result width. - if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { - if (cell->parameters.at("\\B_SIGNED").as_bool()) { - b_expr = "asSInt(" + b_expr + ")"; + // Expand the "A" operand to the result width + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + a_width = y_width; } - if (b_padded_width < y_width) { - auto b_sig = cell->getPort("\\B"); - b_padded_width = y_width; + } + // Shift amount is always unsigned, and needn't be padded to result width, + // otherwise, we need to cast the b_expr appropriately + if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) { + b_expr = "asSInt(" + b_expr + ")"; + // Expand the "B" operand to the result width + if (b_width < y_width) { + b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); + b_width = y_width; } } + // For the arithmetic ops, expand operand widths to result widths befor performing the operation. + // This corresponds (according to iverilog) to what verilog compilers implement. + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or")) + { + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + a_width = y_width; + } + if (b_width < y_width) { + b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); + b_width = y_width; + } + } + // Assume the FIRRTL width is the width of "A" + firrtl_width = a_width; auto a_sig = cell->getPort("\\A"); - if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { - a_expr = "asUInt(" + a_expr + ")"; + if (cell->type == "$add") { + primop = "add"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = max(a_width, b_width); + } else if (cell->type == "$sub") { + primop = "sub"; + firrtl_is_signed = true; + int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0; + int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0; + firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc); + } else if (cell->type == "$mul") { + primop = "mul"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = a_width + b_width; + } else if (cell->type == "$div") { + primop = "div"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = a_width; + } else if (cell->type == "$mod") { + primop = "rem"; + firrtl_width = min(a_width, b_width); + } else if (cell->type == "$and") { + primop = "and"; + always_uint = true; + firrtl_width = max(a_width, b_width); } - - string primop; - bool always_uint = false; - if (cell->type == "$add") primop = "add"; - else if (cell->type == "$sub") primop = "sub"; - else if (cell->type == "$mul") primop = "mul"; - else if (cell->type == "$div") primop = "div"; - else if (cell->type == "$mod") primop = "rem"; - else if (cell->type == "$and") { - primop = "and"; - always_uint = true; - } else if (cell->type == "$or" ) { - primop = "or"; - always_uint = true; - } + primop = "or"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } else if (cell->type == "$xor") { - primop = "xor"; - always_uint = true; - } + primop = "xor"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } + else if (cell->type == "$xnor") { + primop = "xnor"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } else if ((cell->type == "$eq") | (cell->type == "$eqx")) { - primop = "eq"; - always_uint = true; - } + primop = "eq"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$ne") | (cell->type == "$nex")) { - primop = "neq"; - always_uint = true; - } + primop = "neq"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$gt") { - primop = "gt"; - always_uint = true; - } + primop = "gt"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$ge") { - primop = "geq"; - always_uint = true; - } + primop = "geq"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$lt") { - primop = "lt"; - always_uint = true; - } + primop = "lt"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$le") { - primop = "leq"; - always_uint = true; - } + primop = "leq"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$shl") | (cell->type == "$sshl")) { // FIRRTL will widen the result (y) by the amount of the shift. // We'll need to offset this by extracting the un-widened portion as Verilog would do. @@ -564,11 +614,14 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; - b_expr = std::to_string(b_sig.as_int()); + int shift_amount = b_sig.as_int(); + b_expr = std::to_string(shift_amount); + firrtl_width = a_width + shift_amount; } else { primop = "dshl"; // Convert from FIRRTL left shift semantics. - b_expr = gen_dshl(b_expr, b_padded_width); + b_expr = gen_dshl(b_expr, b_width); + firrtl_width = a_width + (1 << b_width) - 1; } } else if ((cell->type == "$shr") | (cell->type == "$sshr")) { @@ -578,36 +631,86 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shr"; - b_expr = std::to_string(b_sig.as_int()); + int shift_amount = b_sig.as_int(); + b_expr = std::to_string(shift_amount); + firrtl_width = max(1, a_width - shift_amount); } else { primop = "dshr"; + firrtl_width = a_width; + } + // We'll need to do some special fixups if the source (and thus result) is signed. + if (firrtl_is_signed) { + // If this is a "logical" shift right, pretend the source is unsigned. + if (cell->type == "$shr") { + a_expr = "asUInt(" + a_expr + ")"; + } } } else if ((cell->type == "$logic_and")) { - primop = "and"; - a_expr = "neq(" + a_expr + ", UInt(0))"; - b_expr = "neq(" + b_expr + ", UInt(0))"; - always_uint = true; - } + primop = "and"; + a_expr = "neq(" + a_expr + ", UInt(0))"; + b_expr = "neq(" + b_expr + ", UInt(0))"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$logic_or")) { - primop = "or"; - a_expr = "neq(" + a_expr + ", UInt(0))"; - b_expr = "neq(" + b_expr + ", UInt(0))"; - always_uint = true; - } + primop = "or"; + a_expr = "neq(" + a_expr + ", UInt(0))"; + b_expr = "neq(" + b_expr + ", UInt(0))"; + always_uint = true; + firrtl_width = 1; + } + else if ((cell->type == "$pow")) { + if (a_sig.is_fully_const() && a_sig.as_int() == 2) { + // We'll convert this to a shift. To simplify things, change the a_expr to "1" + // so we can use b_expr directly as a shift amount. + // Only support 2 ** N (i.e., shift left) + // FIRRTL will widen the result (y) by the amount of the shift. + // We'll need to offset this by extracting the un-widened portion as Verilog would do. + a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)"; + extract_y_bits = true; + // Is the shift amount constant? + auto b_sig = cell->getPort("\\B"); + if (b_sig.is_fully_const()) { + primop = "shl"; + int shiftAmount = b_sig.as_int(); + if (shiftAmount < 0) { + log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell)); + } + b_expr = std::to_string(shiftAmount); + firrtl_width = a_width + shiftAmount; + } else { + primop = "dshl"; + // Convert from FIRRTL left shift semantics. + b_expr = gen_dshl(b_expr, b_width); + firrtl_width = a_width + (1 << b_width) - 1; + } + } else { + log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell)); + } + } if (!cell->parameters.at("\\B_SIGNED").as_bool()) { b_expr = "asUInt(" + b_expr + ")"; } - string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); + string expr; + // Deal with $xnor == ~^ (not xor) + if (primop == "xnor") { + expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str()); + } else { + expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); + } - // Deal with FIRRTL's "shift widens" semantics + // Deal with FIRRTL's "shift widens" semantics, or the need to widen the FIRRTL result. + // If the operation is signed, the FIRRTL width will be 1 one bit larger. if (extract_y_bits) { expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); + } else if (firrtl_is_signed && (firrtl_width + 1) < y_width) { + expr = stringf("pad(%s, %d)", expr.c_str(), y_width); } - if ((is_signed && !always_uint) || cell->type.in("$sub")) + if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); @@ -618,7 +721,6 @@ struct FirrtlWorker if (cell->type.in("$mux")) { - string y_id = make_id(cell->name); int width = cell->parameters.at("\\WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); @@ -762,15 +864,14 @@ struct FirrtlWorker if (clkpol == false) log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); - string q_id = make_id(cell->name); int width = cell->parameters.at("\\WIDTH").as_int(); string expr = make_expr(cell->getPort("\\D")); string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; - wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str())); + wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str())); - cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str())); - register_reverse_wire_map(q_id, cell->getPort("\\Q")); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Q")); continue; } @@ -785,8 +886,6 @@ struct FirrtlWorker // assign y = a[b +: y_width]; // We'll extract the correct bits as part of the primop. - string y_id = make_id(cell->name); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); // Get the initial bit selector string b_expr = make_expr(cell->getPort("\\B")); @@ -808,18 +907,15 @@ struct FirrtlWorker // assign y = a >> b; // where b may be negative - string y_id = make_id(cell->name); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); auto b_string = b_expr.c_str(); - int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); string expr; wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); if (cell->getParam("\\B_SIGNED").as_bool()) { // We generate a left or right shift based on the sign of b. - std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width); + std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width); std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); expr = stringf("mux(%s < 0, %s, %s)", b_string, @@ -833,6 +929,20 @@ struct FirrtlWorker register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } + if (cell->type == "$pos") { + // assign y = a; +// printCell(cell); + string a_expr = make_expr(cell->getPort("\\A")); + // Verilog appears to treat the result as signed, so if the result is wider than "A", + // we need to pad. + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + } + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); + continue; + } log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); } -- cgit v1.2.3 From 15fae357f6c7a5c205d2733cd0b2640eecd17a2d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Aug 2019 12:34:52 +0200 Subject: Implement improved JSON attr/param encoding Signed-off-by: Clifford Wolf --- backends/json/json.cc | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'backends') diff --git a/backends/json/json.cc b/backends/json/json.cc index dda4dfedd..107009ee4 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -83,20 +83,43 @@ struct JsonWriter return str + " ]"; } + void write_parameter_value(const Const &value) + { + if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) { + string str = value.decode_string(); + int state = 0; + for (char c : str) { + if (state == 0) { + if (c == '0' || c == '1' || c == 'x' || c == 'z') + state = 0; + else if (c == ' ') + state = 1; + else + state = 2; + } else if (state == 1 && c != ' ') + state = 2; + } + if (state < 2) + str += " "; + f << get_string(str); + } else + if (GetSize(value) == 32 && value.is_fully_def()) { + if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0) + f << stringf("%d", value.as_int()); + else + f << stringf("%u", value.as_int()); + } else { + f << get_string(value.as_string()); + } + } + void write_parameters(const dict ¶meters, bool for_module=false) { bool first = true; for (auto ¶m : parameters) { f << stringf("%s\n", first ? "" : ","); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str()); - if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) - f << get_string(param.second.decode_string()); - else if (GetSize(param.second.bits) > 32) - f << get_string(param.second.as_string()); - else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0) - f << stringf("%d", param.second.as_int()); - else - f << stringf("%u", param.second.as_int()); + write_parameter_value(param.second); first = false; } } @@ -342,12 +365,13 @@ struct JsonBackend : public Backend { log("Module and cell ports and nets can be single bit wide or vectors of multiple\n"); log("bits. Each individual signal bit is assigned a unique integer. The \n"); log("values referenced above are vectors of this integers. Signal bits that are\n"); - log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n"); - log("a number.\n"); + log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n"); + log("\"z\" instead of a number.\n"); log("\n"); - log("Numeric parameter and attribute values up to 32 bits are written as decimal\n"); - log("values. Numbers larger than that are written as string holding the binary\n"); - log("representation of the value.\n"); + log("Numeric 32-bit parameter and attribute values are written as decimal values.\n"); + log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n"); + log("as string holding the binary representation of the value. Strings are written\n"); + log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n"); log("\n"); log("For example the following Verilog code:\n"); log("\n"); -- cgit v1.2.3 From 28b7053a01630def454e683f03953c74744da025 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 31 Jul 2019 11:49:48 +0200 Subject: Fix formatting for msys2 mingw build using GetSize --- backends/aiger/xaiger.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 69f63486c..9f56d1ab6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -610,15 +610,15 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", output_bits.size() + co_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); write_h_buffer(output_bits.size() + co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size()); + log_debug("piNum = %d\n", GetSize(input_bits)); write_h_buffer(input_bits.size()); - log_debug("poNum = %zu\n", output_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); write_h_buffer(output_bits.size()); - log_debug("boxNum = %zu\n", box_list.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -772,7 +772,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire)); continue; } -- cgit v1.2.3 From 023086bd46bc828621ebb171b159efe1398aaecf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Aug 2019 04:47:55 +0200 Subject: Add $_NMUX_, add "abc -g cmos", add proper cmos cell costs Signed-off-by: Clifford Wolf --- backends/blif/blif.cc | 7 +++++++ backends/btor/btor.cc | 8 +++++++- backends/simplec/simplec.cc | 6 ++++-- backends/smt2/smt2.cc | 1 + backends/smv/smv.cc | 7 +++++++ backends/verilog/verilog_backend.cc | 14 ++++++++++++++ 6 files changed, 40 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index a1761b662..f32b0f533 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -327,6 +327,13 @@ struct BlifDumper goto internal_cell; } + if (!config->icells_mode && cell->type == "$_NMUX_") { + f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), + cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y"))); + goto internal_cell; + } + if (!config->icells_mode && cell->type == "$_FF_") { f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), cstr_init(cell->getPort("\\Q"))); diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index a507b120b..7bacce2af 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -496,7 +496,7 @@ struct BtorWorker goto okay; } - if (cell->type.in("$mux", "$_MUX_")) + if (cell->type.in("$mux", "$_MUX_", "$_NMUX_")) { SigSpec sig_a = sigmap(cell->getPort("\\A")); SigSpec sig_b = sigmap(cell->getPort("\\B")); @@ -511,6 +511,12 @@ struct BtorWorker int nid = next_nid++; btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); + if (cell->type == "$_NMUX_") { + int tmp = nid; + nid = next_nid++; + btorf("%d not %d %d\n", nid, sid, tmp); + } + add_nid_sig(nid, sig_y); goto okay; } diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 6f2ccbe20..54dbb84af 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -472,7 +472,7 @@ struct SimplecWorker return; } - if (cell->type == "$_MUX_") + if (cell->type.in("$_MUX_", "$_NMUX_")) { SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); @@ -484,7 +484,9 @@ struct SimplecWorker string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0"; // casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933) - string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); + string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(), + cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(), + cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index e318a4051..ddd680782 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -510,6 +510,7 @@ struct Smt2Worker if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))"); if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))"); if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)"); + if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))"); if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))"); if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))"); if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))"); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index d75456c1b..e9586fae0 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -537,6 +537,13 @@ struct SmvWorker continue; } + if (cell->type == "$_NMUX_") + { + definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A")))); + continue; + } + if (cell->type == "$_AOI3_") { definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index e0b3a6f80..776f4eacb 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type == "$_NMUX_") { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = !("); + dump_cell_expr_port(f, cell, "S", false); + f << stringf(" ? "); + dump_attributes(f, "", cell->attributes, ' '); + dump_cell_expr_port(f, cell, "B", false); + f << stringf(" : "); + dump_cell_expr_port(f, cell, "A", false); + f << stringf(");\n"); + return true; + } + if (cell->type.in("$_AOI3_", "$_OAI3_")) { f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, cell->getPort("\\Y")); -- cgit v1.2.3 From 3486235338faa1377bb4e1a8981a45b4ee6edfa9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:18:18 -0700 Subject: Make liberal use of IdString.in() --- backends/smt2/smt2.cc | 2 +- backends/verilog/verilog_backend.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index ddd680782..db849882e 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -601,7 +601,7 @@ struct Smt2Worker if (cell->type == "$logic_and") return export_reduce(cell, "(and (or A) (or B))", false); if (cell->type == "$logic_or") return export_reduce(cell, "(or A B)", false); - if (cell->type == "$mux" || cell->type == "$pmux") + if (cell->type.in("$mux", "$pmux")) { int width = GetSize(cell->getPort("\\Y")); std::string processed_expr = get_bv(cell->getPort("\\A")); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 776f4eacb..9a797b535 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -949,7 +949,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffe") + if (cell->type.in("$dff", "$adff", "$dffe")) { RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst; bool pol_clk, pol_arst = false, pol_en = false; -- cgit v1.2.3 From 046e1a52147dd4a0e1f23e4aa7cb71b0a4d1b497 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:22:47 -0700 Subject: Use State::S{0,1} --- backends/btor/btor.cc | 4 ++-- backends/firrtl/firrtl.cc | 4 ++-- backends/verilog/verilog_backend.cc | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 7bacce2af..7c054d655 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -616,8 +616,8 @@ struct BtorWorker if (initstate_nid < 0) { int sid = get_bv_sid(1); - int one_nid = get_sig_nid(Const(1, 1)); - int zero_nid = get_sig_nid(Const(0, 1)); + int one_nid = get_sig_nid(State::S1); + int zero_nid = get_sig_nid(State::S0); initstate_nid = next_nid++; btorf("%d state %d\n", initstate_nid, sid); btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 1c7a7351f..4758c6d4d 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -122,9 +122,9 @@ struct FirrtlWorker // Current (3/13/2019) conventions: // generate a constant 0 for clock and a constant 1 for enable if they are undefined. if (!clk.is_fully_def()) - this->clk = SigSpec(RTLIL::Const(0, 1)); + this->clk = SigSpec(State::S0); if (!ena.is_fully_def()) - this->ena = SigSpec(RTLIL::Const(1, 1)); + this->ena = SigSpec(State::S1); } string gen_read(const char * indent) { string addr_expr = make_expr(addr); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 9a797b535..6cb053f1d 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -380,9 +380,9 @@ void dump_attributes(std::ostream &f, std::string indent, dictfirst).c_str()); f << stringf(" = "); - if (modattr && (it->second == Const(0, 1) || it->second == Const(0))) + if (modattr && (it->second == State::S0 || it->second == Const(0))) f << stringf(" 0 "); - else if (modattr && (it->second == Const(1, 1) || it->second == Const(1))) + else if (modattr && (it->second == State::S1 || it->second == Const(1))) f << stringf(" 1 "); else dump_const(f, it->second, -1, 0, false, as_comment); -- cgit v1.2.3 From a6bc9265fbb2abad73120a068a09f0c7833304de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:23:37 -0700 Subject: RTLIL::S{0,1} -> State::S{0,1} --- backends/aiger/xaiger.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a3a753912..615854459 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -388,11 +388,11 @@ struct XAigerWriter RTLIL::SigSpec rhs; if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) - it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); + it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second))); rhs = it->second; } else { - rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + rhs = RTLIL::SigSpec(State::S0, GetSize(w)); cell->setPort(port_name, rhs); } @@ -400,10 +400,10 @@ struct XAigerWriter for (auto b : rhs.bits()) { SigBit I = sigmap(b); if (b == RTLIL::Sx) - b = RTLIL::S0; + b = State::S0; else if (I != b) { if (I == RTLIL::Sx) - alias_map[b] = RTLIL::S0; + alias_map[b] = State::S0; else alias_map[b] = I; } @@ -672,7 +672,7 @@ struct XAigerWriter if (holes_cell) port_wire.append(holes_wire); else - holes_module->connect(holes_wire, RTLIL::S0); + holes_module->connect(holes_wire, State::S0); } if (!port_wire.empty()) holes_cell->setPort(w->name, port_wire); -- cgit v1.2.3 From e38f40af5b7cdd5c8b896ffba17069bd65f01f29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:42:25 -0700 Subject: Use IdString::begins_with() --- backends/firrtl/firrtl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 4758c6d4d..bb5ea2932 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -297,7 +297,7 @@ struct FirrtlWorker std::string cell_type = fid(cell->type); std::string instanceOf; // If this is a parameterized module, its parent module is encoded in the cell type - if (cell->type.substr(0, 8) == "$paramod") + if (cell->type.begins_with("$paramod")) { std::string::iterator it; for (it = cell_type.begin(); it < cell_type.end(); it++) @@ -776,7 +776,7 @@ struct FirrtlWorker } // This may be a parameterized module - paramod. - if (cell->type.substr(0, 8) == "$paramod") + if (cell->type.begins_with("$paramod")) { process_instance(cell, wire_exprs); continue; -- cgit v1.2.3 From 3090da2d98221435f2d702efee5fa0f5d9fedc68 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 22:21:14 -0700 Subject: Run "clean -purge" on holes_module in its own design --- backends/aiger/xaiger.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a3a753912..36a379e34 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -621,8 +621,7 @@ struct XAigerWriter log_debug("boxNum = %d\n", GetSize(box_list)); write_h_buffer(box_list.size()); - RTLIL::Module *holes_module = nullptr; - holes_module = module->design->addModule("$__holes__"); + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); int port_id = 1; @@ -719,27 +718,33 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call + // instead of per write_xaiger call Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - Pass::call(holes_module->design, "clean -purge"); + holes_module->design->selection_stack.pop_back(); + + // Move into a new (temporary) design so that "clean" will only + // operate (and run checks on) this one module + RTLIL::Design *holes_design = new RTLIL::Design; + holes_module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); - holes_module->design->selection_stack.pop_back(); + delete holes_design; f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - holes_module->design->remove(holes_module); log_pop(); } -- cgit v1.2.3 From 71649969213863b2695f1c51956886fc7879c3e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 11:12:38 -0700 Subject: RTLIL::S{0,1} -> State::S{0,1} --- backends/blif/blif.cc | 2 +- backends/ilang/ilang_backend.cc | 8 ++++---- backends/intersynth/intersynth.cc | 2 +- backends/verilog/verilog_backend.cc | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'backends') diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index f32b0f533..b6e38c16c 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -377,7 +377,7 @@ struct BlifDumper f << stringf("\n"); RTLIL::SigSpec mask = cell->parameters.at("\\LUT"); for (int i = 0; i < (1 << width); i++) - if (mask[i] == RTLIL::S1) { + if (mask[i] == State::S1) { for (int j = width-1; j >= 0; j--) { f << ((i>>j)&1 ? '1' : '0'); } diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 313af7d5c..e06786220 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -40,8 +40,8 @@ void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi for (int i = 0; i < width; i++) { log_assert(offset+i < (int)data.bits.size()); switch (data.bits[offset+i]) { - case RTLIL::S0: break; - case RTLIL::S1: val |= 1 << i; break; + case State::S0: break; + case State::S1: val |= 1 << i; break; default: val = -1; break; } } @@ -54,8 +54,8 @@ void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi for (int i = offset+width-1; i >= offset; i--) { log_assert(i < (int)data.bits.size()); switch (data.bits[i]) { - case RTLIL::S0: f << stringf("0"); break; - case RTLIL::S1: f << stringf("1"); break; + case State::S0: f << stringf("0"); break; + case State::S1: f << stringf("1"); break; case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sz: f << stringf("z"); break; case RTLIL::Sa: f << stringf("-"); break; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index b0e3cd252..98746809c 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -183,7 +183,7 @@ struct IntersynthBackend : public Backend { if (param.second.bits.size() != 32) { node_code += stringf(" %s '", RTLIL::id2cstr(param.first)); for (int i = param.second.bits.size()-1; i >= 0; i--) - node_code += param.second.bits[i] == RTLIL::S1 ? "1" : "0"; + node_code += param.second.bits[i] == State::S1 ? "1" : "0"; } else node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int()); } diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6cb053f1d..6065a71ff 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -200,9 +200,9 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o int32_t val = 0; for (int i = offset+width-1; i >= offset; i--) { log_assert(i < (int)data.bits.size()); - if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1) + if (data.bits[i] != State::S0 && data.bits[i] != State::S1) goto dump_hex; - if (data.bits[i] == RTLIL::S1) + if (data.bits[i] == State::S1) val |= 1 << (i - offset); } if (decimal) @@ -219,8 +219,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o for (int i = offset; i < offset+width; i++) { log_assert(i < (int)data.bits.size()); switch (data.bits[i]) { - case RTLIL::S0: bin_digits.push_back('0'); break; - case RTLIL::S1: bin_digits.push_back('1'); break; + case State::S0: bin_digits.push_back('0'); break; + case State::S1: bin_digits.push_back('1'); break; case RTLIL::Sx: bin_digits.push_back('x'); break; case RTLIL::Sz: bin_digits.push_back('z'); break; case RTLIL::Sa: bin_digits.push_back('?'); break; @@ -273,8 +273,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o for (int i = offset+width-1; i >= offset; i--) { log_assert(i < (int)data.bits.size()); switch (data.bits[i]) { - case RTLIL::S0: f << stringf("0"); break; - case RTLIL::S1: f << stringf("1"); break; + case State::S0: f << stringf("0"); break; + case State::S1: f << stringf("1"); break; case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sz: f << stringf("z"); break; case RTLIL::Sa: f << stringf("?"); break; -- cgit v1.2.3 From 6d77236f3845cd8785e7bdd4da3c5ef966be6043 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 12:20:08 -0700 Subject: substr() -> compare() --- backends/firrtl/firrtl.cc | 2 +- backends/intersynth/intersynth.cc | 2 +- backends/smt2/smt2.cc | 2 +- backends/smv/smv.cc | 2 +- backends/verilog/verilog_backend.cc | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'backends') diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 5be6d60fd..73b1e7d53 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -363,7 +363,7 @@ struct FirrtlWorker } // Check for subfield assignment. std::string bitsString = "bits("; - if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { + if (sinkExpr.compare(0, bitsString.length(), bitsString) == 0) { if (sinkSig == nullptr) log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); // Don't generate the assignment here. diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 98746809c..809a0fa09 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -108,7 +108,7 @@ struct IntersynthBackend : public Backend { if (f.fail()) log_error("Can't open lib file `%s'.\n", filename.c_str()); RTLIL::Design *lib = new RTLIL::Design; - Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog"); + Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog")); libs.push_back(lib); } diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index db849882e..081dcda99 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1476,7 +1476,7 @@ struct Smt2Backend : public Backend { int indent = 0; while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t')) indent++; - if (line.substr(indent, 2) == "%%") + if (line.compare(indent, 2, "%%") == 0) break; *f << line << std::endl; } diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index e9586fae0..f755307bf 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -61,7 +61,7 @@ struct SmvWorker { string name = stringf("_%s", id.c_str()); - if (name.substr(0, 2) == "_\\") + if (name.compare(0, 2, "_\\") == 0) name = "_" + name.substr(2); for (auto &c : name) { diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6065a71ff..7b1db4776 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -604,7 +604,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.substr(0, 6) == "$_DFF_") + if (cell->type.begins_with("$_DFF_")) { std::string reg_name = cellname(cell); bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); @@ -645,7 +645,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.substr(0, 8) == "$_DFFSR_") + if (cell->type.begins_with("$_DFFSR_")) { char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10]; -- cgit v1.2.3 From 0c5db07cd6cc3c19b926da21a46599f97592b20f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Aug 2019 23:25:46 +0200 Subject: Fix various NDEBUG compiler warnings, closes #1255 Signed-off-by: Clifford Wolf --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f49ecbeda..5e12e9a34 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -312,7 +312,7 @@ struct XAigerWriter #if 0 toposort.analyze_loops = true; #endif - bool no_loops = toposort.sort(); + bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); #if 0 unsigned i = 0; for (auto &it : toposort.loops) { -- cgit v1.2.3 From 4fe307f1bc02e32ae70f7ef9495f3418303e43e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 16 Aug 2019 15:41:17 -0700 Subject: Compute abc_scc_break and move CI/CO outside of each abc9 --- backends/aiger/xaiger.cc | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f49ecbeda..41a79d9dd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -326,7 +326,6 @@ struct XAigerWriter #endif log_assert(no_loops); - pool seen_boxes; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); log_assert(cell); @@ -335,47 +334,6 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; - if (seen_boxes.insert(cell->type).second) { - auto it = box_module->attributes.find("\\abc_carry"); - if (it != box_module->attributes.end()) { - RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; - auto carry_in_out = it->second.decode_string(); - auto pos = carry_in_out.find(','); - if (pos == std::string::npos) - log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); - auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); - carry_in = box_module->wire(carry_in_name); - if (!carry_in || !carry_in->port_input) - log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); - - auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); - carry_out = box_module->wire(carry_out_name); - if (!carry_out || !carry_out->port_output) - log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); - - auto &ports = box_module->ports; - for (auto jt = ports.begin(); jt != ports.end(); ) { - RTLIL::Wire* w = box_module->wire(*jt); - log_assert(w); - if (w == carry_in || w == carry_out) { - jt = ports.erase(jt); - continue; - } - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); - ++jt; - } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); - } - } - // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires // NB: Assume box_module->ports are sorted alphabetically -- cgit v1.2.3 From 10c69f71e9dd03780364402f5c470be33f6cfca5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 19 Aug 2019 09:16:20 -0700 Subject: Use %d --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5d3677ab3..0a2445593 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -808,7 +808,7 @@ struct XAigerWriter std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %zu\n", ff_bits.size()); + log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) -- cgit v1.2.3 From 91687d3feae8df0e315232d3989a445e7d452d1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 19 Aug 2019 12:33:24 -0700 Subject: Add (* abc_arrival *) attribute --- backends/aiger/xaiger.cc | 75 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 9 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f6b51b787..6f91e34bd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,6 +86,7 @@ struct XAigerWriter vector> ci_bits; vector> co_bits; vector ff_bits; + dict arrival_times; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -217,7 +218,12 @@ struct XAigerWriter // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; - dict> flop_data; + struct flop_data_t { + IdString d_port; + IdString q_port; + int q_arrival; + }; + dict flop_data; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -272,9 +278,10 @@ struct XAigerWriter toposort.node(cell->name); - auto r = flop_data.insert(std::make_pair(cell->type, std::make_pair(IdString(), IdString()))); + auto r = flop_data.insert(std::make_pair(cell->type, flop_data_t{IdString(), IdString(), 0})); if (r.second && inst_module->attributes.count("\\abc_flop")) { - IdString abc_flop_d, abc_flop_q; + IdString &abc_flop_d = r.first->second.d_port; + IdString &abc_flop_q = r.first->second.q_port; for (auto port_name : inst_module->ports) { auto wire = inst_module->wire(port_name); log_assert(wire); @@ -287,16 +294,22 @@ struct XAigerWriter if (abc_flop_q != IdString()) log_error("More than one port has the 'abc_flop_q' attribute set on module '%s'.\n", log_id(cell->type)); abc_flop_q = port_name; + + auto it = wire->attributes.find("\\abc_arrival"); + if (it != wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); + r.first->second.q_arrival = it->second.as_int(); + } } } if (abc_flop_d == IdString()) log_error("'abc_flop_d' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); if (abc_flop_q == IdString()) log_error("'abc_flop_q' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - r.first->second = std::make_pair(abc_flop_d, abc_flop_q); } - auto abc_flop_d = r.first->second.first; + auto abc_flop_d = r.first->second.d_port; if (abc_flop_d != IdString()) { SigBit d = cell->getPort(abc_flop_d); SigBit I = sigmap(d); @@ -304,13 +317,17 @@ struct XAigerWriter alias_map[I] = d; unused_bits.erase(d); - auto abc_flop_q = r.first->second.second; + auto abc_flop_q = r.first->second.q_port; SigBit q = cell->getPort(abc_flop_q); SigBit O = sigmap(q); if (O != q) alias_map[O] = q; undriven_bits.erase(O); ff_bits.emplace_back(q); + + auto arrival = r.first->second.q_arrival; + if (arrival) + arrival_times[q] = arrival; } for (const auto &conn : cell->connections()) { @@ -330,12 +347,22 @@ struct XAigerWriter bool cell_known = cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto is_input = !cell_known || cell->input(c.first); - auto is_output = !cell_known || cell->output(c.first); + auto port_wire = inst_module->wire(c.first); + log_assert(port_wire); + auto is_input = !cell_known || port_wire->port_input; + auto is_output = !cell_known || port_wire->port_output; if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { + int arrival = 0; + auto it = port_wire->attributes.find("\\abc_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); + arrival = it->second.as_int(); + } + for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -349,6 +376,8 @@ struct XAigerWriter if (!cell_known) keep_bits.insert(b); } + if (arrival) + arrival_times[b] = arrival; } } if (is_output) { @@ -362,6 +391,8 @@ struct XAigerWriter undriven_bits.erase(O); } } + + } } @@ -722,6 +753,9 @@ struct XAigerWriter int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + auto write_buffer_float = [](std::stringstream &buffer, float f32) { + buffer.write(reinterpret_cast(&f32), sizeof(f32)); + }; std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); @@ -806,13 +840,25 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + std::stringstream i_buffer; + auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); + for (auto i : input_bits) + write_i_buffer(arrival_times.at(i, 0)); + //std::stringstream o_buffer; + //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); + //for (auto o : output_bits) + // write_o_buffer(0); + std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); int mergeability_class = 1; - for (auto cell : ff_bits) + for (auto i : ff_bits) { write_r_buffer(mergeability_class++); + write_i_buffer(arrival_times.at(i, 0)); + //write_o_buffer(0); + } f << "r"; buffer_str = r_buffer.str(); @@ -820,6 +866,17 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + f << "i"; + buffer_str = i_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + //f << "o"; + //buffer_str = o_buffer.str(); + //buffer_size_be = to_big_endian(buffer_str.size()); + //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + //f.write(buffer_str.data(), buffer_str.size()); + std::stringstream s_buffer; auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); write_s_buffer(ff_bits.size()); -- cgit v1.2.3 From 45d4b33f0c2140d764a3a16b14286f6651fbbae6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 19 Aug 2019 13:17:31 -0700 Subject: Output i/o/h extensions even if no boxes or flops --- backends/aiger/xaiger.cc | 131 ++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 65 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6f91e34bd..2be88b884 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -344,25 +344,16 @@ struct XAigerWriter } } else { - bool cell_known = cell->known(); + bool cell_known = inst_module; for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto port_wire = inst_module->wire(c.first); - log_assert(port_wire); + auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; auto is_input = !cell_known || port_wire->port_input; auto is_output = !cell_known || port_wire->port_output; if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { - int arrival = 0; - auto it = port_wire->attributes.find("\\abc_arrival"); - if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); - arrival = it->second.as_int(); - } - for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -376,11 +367,19 @@ struct XAigerWriter if (!cell_known) keep_bits.insert(b); } - if (arrival) - arrival_times[b] = arrival; } } if (is_output) { + int arrival = 0; + if (port_wire) { + auto it = port_wire->attributes.find("\\abc_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); + arrival = it->second.as_int(); + } + } + for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -389,6 +388,9 @@ struct XAigerWriter if (O != b) alias_map[O] = b; undriven_bits.erase(O); + + if (arrival) + arrival_times[b] = arrival; } } @@ -748,29 +750,37 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { - auto write_buffer = [](std::stringstream &buffer, int i32) { - int32_t i32_be = to_big_endian(i32); - buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - auto write_buffer_float = [](std::stringstream &buffer, float f32) { - buffer.write(reinterpret_cast(&f32), sizeof(f32)); - }; - - std::stringstream h_buffer; - auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); - write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(ff_bits) + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_bits)); - write_h_buffer(input_bits.size() + ff_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_bits)); - write_h_buffer(output_bits.size() + ff_bits.size()); - log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); + auto write_buffer = [](std::stringstream &buffer, int i32) { + int32_t i32_be = to_big_endian(i32); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); + write_h_buffer(1); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(ff_bits) + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_bits)); + write_h_buffer(input_bits.size() + ff_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_bits)); + write_h_buffer(output_bits.size() + ff_bits.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); + write_h_buffer(box_list.size()); + + auto write_buffer_float = [](std::stringstream &buffer, float f32) { + buffer.write(reinterpret_cast(&f32), sizeof(f32)); + }; + std::stringstream i_buffer; + auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); + for (auto bit : input_bits) + write_i_buffer(arrival_times.at(bit, 0)); + //std::stringstream o_buffer; + //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); + //for (auto bit : output_bits) + // write_o_buffer(0); + if (!box_list.empty() || !ff_bits.empty()) { RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); @@ -834,48 +844,22 @@ struct XAigerWriter write_h_buffer(box_count++); } - f << "h"; - std::string buffer_str = h_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - - std::stringstream i_buffer; - auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); - for (auto i : input_bits) - write_i_buffer(arrival_times.at(i, 0)); - //std::stringstream o_buffer; - //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); - //for (auto o : output_bits) - // write_o_buffer(0); - std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); int mergeability_class = 1; - for (auto i : ff_bits) { + for (auto bit : ff_bits) { write_r_buffer(mergeability_class++); - write_i_buffer(arrival_times.at(i, 0)); + write_i_buffer(arrival_times.at(bit, 0)); //write_o_buffer(0); } f << "r"; - buffer_str = r_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - - f << "i"; - buffer_str = i_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); + std::string buffer_str = r_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - //f << "o"; - //buffer_str = o_buffer.str(); - //buffer_size_be = to_big_endian(buffer_str.size()); - //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - //f.write(buffer_str.data(), buffer_str.size()); std::stringstream s_buffer; auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); @@ -947,6 +931,23 @@ struct XAigerWriter } } + f << "h"; + std::string buffer_str = h_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + f << "i"; + buffer_str = i_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + //f << "o"; + //buffer_str = o_buffer.str(); + //buffer_size_be = to_big_endian(buffer_str.size()); + //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + //f.write(buffer_str.data(), buffer_str.size()); + f << stringf("Generated by %s\n", yosys_version_str); } -- cgit v1.2.3 From c00d72cdb30382d1e4d63f64e2b6ee2d1e312092 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 14:47:58 -0700 Subject: Minor refactor --- backends/aiger/xaiger.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2be88b884..ad2a778fa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -331,14 +331,15 @@ struct XAigerWriter } for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_input) { // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; + if (port_wire->port_output) continue; for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); } - if (cell->output(conn.first)) + if (port_wire->port_output) for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); } @@ -354,7 +355,7 @@ struct XAigerWriter log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { - for (auto b : c.second.bits()) { + for (auto b : sigmap(c.second)) { Wire *w = b.wire; if (!w) continue; if (!w->port_output || !cell_known) { @@ -380,7 +381,7 @@ struct XAigerWriter } } - for (auto b : c.second.bits()) { + for (auto b : sigmap(c.second)) { Wire *w = b.wire; if (!w) continue; input_bits.insert(b); @@ -393,8 +394,6 @@ struct XAigerWriter arrival_times[b] = arrival; } } - - } } -- cgit v1.2.3 From 1b5d2de1d4212bd93f9b0ca0d5173e4c8a4dd4e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 15:23:26 -0700 Subject: Do not sigmap! --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ad2a778fa..d02997da4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -355,7 +355,7 @@ struct XAigerWriter log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { - for (auto b : sigmap(c.second)) { + for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; if (!w->port_output || !cell_known) { @@ -381,7 +381,7 @@ struct XAigerWriter } } - for (auto b : sigmap(c.second)) { + for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; input_bits.insert(b); -- cgit v1.2.3 From 091bf4a18b2f4bf84fe62b61577c88d961468b3c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 18:16:37 -0700 Subject: Remove sequential extension --- backends/aiger/xaiger.cc | 299 +++++------------------------------------------ 1 file changed, 29 insertions(+), 270 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d02997da4..0d69e0f13 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -76,32 +76,25 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; - bool zinit_mode; SigMap sigmap; - dict init_map; pool input_bits, output_bits; - dict not_map, ff_map, alias_map; + dict not_map, alias_map; dict> and_map; vector> ci_bits; vector> co_bits; - vector ff_bits; dict arrival_times; vector> aig_gates; - vector aig_latchin, aig_latchinit, aig_outputs; + vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; dict ordered_outputs; - dict ordered_latches; vector box_list; bool omode = false; - //dict init_inputs; - //int initstate_ff = 0; - int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -144,7 +137,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -167,14 +160,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) - if (initval[i] == State::S0 || initval[i] == State::S1) - init_map[initsig[i]] = initval[i] == State::S1; - } - bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -218,12 +203,6 @@ struct XAigerWriter // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; - struct flop_data_t { - IdString d_port; - IdString q_port; - int q_arrival; - }; - dict flop_data; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -262,86 +241,25 @@ struct XAigerWriter log_assert(!holes_mode); - if (cell->type == "$__ABC_FF_") - { - SigBit D = sigmap(cell->getPort("\\D").as_bit()); - SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - alias_map[Q] = D; - continue; - } - RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; - toposort.node(cell->name); - - auto r = flop_data.insert(std::make_pair(cell->type, flop_data_t{IdString(), IdString(), 0})); - if (r.second && inst_module->attributes.count("\\abc_flop")) { - IdString &abc_flop_d = r.first->second.d_port; - IdString &abc_flop_q = r.first->second.q_port; - for (auto port_name : inst_module->ports) { - auto wire = inst_module->wire(port_name); - log_assert(wire); - if (wire->attributes.count("\\abc_flop_d")) { - if (abc_flop_d != IdString()) - log_error("More than one port has the 'abc_flop_d' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_d = port_name; - } - if (wire->attributes.count("\\abc_flop_q")) { - if (abc_flop_q != IdString()) - log_error("More than one port has the 'abc_flop_q' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_q = port_name; - - auto it = wire->attributes.find("\\abc_arrival"); - if (it != wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); - r.first->second.q_arrival = it->second.as_int(); - } + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_input) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_output) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } - } - if (abc_flop_d == IdString()) - log_error("'abc_flop_d' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - if (abc_flop_q == IdString()) - log_error("'abc_flop_q' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - } - - auto abc_flop_d = r.first->second.d_port; - if (abc_flop_d != IdString()) { - SigBit d = cell->getPort(abc_flop_d); - SigBit I = sigmap(d); - if (I != d) - alias_map[I] = d; - unused_bits.erase(d); - - auto abc_flop_q = r.first->second.q_port; - SigBit q = cell->getPort(abc_flop_q); - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - ff_bits.emplace_back(q); - - auto arrival = r.first->second.q_arrival; - if (arrival) - arrival_times[q] = arrival; - } - for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - if (port_wire->port_input) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_output) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } - - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); } } else { @@ -548,7 +466,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -564,7 +481,6 @@ struct XAigerWriter } not_map.sort(); - ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -576,77 +492,12 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto bit : ff_bits) { - aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; + aig_map[bit] = 2*aig_m; } - //if (zinit_mode) - //{ - // for (auto it : ff_map) { - // if (init_map.count(it.first)) - // continue; - // aig_m++, aig_i++; - // init_inputs[it.first] = 2*aig_m; - // } - //} - - //for (auto it : ff_map) { - // aig_m++, aig_l++; - // aig_map[it.first] = 2*aig_m; - // ordered_latches[it.first] = aig_l-1; - // if (init_map.count(it.first) == 0) - // aig_latchinit.push_back(2); - // else - // aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - //} - - //if (!init_inputs.empty()) { - // aig_m++, aig_l++; - // initstate_ff = 2*aig_m+1; - // aig_latchinit.push_back(0); - //} - - //if (zinit_mode) - //{ - // for (auto it : ff_map) - // { - // int l = ordered_latches[it.first]; - - // if (aig_latchinit.at(l) == 1) - // aig_map[it.first] ^= 1; - - // if (aig_latchinit.at(l) == 2) - // { - // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - // } - // } - //} - - //for (auto it : ff_map) { - // int a = bit2aig(it.second); - // int l = ordered_latches[it.first]; - // if (zinit_mode && aig_latchinit.at(l) == 1) - // aig_latchin.push_back(a ^ 1); - // else - // aig_latchin.push_back(a); - //} - - //if (!init_inputs.empty()) - // aig_latchin.push_back(1); - for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -658,11 +509,6 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto bit : ff_bits) { - aig_o++; - aig_outputs.push_back(ff_aig_map.at(bit)); - } - if (output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -677,8 +523,6 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); - log_assert(aig_l == GetSize(aig_latchin)); - log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -689,15 +533,6 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - //for (int i = 0; i < aig_l; i++) { - // if (zinit_mode || aig_latchinit.at(i) == 0) - // f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 1) - // f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 2) - // f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - //} - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -715,15 +550,6 @@ struct XAigerWriter } else { - //for (int i = 0; i < aig_l; i++) { - // if (zinit_mode || aig_latchinit.at(i) == 0) - // f << stringf("%d\n", aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 1) - // f << stringf("%d 1\n", aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 2) - // f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - //} - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -756,14 +582,14 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(ff_bits) + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_bits)); - write_h_buffer(input_bits.size() + ff_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_bits)); - write_h_buffer(output_bits.size() + ff_bits.size()); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); log_debug("boxNum = %d\n", GetSize(box_list)); write_h_buffer(box_list.size()); @@ -779,7 +605,7 @@ struct XAigerWriter //for (auto bit : output_bits) // write_o_buffer(0); - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); @@ -845,41 +671,13 @@ struct XAigerWriter std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %d\n", GetSize(ff_bits)); - write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto bit : ff_bits) { - write_r_buffer(mergeability_class++); - write_i_buffer(arrival_times.at(bit, 0)); - //write_o_buffer(0); - } - + write_r_buffer(0); f << "r"; std::string buffer_str = r_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - std::stringstream s_buffer; - auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); - write_s_buffer(ff_bits.size()); - for (auto bit : ff_bits) { - auto it = bit.wire->attributes.find("\\init"); - if (it != bit.wire->attributes.end()) { - auto init = it->second[bit.offset]; - if (init == RTLIL::S1) { - write_s_buffer(1); - continue; - } - } - write_s_buffer(0); - } - f << "s"; - buffer_str = s_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - if (holes_module) { log_push(); @@ -915,7 +713,7 @@ struct XAigerWriter Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; @@ -953,9 +751,7 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; - dict init_lines; dict output_lines; - dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -976,30 +772,10 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - int init = 2; - auto it = init_map.find(b); - if (it != init_map.end()) - init = it->second ? 1 : 0; - output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); + output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire)); continue; } - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - // continue; - //} - - //if (ordered_latches.count(sig[i])) { - // int l = ordered_latches.at(sig[i]); - // if (zinit_mode && (aig_latchinit.at(l) == 1)) - // latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - // else - // latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - // continue; - //} - if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; @@ -1015,10 +791,6 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); - init_lines.sort(); - for (auto &it : init_lines) - f << it.second; - int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); @@ -1030,10 +802,6 @@ struct XAigerWriter if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 $__dummy__\n"; - latch_lines.sort(); - for (auto &it : latch_lines) - f << it.second; - wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -1054,10 +822,6 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); - log(" -zinit\n"); - log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); - log(" uninitialized FFs.\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -1068,7 +832,6 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -1081,10 +844,6 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } - if (args[argidx] == "-zinit") { - zinit_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1103,7 +862,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From 7b646101e936cacd20938c20ddfbaa63ee268fb2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 20:57:13 -0700 Subject: Only xaig if GetSize(output_bits) > 0 --- backends/aiger/xaiger.cc | 296 ++++++++++++++++++++++++----------------------- 1 file changed, 149 insertions(+), 147 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0d69e0f13..c1ab59600 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -575,175 +575,177 @@ struct XAigerWriter f << "c"; - auto write_buffer = [](std::stringstream &buffer, int i32) { - int32_t i32_be = to_big_endian(i32); - buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - std::stringstream h_buffer; - auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); - write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); - log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); - - auto write_buffer_float = [](std::stringstream &buffer, float f32) { - buffer.write(reinterpret_cast(&f32), sizeof(f32)); - }; - std::stringstream i_buffer; - auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); - for (auto bit : input_bits) - write_i_buffer(arrival_times.at(bit, 0)); - //std::stringstream o_buffer; - //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); - //for (auto bit : output_bits) - // write_o_buffer(0); - - if (!box_list.empty()) { - RTLIL::Module *holes_module = module->design->addModule("$__holes__"); - log_assert(holes_module); - - int port_id = 1; - int box_count = 0; - for (auto cell : box_list) { - RTLIL::Module* box_module = module->design->module(cell->type); - int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) { - holes_cell = holes_module->addCell(cell->name, cell->type); - holes_cell->parameters = cell->parameters; - } + if (GetSize(output_bits) > 0) { + auto write_buffer = [](std::stringstream &buffer, int i32) { + int32_t i32_be = to_big_endian(i32); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); + write_h_buffer(1); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); + write_h_buffer(box_list.size()); + + auto write_buffer_float = [](std::stringstream &buffer, float f32) { + buffer.write(reinterpret_cast(&f32), sizeof(f32)); + }; + std::stringstream i_buffer; + auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); + for (auto bit : input_bits) + write_i_buffer(arrival_times.at(bit, 0)); + //std::stringstream o_buffer; + //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); + //for (auto bit : output_bits) + // write_o_buffer(0); + + if (!box_list.empty()) { + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); + log_assert(holes_module); + + int port_id = 1; + int box_count = 0; + for (auto cell : box_list) { + RTLIL::Module* box_module = module->design->module(cell->type); + int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) { + holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (const auto &port_name : box_module->ports) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_wire; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + if (holes_cell) + port_wire.append(holes_wire); + } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, State::S0); } - if (holes_cell) - port_wire.append(holes_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); } - if (w->port_output) { - box_outputs += GetSize(w); - for (int i = 0; i < GetSize(w); i++) { - if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); - else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); - holes_wire->port_output = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - if (holes_cell) - port_wire.append(holes_wire); - else - holes_module->connect(holes_wire, State::S0); - } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); - } - } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(box_count++); - } + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); + write_h_buffer(box_count++); + } - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - write_r_buffer(0); - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + write_r_buffer(0); + f << "r"; + std::string buffer_str = r_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); - if (holes_module) { - log_push(); + if (holes_module) { + log_push(); - // NB: fixup_ports() will sort ports by name - //holes_module->fixup_ports(); - holes_module->check(); + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); - holes_module->design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = holes_module->design->selection_stack.back(); - sel.select(holes_module); + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); - // TODO: Should not need to opt_merge if we only instantiate - // each box type once... - Pass::call(holes_module->design, "opt_merge -share_all"); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb"); + Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); - for (auto cell : holes_module->cells()) - if (!cell->type.in("$_NOT_", "$_AND_")) - log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call + Pass::call(holes_module->design, "techmap"); + Pass::call(holes_module->design, "aigmap"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - holes_module->design->selection_stack.pop_back(); + holes_module->design->selection_stack.pop_back(); - // Move into a new (temporary) design so that "clean" will only - // operate (and run checks on) this one module - RTLIL::Design *holes_design = new RTLIL::Design; - holes_module->design->modules_.erase(holes_module->name); - holes_design->add(holes_module); - Pass::call(holes_design, "clean -purge"); + // Move into a new (temporary) design so that "clean" will only + // operate (and run checks on) this one module + RTLIL::Design *holes_design = new RTLIL::Design; + holes_module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "clean -purge"); - std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/); + std::stringstream a_buffer; + XAigerWriter writer(holes_module, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/); - delete holes_design; + delete holes_design; - f << "a"; - std::string buffer_str = a_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + f << "a"; + std::string buffer_str = a_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); - log_pop(); + log_pop(); + } } - } - f << "h"; - std::string buffer_str = h_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - - f << "i"; - buffer_str = i_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - //f << "o"; - //buffer_str = o_buffer.str(); - //buffer_size_be = to_big_endian(buffer_str.size()); - //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - //f.write(buffer_str.data(), buffer_str.size()); + f << "h"; + std::string buffer_str = h_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + f << "i"; + buffer_str = i_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + //f << "o"; + //buffer_str = o_buffer.str(); + //buffer_size_be = to_big_endian(buffer_str.size()); + //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + //f.write(buffer_str.data(), buffer_str.size()); + } f << stringf("Generated by %s\n", yosys_version_str); } -- cgit v1.2.3 From 4d123b7638b7036da70de169d16d2ae21b89b8e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 21:22:38 -0700 Subject: Revert "Only xaig if GetSize(output_bits) > 0" This reverts commit 7b646101e936cacd20938c20ddfbaa63ee268fb2. --- backends/aiger/xaiger.cc | 296 +++++++++++++++++++++++------------------------ 1 file changed, 147 insertions(+), 149 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c1ab59600..0d69e0f13 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -575,178 +575,176 @@ struct XAigerWriter f << "c"; - if (GetSize(output_bits) > 0) { - auto write_buffer = [](std::stringstream &buffer, int i32) { - int32_t i32_be = to_big_endian(i32); - buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - std::stringstream h_buffer; - auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); - write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); - log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); - - auto write_buffer_float = [](std::stringstream &buffer, float f32) { - buffer.write(reinterpret_cast(&f32), sizeof(f32)); - }; - std::stringstream i_buffer; - auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); - for (auto bit : input_bits) - write_i_buffer(arrival_times.at(bit, 0)); - //std::stringstream o_buffer; - //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); - //for (auto bit : output_bits) - // write_o_buffer(0); - - if (!box_list.empty()) { - RTLIL::Module *holes_module = module->design->addModule("$__holes__"); - log_assert(holes_module); - - int port_id = 1; - int box_count = 0; - for (auto cell : box_list) { - RTLIL::Module* box_module = module->design->module(cell->type); - int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) { - holes_cell = holes_module->addCell(cell->name, cell->type); - holes_cell->parameters = cell->parameters; - } + auto write_buffer = [](std::stringstream &buffer, int i32) { + int32_t i32_be = to_big_endian(i32); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); + write_h_buffer(1); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); + write_h_buffer(box_list.size()); + + auto write_buffer_float = [](std::stringstream &buffer, float f32) { + buffer.write(reinterpret_cast(&f32), sizeof(f32)); + }; + std::stringstream i_buffer; + auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1); + for (auto bit : input_bits) + write_i_buffer(arrival_times.at(bit, 0)); + //std::stringstream o_buffer; + //auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1); + //for (auto bit : output_bits) + // write_o_buffer(0); + + if (!box_list.empty()) { + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); + log_assert(holes_module); + + int port_id = 1; + int box_count = 0; + for (auto cell : box_list) { + RTLIL::Module* box_module = module->design->module(cell->type); + int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) { + holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (const auto &port_name : box_module->ports) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_wire; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - if (holes_cell) - port_wire.append(holes_wire); - } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); - } - if (w->port_output) { - box_outputs += GetSize(w); - for (int i = 0; i < GetSize(w); i++) { - if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); - else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); - holes_wire->port_output = true; + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); - if (holes_cell) - port_wire.append(holes_wire); - else - holes_module->connect(holes_wire, State::S0); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); + if (holes_cell) + port_wire.append(holes_wire); } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, State::S0); + } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } - - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(box_count++); } - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - write_r_buffer(0); - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - - if (holes_module) { - log_push(); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); + write_h_buffer(box_count++); + } - // NB: fixup_ports() will sort ports by name - //holes_module->fixup_ports(); - holes_module->check(); + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + write_r_buffer(0); + f << "r"; + std::string buffer_str = r_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); - holes_module->design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = holes_module->design->selection_stack.back(); - sel.select(holes_module); + if (holes_module) { + log_push(); - // TODO: Should not need to opt_merge if we only instantiate - // each box type once... - Pass::call(holes_module->design, "opt_merge -share_all"); + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); - Pass::call(holes_module->design, "flatten -wb"); + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); - for (auto cell : holes_module->cells()) - if (!cell->type.in("$_NOT_", "$_AND_")) - log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); - holes_module->design->selection_stack.pop_back(); + Pass::call(holes_module->design, "flatten -wb"); - // Move into a new (temporary) design so that "clean" will only - // operate (and run checks on) this one module - RTLIL::Design *holes_design = new RTLIL::Design; - holes_module->design->modules_.erase(holes_module->name); - holes_design->add(holes_module); - Pass::call(holes_design, "clean -purge"); + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call + Pass::call(holes_module->design, "techmap"); + Pass::call(holes_module->design, "aigmap"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/); + holes_module->design->selection_stack.pop_back(); - delete holes_design; + // Move into a new (temporary) design so that "clean" will only + // operate (and run checks on) this one module + RTLIL::Design *holes_design = new RTLIL::Design; + holes_module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "clean -purge"); - f << "a"; - std::string buffer_str = a_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + std::stringstream a_buffer; + XAigerWriter writer(holes_module, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/); - log_pop(); - } - } + delete holes_design; - f << "h"; - std::string buffer_str = h_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + f << "a"; + std::string buffer_str = a_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); - f << "i"; - buffer_str = i_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - //f << "o"; - //buffer_str = o_buffer.str(); - //buffer_size_be = to_big_endian(buffer_str.size()); - //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - //f.write(buffer_str.data(), buffer_str.size()); + log_pop(); + } } + f << "h"; + std::string buffer_str = h_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + f << "i"; + buffer_str = i_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + //f << "o"; + //buffer_str = o_buffer.str(); + //buffer_size_be = to_big_endian(buffer_str.size()); + //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + //f.write(buffer_str.data(), buffer_str.size()); + f << stringf("Generated by %s\n", yosys_version_str); } -- cgit v1.2.3 From 8182cb9d91555d5be52abbfeeb5d22af05342d8a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 21:30:16 -0700 Subject: Fix omode which inserts an output if none exists (otherwise abc9 breaks) --- backends/aiger/xaiger.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0d69e0f13..8c8ff2f7e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -504,16 +504,16 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + if (output_bits.empty()) { + output_bits.insert(State::S0); + omode = true; + } + for (auto bit : output_bits) { ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - if (output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - omode = true; - } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -575,6 +575,7 @@ struct XAigerWriter f << "c"; + log_assert(!output_bits.empty()); auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -796,11 +797,11 @@ struct XAigerWriter f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); output_lines.sort(); + if (omode) + output_lines[State::S0] = "output 0 0 $__dummy__\n"; for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From 8f0c1232d7c511a6473f4581e4c27a90088cedb7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 11:29:40 -0700 Subject: Revert "Fix omode which inserts an output if none exists (otherwise abc9 breaks)" This reverts commit 8182cb9d91555d5be52abbfeeb5d22af05342d8a. --- backends/aiger/xaiger.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8c8ff2f7e..0d69e0f13 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -504,16 +504,16 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (output_bits.empty()) { - output_bits.insert(State::S0); - omode = true; - } - for (auto bit : output_bits) { ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } + if (output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + omode = true; + } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -575,7 +575,6 @@ struct XAigerWriter f << "c"; - log_assert(!output_bits.empty()); auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -797,11 +796,11 @@ struct XAigerWriter f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); output_lines.sort(); - if (omode) - output_lines[State::S0] = "output 0 0 $__dummy__\n"; for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + if (omode && output_bits.empty()) + f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From 399ac760ff2bf4a7d438ed388820e7bfb511de6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 11:31:18 -0700 Subject: Output "h" extension only if boxes --- backends/aiger/xaiger.cc | 60 ++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 28 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0d69e0f13..b66706ffa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -575,24 +575,6 @@ struct XAigerWriter f << "c"; - auto write_buffer = [](std::stringstream &buffer, int i32) { - int32_t i32_be = to_big_endian(i32); - buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - std::stringstream h_buffer; - auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); - write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); - log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); - auto write_buffer_float = [](std::stringstream &buffer, float f32) { buffer.write(reinterpret_cast(&f32), sizeof(f32)); }; @@ -606,6 +588,24 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty()) { + auto write_buffer = [](std::stringstream &buffer, int i32) { + int32_t i32_be = to_big_endian(i32); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); + write_h_buffer(1); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); + write_h_buffer(box_list.size()); + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); @@ -669,12 +669,18 @@ struct XAigerWriter write_h_buffer(box_count++); } + f << "h"; + std::string buffer_str = h_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); write_r_buffer(0); f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); + buffer_str = r_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); @@ -727,16 +733,14 @@ struct XAigerWriter log_pop(); } } - - f << "h"; - std::string buffer_str = h_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + else { + log_debug("piNum = %d\n", GetSize(input_bits)); + log_debug("poNum = %d\n", GetSize(output_bits)); + } f << "i"; - buffer_str = i_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); + std::string buffer_str = i_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); //f << "o"; -- cgit v1.2.3 From 082a01954b95f50cb0ab1b2a1105c06391c0b1b4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 17:30:54 -0700 Subject: Revert "Output "h" extension only if boxes" This reverts commit 399ac760ff2bf4a7d438ed388820e7bfb511de6b. --- backends/aiger/xaiger.cc | 60 ++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b66706ffa..0d69e0f13 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -575,6 +575,24 @@ struct XAigerWriter f << "c"; + auto write_buffer = [](std::stringstream &buffer, int i32) { + int32_t i32_be = to_big_endian(i32); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); + write_h_buffer(1); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits)); + write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits)); + write_h_buffer(output_bits.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); + write_h_buffer(box_list.size()); + auto write_buffer_float = [](std::stringstream &buffer, float f32) { buffer.write(reinterpret_cast(&f32), sizeof(f32)); }; @@ -588,24 +606,6 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty()) { - auto write_buffer = [](std::stringstream &buffer, int i32) { - int32_t i32_be = to_big_endian(i32); - buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - std::stringstream h_buffer; - auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); - write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); - log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); - RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); @@ -669,18 +669,12 @@ struct XAigerWriter write_h_buffer(box_count++); } - f << "h"; - std::string buffer_str = h_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); write_r_buffer(0); f << "r"; - buffer_str = r_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); + std::string buffer_str = r_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); @@ -733,16 +727,18 @@ struct XAigerWriter log_pop(); } } - else { - log_debug("piNum = %d\n", GetSize(input_bits)); - log_debug("poNum = %d\n", GetSize(output_bits)); - } - f << "i"; - std::string buffer_str = i_buffer.str(); + f << "h"; + std::string buffer_str = h_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + + f << "i"; + buffer_str = i_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); //f << "o"; //buffer_str = o_buffer.str(); //buffer_size_be = to_big_endian(buffer_str.size()); -- cgit v1.2.3 From 3247442bf9b1f5b672a360b1fc55af9170d000c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 17:34:00 -0700 Subject: Revert "Revert "Fix omode which inserts an output if none exists (otherwise abc9 breaks)"" This reverts commit 8f0c1232d7c511a6473f4581e4c27a90088cedb7. --- backends/aiger/xaiger.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0d69e0f13..8c8ff2f7e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -504,16 +504,16 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + if (output_bits.empty()) { + output_bits.insert(State::S0); + omode = true; + } + for (auto bit : output_bits) { ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - if (output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - omode = true; - } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -575,6 +575,7 @@ struct XAigerWriter f << "c"; + log_assert(!output_bits.empty()); auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -796,11 +797,11 @@ struct XAigerWriter f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); output_lines.sort(); + if (omode) + output_lines[State::S0] = "output 0 0 $__dummy__\n"; for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From e9bb252e77ba979a4c7041e6a221862a6464bf99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 20:15:09 -0700 Subject: Recognise built-in types (e.g. $_DFF_*) --- backends/aiger/xaiger.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8c8ff2f7e..fa6ba0aca 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -263,12 +263,12 @@ struct XAigerWriter } } else { - bool cell_known = inst_module; + bool cell_known = inst_module || cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; - auto is_input = !cell_known || port_wire->port_input; - auto is_output = !cell_known || port_wire->port_output; + auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); + auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); -- cgit v1.2.3 From c1b628508d54eb0ab6e5c9559063330a409d0a51 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 8 Sep 2019 15:47:09 +0800 Subject: backends: smt2: use $(CXX) variable for compiler The Makefile assumes the compiler is called `gcc`, which isn't always true. In fact, if we're building on msys2 or msys2-64, the compiler is called `i686-w64-mingw32-g++` or `x86_64-w64-mingw32-g++`. Use the variable instead of hardcoding the name, to fix building on these systems. Signed-off-by: Sean Cross --- backends/smt2/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc index 92941d4cf..68394a909 100644 --- a/backends/smt2/Makefile.inc +++ b/backends/smt2/Makefile.inc @@ -16,7 +16,7 @@ yosys-smtbmc-script.py: backends/smt2/smtbmc.py -e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@ yosys-smtbmc.exe: misc/launcher.c yosys-smtbmc-script.py - $(P) gcc -DGUI=0 -O -s -o $@ $< + $(P) $(CXX) -DGUI=0 -O -s -o $@ $< # Other targets else TARGETS += yosys-smtbmc -- cgit v1.2.3 From b88d2e5f30712f797a5c4fb2b7308494155b95d0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 18 Sep 2019 11:56:14 +0200 Subject: Fix stupid bug in btor back-end Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 7c054d655..4472993d4 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -685,7 +685,7 @@ struct BtorWorker } else { - int nid_init_val = next_nid++; + nid_init_val = next_nid++; btorf("%d state %d\n", nid_init_val, sid); for (int i = 0; i < nwords; i++) { -- cgit v1.2.3 From 779ce3537fa921daf6ffd780264f0867a8ebc4be Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 18 Sep 2019 13:33:02 +0200 Subject: Add "write_aiger -L" Signed-off-by: Clifford Wolf --- backends/aiger/aiger.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'backends') diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 7c851bb91..0798fb35d 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -101,7 +101,7 @@ struct AigerWriter return a; } - AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool lmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -367,6 +367,12 @@ struct AigerWriter aig_latchin.push_back(a); } + if (lmode && aig_l == 0) { + aig_m++, aig_l++; + aig_latchinit.push_back(0); + aig_latchin.push_back(0); + } + if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); @@ -704,9 +710,9 @@ struct AigerBackend : public Backend { log(" -vmap \n"); log(" like -map, but more verbose\n"); log("\n"); - log(" -I, -O, -B\n"); - log(" If the design contains no input/output/assert then create one\n"); - log(" dummy input/output/bad_state pin to make the tools reading the\n"); + log(" -I, -O, -B, -L\n"); + log(" If the design contains no input/output/assert/flip-flop then create one\n"); + log(" dummy input/output/bad_state-pin or latch to make the tools reading the\n"); log(" AIGER file happy.\n"); log("\n"); } @@ -720,6 +726,7 @@ struct AigerBackend : public Backend { bool imode = false; bool omode = false; bool bmode = false; + bool lmode = false; std::string map_filename; log_header(design, "Executing AIGER backend.\n"); @@ -764,6 +771,10 @@ struct AigerBackend : public Backend { bmode = true; continue; } + if (args[argidx] == "-L") { + lmode = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -773,7 +784,7 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { -- cgit v1.2.3